XSLT - 动态地向节点添加属性

时间:2015-07-16 14:38:51

标签: xml xslt xslt-2.0

我有xml如下,

<doc>
<p type="Foot">
    <link ref="http://www.facebook.com">
        <c type="Hyperlink">www.facebook.com</c>
    </link>
</p>
 <p type="End">
    <link ref="http://www.google.com">
        <c type="Hyperlink">www.google.com.com</c>
    </link>
</p>
</doc>

我需要做的是向<p>节点添加动态ID属性,该节点具有属性"Foot""End"。所以我写了以下xsl,

<xsl:template match="p[@type='Foot' or @type='End']" priority="1">
     <xsl:copy>
        <xsl:attribute name="id">
            <xsl:value-of select="'foot-'"/> 
            <xsl:number count="p[@type='Foot' or @type='End']" level="any"/>
        </xsl:attribute>
        <xsl:next-match/>
    </xsl:copy>
    </xsl:template>

它给了我以下结果

<doc>
<p id="foot-1"><p type="Foot">
    <link ref="http://www.facebook.com">
        <c type="Hyperlink">www.facebook.com</c>
    </link>
</p></p>
 <p id="foot-2"><p type="End">
    <link ref="http://www.google.com">
        <c type="Hyperlink">www.google.com.com</c>
    </link>
</p></p>
</doc>

如上面的结果xml,它添加重复的

节点并添加新属性。但我需要的是这个,

<doc>
<p id="foot-1 type="Foot">
    <link ref="http://www.facebook.com">
        <c type="Hyperlink">www.facebook.com</c>
    </link>
</p></p>
 <p id="foot-2 type="End">
    <link ref="http://www.google.com">
        <c type="Hyperlink">www.google.com.com</c>
    </link>
</p></p>
</doc>

如何通过更改mu xsl来获得此输出?

1 个答案:

答案 0 :(得分:3)

我认为您的问题很可能是我们可以从您的问题中看到的 - 您正在调用xsl:next-match,在已经输出{{1}的模板中来自p指令的标记。如果下一场比赛发生了xsl:copy,那么您将在第一场比赛中获得第二个xsl:copy代码,就像您正在看到的一样。

听起来你需要做的就是让另一个具有更高优先级的模板只匹配p,让它做p,调用<xsl:copy>然后处理子节点,从与特定情况匹配的优先级较低的模板中删除<xsl:next-match>

<xsl:copy>

顺便说一下,你不需要<xsl:template match="p" priority="2"> <xsl:copy> <xsl:next-match/> <xsl:apply-templates select="node() | @*"/> </xsl:copy> </xsl:template> <xsl:template match="p[@type='Foot']" priority="1"> <xsl:attribute name="id"> <xsl:value-of select="'foot-'"/> <xsl:number count="p[@type='Foot' or @type='End']" level="any"/> </xsl:attribute> <xsl:next-match/> </xsl:template> etc.. - 如果它只是一个常数,那么<xsl:value-of select="'foot-'"/>就可以了。