XSLT - 如何为每个X字符添加新标记

时间:2016-11-15 08:21:42

标签: html xml xslt tags xslt-1.0

我想为每个10个字符的XML添加一个新标记<br\>。 (不包括内部节点)

例如,如果我的输入是:

<main>
   01234567890123
   <a> 
        link        
   </a>
   45678901234567901234
</main>

我希望是这样的事情:

<main>
   0123456789<br\>0123
   <a> 
        link        
   </a>
   456789<br\>012345679<br\>01234
</main>

我写了这个函数:

<!-- Add new "HTML Break" Every X chars  -->
<xsl:template name="Add-HTML-Break-After-X-Chars">
<xsl:param name="text" />
<xsl:param name="max-length" />

<xsl:choose>
  <xsl:when test="string-length($text) > $max-length">

    <!-- Show the X length of the text -->
    <xsl:copy-of select="substring($text,1,$max-length)" />

    <!-- Adding the special tag  -->
    <br/>

    <!-- continue to add the rest of the text  -->
    <xsl:call-template name="Add-HTML-Break-After-X-Chars">
      <xsl:with-param name="text" select="substring($text, $max-length + 1)" />
      <xsl:with-param name="max-length" select="$max-length" />
    </xsl:call-template>


  </xsl:when>
  <xsl:otherwise>

    <!-- Show the text (length is less then X) -->
    <xsl:copy-of select="$text" />

  </xsl:otherwise>
</xsl:choose>

问题在于我在没有内部标签的情况下获得输出:

<main>
   0123456789<br\>0123
        link        
   45<br\>6789012345<br\>67901234
</main>

我使用此代码调用模板:

    <xsl:call-template name="Add-HTML-Break-After-X-Chars">
      <xsl:with-param name="text" select="main" />
      <xsl:with-param name="max-length" select="10" />
    </xsl:call-template>

我也试过&#34;价值&#34;而不是&#34; copy-of&#34;。

有没有办法可以保留标签?

如果是这样,我怎样才能保留它们并制作一个安全的&#34;插入新标签?

1 个答案:

答案 0 :(得分:1)

这在XSLT中很难做到,因为它会单独处理每个文本节点,而不会从前面的文本节点传递任何信息。

这是一种可行的方法:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="main/text()" name="wrap">
    <xsl:param name="text" select="."/>
    <xsl:param name="line-length" select="10"/>
    <xsl:param name="carry">
        <xsl:variable name="lengths">
            <xsl:for-each select="preceding-sibling::text()">
                <length>
                    <xsl:value-of select="string-length()"/>
                </length>
            </xsl:for-each>
        </xsl:variable>
        <xsl:value-of select="sum(exsl:node-set($lengths)/length) mod $line-length"/>
    </xsl:param>

    <xsl:value-of select="substring($text, 1, $line-length - $carry)"/>
    <br/>
    <xsl:if test="$carry + string-length($text) > $line-length">
        <!-- recursive call -->
        <xsl:call-template name="wrap">
            <xsl:with-param name="text" select="substring($text, $line-length - $carry + 1)"/>
            <xsl:with-param name="carry" select="0"/>
        </xsl:call-template>            
    </xsl:if>
</xsl:template>

</xsl:stylesheet>

当这应用于以下测试输入时:

<强> XML

<main>A123456789B123<a>link1</a>456789C123456789D12345678<a>link2</a>9E123456789F1234567</main>

结果将是:

<?xml version="1.0" encoding="UTF-8"?>
<main>A123456789<br/>B123<a>link1</a>456789<br/>C123456789<br/>D12345678<a>link2</a>9<br/>E123456789<br/>F1234567</main>