2011-09-03 78 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:不客气。 –