Reputation: 1020
I have XML:
<doc>
<p id="123" sec="abc"></p>
</doc>
Using XSLT, I need to:
1) add new attribute name
with value 'myname'
2) copy same sec
value
3) overwrite id
attribute to new value
I've written the following XSLT to do that,
<xsl:template match="p">
<p name="myname" id="999">
<xsl:apply-templates select="node()|@*"/>
</p>
</xsl:template>
It gives me following result:
<doc>
<p name="myname" id="123" sec="abc"></p>
</doc>
The desired result is:
<doc>
<p name="myname" id="999" sec="abc"></p>
</doc>
It seems it does not overwrite id
attribute value. How can I overwrite this value from XSLT?
Upvotes: 1
Views: 1655
Reputation: 163458
The key thing is that if you add several attributes with the same name to an element, the last one wins. Your explicit id="999" is considered to precede the attribute that you copy using the xsl:apply-templates call, so it has no effect.
There are several solutions. You can avoid applying templates to the @id attribute (using a select in the apply-templates); you can have a template rule for the @id attribute that does not cause it to be copied; or you could add the id="999" attribute AFTER doing the apply-templates, by means of an xsl:attribute instruction that appears after the xsl:apply-templates instruction.
Upvotes: 1
Reputation: 117073
Or simply:
<xsl:template match="p">
<p name="myname" id="999" sec="{@sec}"/>
</xsl:template>
--
In case the p
element can contain other nodes (unlike the example shown), use:
<xsl:template match="p">
<p name="myname" id="999" sec="{@sec}">
<xsl:apply-templates/>
</p>
</xsl:template>
Upvotes: 1
Reputation: 167691
Change the template
<xsl:template match="p">
<p name="myname" id="999">
<xsl:apply-templates select="node()|@*"/>
</p>
</xsl:template>
to
<xsl:template match="p">
<p name="myname" id="999">
<xsl:apply-templates select="@* except @id, node()"/>
</p>
</xsl:template>
or write a template for the id
attribute:
<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>
Upvotes: 6
Reputation: 1647
i can't try it myself at the moment ... please try to NOT copy 'id' attribute since this will overrule your 'id' attribute in the xslt.
<xsl:template match="p">
<p name="myname" id="999">
<xsl:apply-templates select="node()|@*[local-name() != 'id']"/>
</p>
</xsl:template>
Upvotes: 2