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

时间:2012-03-21 14:01:46

标签: 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 select="substring-after($source, $newline)"/>
</xsl:variable>

这是recusrive模板的一部分,它将$ rest推入自身。

问题是代码示例没有定义$ newline。 如果我将$ newline设置为一个字母,比如's',那么文本就会被分割得很好(例如,它会将输入“响亮”变成“重新”和“响亮”)。但是当我尝试将$ newline设置为换行符时,即&#xa;&#xa0;时,它会永远递归,并给我一个堆栈溢出。我也尝试为换行定义一个ENTITY,但没有区别。

输入在每行末尾都有普通的CR / LF(我在Windows机器上)。

任何人都知道我做错了什么,或建议采取何种方法?

谢谢, Mathijs

5 个答案:

答案 0 :(得分:3)

如果您可以使用EXSLT尝试使用str:tokenize

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

或类似于XSLT 2.0:

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

答案 1 :(得分:2)

我曾经使用过这个模板。它是一个命名模板,因此您可以在需要的地方调用它。这里的文字分为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>

让我知道它是否适合你。

此致 彼得

答案 2 :(得分:2)

您可以使用以下内容。

<?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>

输出结果为

<?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>

请注意,前导标签(或空白)被视为行的一部分。

答案 3 :(得分:2)

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>

答案 4 :(得分: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>