String 在XSLT中,如何将元素的文本内容拆分为行?

String 在XSLT中,如何将元素的文本内容拆分为行?,string,xslt,character,String,Xslt,Character,我正在使用XSLT解析XML元素的文本内容。此文本包含换行符,但我似乎无法正确解析它们。我正在使用我在网上找到的代码来切碎文本。这是代码的相关部分 <xsl:variable name="first"> <xsl:value-of select="substring-before($source, $newline)"/> </xsl:variable> <xsl:variable name="rest"> <xsl:value-of

我正在使用XSLT解析XML元素的文本内容。此文本包含换行符,但我似乎无法正确解析它们。我正在使用我在网上找到的代码来切碎文本。这是代码的相关部分

<xsl:variable name="first">
  <xsl:value-of select="substring-before($source, $newline)"/>
</xsl:variable>
<xsl:variable name="rest">
  <xsl:value-of select="substring-after($source, $newline)"/>
</xsl:variable>

这是将$rest推入自身的RecurSrive模板的一部分

问题是代码示例没有定义$newline。 如果我将$newline设置为一个字母,如“s”,则文本会很好地分开(例如,它会将输入“响亮”变成“re”和“ounding”)。但是,当我尝试将$newline设置为换行符时,即

和#xa0,它将永远递归并导致堆栈溢出。我还尝试为换行符定义一个实体,但没有任何区别

输入在每行的末尾都有普通的CR/LF(我在一个Windows框上)

有人知道我做错了什么,或者建议一种方法吗

谢谢,
Mathijs

我曾经使用过这个模板。它是一个命名模板,因此您可以随时调用它。此处的文本分为70个字符:

<xsl:template name="Texts">
    <xsl:param name="string" select="TEXTITEM" />
    <xsl:param name="line-length" select="70"/>
    <xsl:variable name="line" select="substring($string,1,$line-length)"/>
    <xsl:variable name="rest" select="substring($string, $line-length+1)"/>
    <xsl:if test="$line">
        <MYTEXT> 
            <xsl:value-of select="$line"/>  
        </MYTEXT> 
    </xsl:if>
    <xsl:if test="$rest">
        <xsl:call-template name="Texts">
            <xsl:with-param name="string" select="$rest"/>
            <xsl:with-param name="line-length" select="$line-length"/>
        </xsl:call-template>
    </xsl:if>   
</xsl:template>

让我知道它是否适合你

问候,,
Peter

如果可以使用EXSLT,请尝试使用

或者与XSLT 2.0类似:

<xsl:for-each select="tokenize($source, $newline)">
  <xsl:sequence select="."/>
  <xsl:text>&#x0a;</xsl:text>
</xsl:for-each>

您可以使用以下选项

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="/">
        <root>
            <xsl:for-each select="root/str">
                <str>
                    <xsl:call-template name="strSplit">
                        <xsl:with-param name="str" select="."/>
                        <xsl:with-param name="seqno" select="1"/>
                    </xsl:call-template>
                </str>
            </xsl:for-each>
        </root>
   </xsl:template>

    <xsl:template name="strSplit">
        <xsl:param name="str"/>
        <xsl:param name="seqno"/>

        <xsl:variable name="afterLeadingWS"
            select="substring-after($str, substring-before($str,substring-before(normalize-space($str), ' ')))"/>

        <xsl:choose>
            <xsl:when test="contains($afterLeadingWS, '&#xA;')">
                <line>
                    <xsl:attribute name="seqno"><xsl:value-of select="$seqno"/></xsl:attribute>
                    <xsl:attribute name="length"><xsl:value-of select="string-length(substring-before($afterLeadingWS, '&#xA;'))"/></xsl:attribute>
                    <xsl:value-of select="substring-before($afterLeadingWS, '&#xA;')"/>
                </line>
                <xsl:call-template name="strSplit">
                    <xsl:with-param name="str" select="substring-after($afterLeadingWS, '&#xA;')"/>
                    <xsl:with-param name="seqno" select="$seqno + 1"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <line>
                    <xsl:attribute name="seqno"><xsl:value-of select="$seqno"/></xsl:attribute>
                    <xsl:value-of select="$afterLeadingWS"/>
                </line>
            </xsl:otherwise>
        </xsl:choose>
   </xsl:template>
</xsl:stylesheet>

适用于

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <str>
        yigifgniuq  h 
        eukwgf kuew hgk.uhgku
        ,/v.,silghouihhg
    </str>
    <str>
        09734ymmnyr n.0808
        o149013483ymr7rg
        738924m c0 

    </str>
</root>

