XSLT:从第 2 次出现开始匹配元素

XSLT: Match Elements starting at 2nd occurance

希望你能帮帮我。我正在搜索一个通用的 XSLT 匹配模板,它在第一次出现后匹配某个名称的所有元素。 在此示例中,所有内容都应使用身份转换进行复制,"line" 的第一次出现需要 "do something" 逻辑,并且应忽略第一个之后的所有 "line" 元素。 "line" 理论上元素可以无限次出现。

样本来源XML:

<?xml version="1.0" encoding="UTF-8"?>
<sampledoc>
    <header1>a1</header1>
    <header2>b1</header2>
    <header3>c1</header3>
    <line>a2</line>
    <line>b2</line>
    <line>c2</line>
    <line>c3</line>
    <line>c4</line>
    <footer>bye</footer>
</sampledoc>

我希望有类似 following::line[1] 的东西,但无法正常工作。所以这是我的 "static" 版本:

<?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" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>

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

    <xsl:template match="line[1]">
        <!-- Do something --> 
    </xsl:template>

    <xsl:template match="line[2]"/>
    <xsl:template match="line[3]"/>
    <xsl:template match="line[4]"/>
    <xsl:template match="line[5]"/>
    <xsl:template match="line[6]"/>
    <xsl:template match="line[7]"/>



</xsl:stylesheet>

谢谢!

您需要了解模板匹配优先级。特别是,将元素与条件匹配的模板比仅匹配元素名称本身具有更高的优先级。 (具体来说,line[1] 的模板匹配的优先级为 0.5,而仅匹配 line 的模板的优先级为 0。)

这意味着您只需要以下模板。

<xsl:template match="line[1]">
    <newline /> 
</xsl:template>

<xsl:template match="line"/>

因此,对于第一个 line 元素,虽然两个模板都可以匹配它,但第一个具有更高的优先级,因此将在所有情况下使用。

有关详细信息,请参阅 https://www.w3.org/TR/xslt-10/#conflict

试试这个 XSLT

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

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

    <xsl:template match="line[1]">
        <newline /> 
    </xsl:template>

    <xsl:template match="line"/>
</xsl:stylesheet>

(请注意,在这种情况下,您的模板匹配 / 不是必需的,因为 XSLT 的 built-in templates 会做同样的事情)

使用<xsl:template match="line[position() > 1]"/>不处理任何第二、三、四行子元素。