XSLT2.0-Group相邻不复制文本()

时间:2013-12-14 01:39:55

标签: xml xslt xslt-2.0

我使用以下XSLT 2.0对相邻的“内联”元素进行分组,但没有复制text()节点,有人知道为什么吗? 来源xml:

    <para>
      <p>some text</p>
      <section>
       <section>
        <inline>inline text</inline>
        <inline/>
        <p>some more text</p>
        <p/>
       </section>
       <para>
        <p>dog</p>
        <p/>
        <p/>
        <sub-para>
            <p/>
            <p/>
        </sub-para>
       </para>
      </section>
    </para>

我的XSLT 2.0样式表有2个模板匹配(用于text())和*(用于任何元素)

    <xsl:template match="text()">
     <xsl:copy />
    </xsl:template>

    <xsl:template match="*">
      <xsl:copy>
        <xsl:for-each-group select="*" group-adjacent="boolean(self::inline)">
            <xsl:choose>
                <xsl:when test="current-grouping-key()">
                    <grp><xsl:copy-of select="current-group()"/></grp>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:apply-templates select="current-group()"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each-group>
      </xsl:copy>
    </xsl:template>

我目前得到的结果是:

    <para>
     <p/>
     <section>
      <section>
       <grp>
        <inline>inline text</inline>
        <inline/>
       </grp>
       <p/>
       <p/>
      </section>
      <para>
        <p/>
        <p/>
        <p/>
        <sub-para>
         <p/>
         <p/>
        </sub-para>
       </para>
     </section>
    </para>

即。复制元素,对相邻的内联元素进行分组,但不复制任何文本节点。

为什么不调用apply-templates select = current-group()会导致调用text()模板?

非常感谢任何答案

2 个答案:

答案 0 :(得分:0)

指令<xsl:for-each-group select="*"选择子元素节点,而不选择子文本节点。因此,文本节点不会成为任何组的一部分,因此不会被复制。

您拥有与文本节点匹配的模板规则这一事实无关紧要,因为您从不将模板应用于文本节点。

如果更改for-each-group以选择文本节点(通过编写select="node()"),则存在“内联”元素不再相邻的问题,因为它们由空白文本分隔节点

我不知道源词汇表,但我倾向于仅将分组模板用于“块级”元素(如para和section),并对具有文本或混合内容的元素使用标准身份模板

答案 1 :(得分:0)

正如迈克尔凯先生所说,你只是选择元素,而不是节点,所以你的文本节点永远不会被处理。

作为当前模板,你有匹配元素,然后处理子元素,我认为你需要的是第二个模板,它也匹配元素,但只有没有子元素的模板。在此模板中,您可以添加处理文本节点

<xsl:template match="*[not(*)]">
      <xsl:copy>
          <xsl:apply-templates />
     </xsl:copy>
</xsl:template>

由于此模板已指定条件,因此,当条件为真时,我应该优先考虑现有模板。

实际上,它甚至可以简化为

<xsl:template match="*[not(*)]">
      <xsl:copy-of select="." />
</xsl:template>

值得指出的是,无论是否将模板应用于文本节点,实际上都不需要匹配 text()的当前模板。 XSLT具有内置模板的概念,当在XSLT中找不到节点的显式模板匹配时使用。这些内置模板无论如何都会输出文本节点,因此你所有的“text()”模板都是模板中的内置版本所做的。