Reputation: 1020
I have xml like follows,
<doc>
<a ref="style1"><b>Test1</b></a>
<a ref="style1"><b>Test2</b></a>
<a ref="style2"><b>Test3</b></a>
</doc>
I need to add new attribute and new node inside <a>
nodes which have attribute "style1"
.
So I wrote following xsl,
//add attribute
<xsl:template match="a[@ref='style1']">
<xsl:copy>
<xsl:attribute name="id">myId</xsl:attribute>
</xsl:copy>
</xsl:template>
//add new node
<xsl:template match="a[@ref='style1']" priority="1">
<xsl:copy>
<newNode></newNode>
</xsl:copy>
<xsl:next-match/>
</xsl:template>
I need to create two templates as above (requirement).
but my current output as follows,
<doc>
<a><newNode/></a><a id="myId"/>
<a><newNode/></a><a id="myId"/>
<a ref="style2"><b>Test2</b></a>
</doc>
as you can see, <a>
nodes has doubled. and <b>
nodes have gone. but m expected output is this,
<doc>
<a id="myId"><newNode/><b>Test1</b>/a>
<a id="myId"><newNode/><b>Test2</b>/a>
<a ref="style2"><b>Test3</b></a>
</doc>
How can I organize my code to get above expected output??
Upvotes: 2
Views: 3796
Reputation: 116993
First, you should only use xsl:copy
in one of the templates - otherwise you will be duplicating the node.
Next, you must add attributes before adding any child nodes.
Finally, in order to have both the new attribute and the existing child nodes inside the parent, you must place the relevant instructions inside the xsl:copy
element:
XSLT 2.0
<xsl:stylesheet version="2.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="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="a[@ref='style1']">
<xsl:attribute name="id">myId</xsl:attribute>
</xsl:template>
<xsl:template match="a[@ref='style1']" priority="1">
<xsl:copy>
<xsl:next-match/>
<newNode/>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Result
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<a id="myId">
<newNode/>
<b>Test1</b>
</a>
<a id="myId">
<newNode/>
<b>Test2</b>
</a>
<a ref="style2">
<b>Test3</b>
</a>
</doc>
Upvotes: 3