2011-09-03 159 views
1

的equivilant我處理,其具有包含文本複製到一個純文本文件<paragraph>標籤的XML文檔。有時線條在奇怪的地方被打破,有時它們太長。我有一個簡單的運行apply-template動作的段落模板,並附加了幾行換行符。XSL爲文本,「格式化」

有沒有辦法來重新格式化類似於UNIX「FMT」命令項(其中文本的流rewraps歸一化的寬度)文本()後的申請模板有機會處理其他段落內的標籤(如粗體,時間等)。

此外,有沒有爲每個格式化行縮進的方式,因爲你通常會在一個塊引用做一個純文本文件?

+0

不要指望很多人知道「unix'fmt'」是幹什麼的。請提供一個(小)XML文檔的完整示例,確切的期望輸出以及轉換應實現的規則。 –

+0

好問題,+1。請參閱我的答案,瞭解使用FXSL模板「str-split-to-lines」的簡單XSLT 1.0解決方案。 –

+0

所以,@JeffG,我的回答有用嗎? –

回答

1

一個簡單的解決辦法是使用str-split-to-lines模板從FXSL這樣

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:f="http://fxsl.sf.net/" 
xmlns:ext="http://exslt.org/common" 
xmlns:str-split2lines-func="f:str-split2lines-func" 
exclude-result-prefixes="xsl f ext str-split2lines-func" 
> 


    <xsl:import href="dvc-str-foldl.xsl"/> 

    <str-split2lines-func:str-split2lines-func/> 

    <xsl:output indent="yes" omit-xml-declaration="yes"/> 

    <xsl:template match="/"> 
     <xsl:call-template name="str-split-to-lines"> 
     <xsl:with-param name="pStr" select="/*"/> 
     <xsl:with-param name="pLineLength" select="50"/> 
     <xsl:with-param name="pDelimiters" select="' &#9;&#10;&#13;'"/> 
     </xsl:call-template> 
    </xsl:template> 

    <xsl:template name="str-split-to-lines"> 
     <xsl:param name="pStr"/> 
     <xsl:param name="pLineLength" select="60"/> 
     <xsl:param name="pDelimiters" select="' &#9;&#10;&#13;'"/> 

     <xsl:variable name="vsplit2linesFun" 
        select="document('')/*/str-split2lines-func:*[1]"/> 

     <xsl:variable name="vrtfParams"> 
     <delimiters><xsl:value-of select="$pDelimiters"/></delimiters> 
     <lineLength><xsl:copy-of select="$pLineLength"/></lineLength> 
     </xsl:variable> 

     <xsl:variable name="vResult"> 
      <xsl:call-template name="dvc-str-foldl"> 
      <xsl:with-param name="pFunc" select="$vsplit2linesFun"/> 
      <xsl:with-param name="pStr" select="$pStr"/> 
      <xsl:with-param name="pA0" select="ext:node-set($vrtfParams)"/> 
      </xsl:call-template> 
     </xsl:variable> 

     <xsl:for-each select="ext:node-set($vResult)/line"> 
     <xsl:for-each select="word"> 
      <xsl:value-of select="concat(., ' ')"/> 
     </xsl:for-each> 
     <xsl:value-of select="'&#xA;'"/> 
     </xsl:for-each> 
    </xsl:template> 

    <xsl:template match="str-split2lines-func:*" mode="f:FXSL"> 
     <xsl:param name="arg1" select="/.."/> 
     <xsl:param name="arg2"/> 

     <xsl:copy-of select="$arg1/*[position() &lt; 3]"/> 
     <xsl:copy-of select="$arg1/line[position() != last()]"/> 

     <xsl:choose> 
     <xsl:when test="contains($arg1/*[1], $arg2)"> 
      <xsl:if test="string($arg1/word)"> 
      <xsl:call-template name="fillLine"> 
       <xsl:with-param name="pLine" select="$arg1/line[last()]"/> 
       <xsl:with-param name="pWord" select="$arg1/word"/> 
       <xsl:with-param name="pLineLength" select="$arg1/*[2]"/> 
      </xsl:call-template> 
      </xsl:if> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:copy-of select="$arg1/line[last()]"/> 
      <word><xsl:value-of select="concat($arg1/word, $arg2)"/></word> 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 

     <!-- Test if the new word fits into the last line --> 
    <xsl:template name="fillLine"> 
     <xsl:param name="pLine" select="/.."/> 
     <xsl:param name="pWord" select="/.."/> 
     <xsl:param name="pLineLength" /> 

     <xsl:variable name="vnWordsInLine" select="count($pLine/word)"/> 
     <xsl:variable name="vLineLength" 
     select="string-length($pLine) + $vnWordsInLine"/> 
     <xsl:choose> 
     <xsl:when test="not($vLineLength + string-length($pWord) 
          > 
          $pLineLength)"> 
      <line> 
      <xsl:copy-of select="$pLine/*"/> 
      <xsl:copy-of select="$pWord"/> 
      </line> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:copy-of select="$pLine"/> 
      <line> 
      <xsl:copy-of select="$pWord"/> 
      </line> 
      <word/> 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 

</xsl:stylesheet> 

當這種轉變是在一個XML文檔應用這樣一個

<text> 
Dec. 13 — As always for a presidential inaugural, security and surveillance were 
extremely tight in Washington, DC, last January. But as George W. Bush prepared to 
take the oath of office, security planners installed an extra layer of protection: a 
prototype software system to detect a biological attack. The U.S. Department of 
Defense, together with regional health and emergency-planning agencies, distributed 
a special patient-query sheet to military clinics, civilian hospitals and even aid 
stations along the parade route and at the inaugural balls. Software quickly 
analyzed complaints of seven key symptoms — from rashes to sore throats — for 
patterns that might indicate the early stages of a bio-attack. There was a brief 
scare: the system noticed a surge in flulike symptoms at military clinics. 
Thankfully, tests confirmed it was just that — the flu. 
</text> 

需要的輸出(包裝成最大寬度爲50的文字)

Dec. 13 — As always for a presidential inaugural, 
security and surveillance were extremely tight in 
Washington, DC, last January. But as George W. 
Bush prepared to take the oath of office, security 
planners installed an extra layer of protection: a 
prototype software system to detect a biological 
attack. The U.S. Department of Defense, together 
with regional health and emergency-planning 
agencies, distributed a special patient-query 
sheet to military clinics, civilian hospitals and 
even aid stations along the parade route and at 
the inaugural balls. Software quickly analyzed 
complaints of seven key symptoms — from rashes to 
sore throats — for patterns that might indicate 
the early stages of a bio-attack. There was a 
brief scare: the system noticed a surge in flulike 
symptoms at military clinics. Thankfully, tests 
confirmed it was just that — the flu. 
+0

非常有幫助。謝謝。 – JeffG

+0

@JeffG:不客氣。 –