伊吉格尼乌克h
eukwgf kuew hgk.uhgku
,/v.,锡尔古伊
09734ymmnyr n.0808
o149013483ymr7rg
738924m二氧化碳
输出结果为

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <str>
        <line seqno="1" length="13">yigifgniuq  h </line>
        <line seqno="2" length="21">eukwgf kuew hgk.uhgku</line>
        <line seqno="3" length="18">        ,/v.,silghouihhg</line>
        <line seqno="4">    </line>
    </str>
    <str>
        <line seqno="1" length="18">09734ymmnyr n.0808</line>
        <line seqno="2" length="16">o149013483ymr7rg</line>
        <line seqno="3" length="11">738924m c0 </line>
        <line seqno="4" length="2">     </line>
        <line seqno="5">    </line>
    </str>
</root>

伊吉格尼乌克h
eukwgf kuew hgk.uhgku
,/v.,锡尔古伊
09734ymmnyr n.0808
o149013483ymr7rg
738924m二氧化碳

请注意,前面的制表符(或空格)被视为线条的一部分。

Maestro13的回答让我与他最接近,我最终将我拥有的模板与他合并,生成了这个,我在这里为后代分享。它是一个模板,返回传递给它的字符串中最长行的长度

<xsl:template name="longestCodeLine">
    <xsl:param name="str"/>

    <xsl:choose>
    <!-- Is this the last line? -->
    <xsl:when test="contains($str, '&#xA;')">
        <!-- No. First isolate all remaining lines, and recurse to find its longest line. -->
        <xsl:variable name="bestOfTheRest">
            <xsl:call-template name="longestCodeLine">
                <xsl:with-param name="str" select="substring-after($str, '&#xA;')"/>                        
            </xsl:call-template>
        </xsl:variable>
        <xsl:choose>
            <!-- Compare the longest of the remaining lines to this one. Which one's longer? -->
            <!-- If the longest of the remaining lines is longer, return that line. -->
            <xsl:when test="string-length($bestOfTheRest) &gt; string-length(substring-before($str, '&#xA;'))">
                <xsl:value-of select="$bestOfTheRest"/>
            </xsl:when>
            <!-- If this line longer, return this line. -->
            <xsl:otherwise>
                <xsl:value-of select="substring-before($str, '&#xA;')"/>
            </xsl:otherwise>
        </xsl:choose>
            </xsl:when>
    <!-- If there are no \n's left, this is your last string. So it is by definition the longest one left. -->
    <xsl:otherwise>
        <xsl:value-of select="$str"/>
    </xsl:otherwise>
    </xsl:choose>   
</xsl:template>

我想我应该添加一个行分割代码,在空白后添加换行符

<xsl:function name="kode:splitLongLine">
  <xsl:param name="string"/>
  <xsl:variable name="regex">
   <xsl:text>(((.){1,55})( |$))</xsl:text>
  </xsl:variable>

  <xsl:variable name="result">
   <xsl:analyze-string select="$string" regex="{$regex}">
    <xsl:matching-substring>
     <xsl:value-of select="concat(regex-group(1),'&#10;')"/>
    </xsl:matching-substring>
    <xsl:non-matching-substring>
     <xsl:value-of select="concat('REPORT ERROR: ', .)"/>
    </xsl:non-matching-substring>
   </xsl:analyze-string>
  </xsl:variable>

  <xsl:sequence select="$result"/>
 </xsl:function>

(((.){1,55})( |$))

对不起,我忘了提到新行字符:尝试使用“0x0d 0x0a”,它是ASCII CR+LF。所以$newline=“0x0d 0x0a”祝你好运,彼得这是把它切成等长的块,这不是我需要的。我真正想要实现的是找出哪一行最长。如果我将$newline设置为值0x0d0x0a,$first和$rest都变为空。如果将其设置为\n或\n\r,则相同。或者如果我说-,或者如果我只是按回车键。在xsl:variable标记中。遗憾的是,我两者都没有。我从Ant脚本调用XSLT。这看起来非常有用。。。但是,我不想输出标记化的行,而是想知道最长行的长度。这样添加另一个属性:-请参见上面的编辑,我可以修改此属性,将原始地址(由新行分隔)拆分为
blah…
Hello Mathijs,感谢您共享您的最终代码。我将对此进行研究,“#xA;”和“0x0a”之间的区别我并不清楚。我也必须跟进此事。向你问好,彼得+1
<xsl:function name="kode:splitLongLine">
  <xsl:param name="string"/>
  <xsl:variable name="regex">
   <xsl:text>(((.){1,55})( |$))</xsl:text>
  </xsl:variable>

  <xsl:variable name="result">
   <xsl:analyze-string select="$string" regex="{$regex}">
    <xsl:matching-substring>
     <xsl:value-of select="concat(regex-group(1),'&#10;')"/>
    </xsl:matching-substring>
    <xsl:non-matching-substring>
     <xsl:value-of select="concat('REPORT ERROR: ', .)"/>
    </xsl:non-matching-substring>
   </xsl:analyze-string>
  </xsl:variable>

  <xsl:sequence select="$result"/>
 </xsl:function>