包装元素

时间:2018-04-06 12:10:02

标签: xslt xslt-2.0

我有一个包含多个<b>元素的输入xml文件,我必须包装连续出现的所有<b>。我为此写了一个xsl。这是更好的方法吗?在包装元素之后,在转换期间还会产生额外的空间。

示例输入XML

<chap>
<p><b>The</b> <b>Attorney</b> General <b>(Fees)</b><b>a</b><b>b</b><b>c</b> Determination 2012 No 110 commenced on 1 <b>July</b> <b>2012</b> <b>and</b> was repealed on <b>1</b> <b>July</b> <b>2013</b>. The Determination is yet to be amended by:</p>
</chap>

XSLT

    <?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:guru="Self"
    exclude-result-prefixes="xs"
    version="2.0">
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="b[preceding-sibling::node()[1][self::b]]
         |b[preceding-sibling::node()[1][normalize-space(.) = '']][preceding-sibling::node()[2][self::b]]"/>

    <xsl:template match="b">
        <xsl:copy>
            <xsl:apply-templates/>
            <xsl:if test="following-sibling::node()[1][self::b]">
                <xsl:copy-of select="guru:wrap(following-sibling::node()[1], '')"/>
            </xsl:if>
            <xsl:if test="following-sibling::node()[1][normalize-space(.) = '']/following-sibling::node()[1][self::b]">
                <xsl:copy-of select="guru:wrap(following-sibling::node()[2], following-sibling::node()[1])"/>
            </xsl:if> 
        </xsl:copy>
    </xsl:template>

    <xsl:function name="guru:wrap">
        <xsl:param name="b_data"/>
        <xsl:param name="space"/>
        <xsl:value-of select="$space"/>
        <xsl:value-of select="$b_data"/>
        <xsl:if test="$b_data/following-sibling::node()[1][self::b]">
            <xsl:copy-of select="guru:wrap($b_data/following-sibling::node()[1], '')"/>
        </xsl:if>
        <xsl:if test="$b_data/following-sibling::node()[1][normalize-space(.) = '']/following-sibling::node()[1][self::b]">
            <xsl:copy-of select="guru:wrap($b_data/following-sibling::node()[2], $b_data/following-sibling::node()[1])"/>
        </xsl:if> 
    </xsl:function>

</xsl:stylesheet>

输出

<chap>
    <p><b>The Attorney</b>  General <b>(Fees)abc</b> Determination 2012 No 110 commenced on 1 <b>July 2012 and</b>   was repealed on <b>1 July 2013</b>  . The Determination is yet to be amended by:</p>
</chap>

所需输出

<chap>
    <p><b>The Attorney</b> General <b>(Fees)abc</b> Determination 2012 No 110 commenced on 1 <b>July 2012 and</b> was repealed on <b>1 July 2013</b>. The Determination is yet to be amended by:</p>
</chap>

先谢谢。

1 个答案:

答案 0 :(得分:1)

我建议使用for-each-group group-adjacent="self::b or self::text()[. = ' ']"

  <xsl:template match="p">
      <xsl:copy>
          <xsl:apply-templates select="@*"/>
          <xsl:for-each-group select="node()" group-adjacent="self::b or self::text()[. = ' ']">
              <xsl:choose>
                  <xsl:when test="current-grouping-key()">
                      <b>
                          <xsl:apply-templates select="current-group()/node() | current-group()[self::text()]"/>
                      </b>
                  </xsl:when>
                  <xsl:otherwise>
                      <xsl:apply-templates select="current-group()"/>
                  </xsl:otherwise>                  
              </xsl:choose>
          </xsl:for-each-group>
      </xsl:copy>
  </xsl:template>

https://xsltfiddle.liberty-development.net/gWmuiHU/1显示结果,它使用XSLT 3,但对于XSLT 2,您只需删除xsl:mode并保留身份模板

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

你的代码中有。