用 XSLT 覆盖属性
Overwrite attribute with XSLT
我有 XML:
<doc>
<p id="123" sec="abc"></p>
</doc>
使用 XSLT,我需要:
1) 添加新属性 name
,值为 'myname'
2) 复制相同的 sec
值
3) 将 id
属性覆盖为新值
我为此编写了以下 XSLT,
<xsl:template match="p">
<p name="myname" id="999">
<xsl:apply-templates select="node()|@*"/>
</p>
</xsl:template>
它给了我以下结果:
<doc>
<p name="myname" id="123" sec="abc"></p>
</doc>
期望的结果是:
<doc>
<p name="myname" id="999" sec="abc"></p>
</doc>
它似乎没有覆盖 id
属性值。如何从 XSLT 覆盖这个值?
我目前无法自己尝试...请尽量不要复制 'id' 属性,因为这会否决 xslt 中的 'id' 属性。
<xsl:template match="p">
<p name="myname" id="999">
<xsl:apply-templates select="node()|@*[local-name() != 'id']"/>
</p>
</xsl:template>
更改模板
<xsl:template match="p">
<p name="myname" id="999">
<xsl:apply-templates select="node()|@*"/>
</p>
</xsl:template>
到
<xsl:template match="p">
<p name="myname" id="999">
<xsl:apply-templates select="@* except @id, node()"/>
</p>
</xsl:template>
或者为 id
属性写一个模板:
<xsl:template match="p">
<p name="myname">
<xsl:apply-templates select="@* , node()"/>
</p>
</xsl:template>
<xsl:template match="p/@id">
<xsl:attribute name="id" select="999"/>
</xsl:template>
或者简单地说:
<xsl:template match="p">
<p name="myname" id="999" sec="{@sec}"/>
</xsl:template>
--
如果 p
元素可以包含其他节点(与显示的示例不同),请使用:
<xsl:template match="p">
<p name="myname" id="999" sec="{@sec}">
<xsl:apply-templates/>
</p>
</xsl:template>
关键是如果你给一个元素添加多个同名的属性,最后一个会胜出。您的显式 id="999" 被认为在您使用 xsl:apply-templates 调用复制的属性之前,因此它没有任何效果。
有几种解决方法。您可以避免将模板应用于 @id 属性(在应用模板中使用 select);您可以为 @id 属性设置一个不会导致它被复制的模板规则;或者您可以在执行应用模板后添加 id="999" 属性,方法是在 xsl:apply-模板指令之后出现 xsl:attribute 指令。
我有 XML:
<doc>
<p id="123" sec="abc"></p>
</doc>
使用 XSLT,我需要:
1) 添加新属性 name
,值为 'myname'
2) 复制相同的 sec
值
3) 将 id
属性覆盖为新值
我为此编写了以下 XSLT,
<xsl:template match="p">
<p name="myname" id="999">
<xsl:apply-templates select="node()|@*"/>
</p>
</xsl:template>
它给了我以下结果:
<doc>
<p name="myname" id="123" sec="abc"></p>
</doc>
期望的结果是:
<doc>
<p name="myname" id="999" sec="abc"></p>
</doc>
它似乎没有覆盖 id
属性值。如何从 XSLT 覆盖这个值?
我目前无法自己尝试...请尽量不要复制 'id' 属性,因为这会否决 xslt 中的 'id' 属性。
<xsl:template match="p">
<p name="myname" id="999">
<xsl:apply-templates select="node()|@*[local-name() != 'id']"/>
</p>
</xsl:template>
更改模板
<xsl:template match="p">
<p name="myname" id="999">
<xsl:apply-templates select="node()|@*"/>
</p>
</xsl:template>
到
<xsl:template match="p">
<p name="myname" id="999">
<xsl:apply-templates select="@* except @id, node()"/>
</p>
</xsl:template>
或者为 id
属性写一个模板:
<xsl:template match="p">
<p name="myname">
<xsl:apply-templates select="@* , node()"/>
</p>
</xsl:template>
<xsl:template match="p/@id">
<xsl:attribute name="id" select="999"/>
</xsl:template>
或者简单地说:
<xsl:template match="p">
<p name="myname" id="999" sec="{@sec}"/>
</xsl:template>
--
如果 p
元素可以包含其他节点(与显示的示例不同),请使用:
<xsl:template match="p">
<p name="myname" id="999" sec="{@sec}">
<xsl:apply-templates/>
</p>
</xsl:template>
关键是如果你给一个元素添加多个同名的属性,最后一个会胜出。您的显式 id="999" 被认为在您使用 xsl:apply-templates 调用复制的属性之前,因此它没有任何效果。
有几种解决方法。您可以避免将模板应用于 @id 属性(在应用模板中使用 select);您可以为 @id 属性设置一个不会导致它被复制的模板规则;或者您可以在执行应用模板后添加 id="999" 属性,方法是在 xsl:apply-模板指令之后出现 xsl:attribute 指令。