Reputation: 17478
How do I copy children using XSL?
Source:
<body>
<keyword><i color="blue">super</i>man</keyword>
<keyword><i color="blue">super</i>man</keyword>
<keyword><i color="blue">super</i>woman</keyword>
</body>
I am using the following
<xsl:template match="keyword" >
<keyword>
<xsl:attribute name="type">Key Words Head First</xsl:attribute>
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</keyword>
</xsl:template>
When using the above code I am getting double nested <keyword>
tags.
Thanks.
Upvotes: 2
Views: 720
Reputation: 60414
You don't need to output a keyword
explicitly and copy the existing keyword
using xsl:copy
. As an alternative to @DevNull's answer:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="keyword">
<xsl:copy>
<xsl:attribute name="type">Key Words Head First</xsl:attribute>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
...produces the following, when applied to your input:
<body>
<keyword type="Key Words Head First"><i color="blue">super</i>man</keyword>
<keyword type="Key Words Head First"><i color="blue">super</i>man</keyword>
<keyword type="Key Words Head First"><i color="blue">super</i>woman</keyword>
</body>
From the comments:
...what if the attribute needs to be overridden. Like suppose 'keyword' already has a 'type' attribute.
In that case, don't copy the existing type
attribute:
<xsl:template match="keyword">
<xsl:copy>
<xsl:attribute name="type">Key Words Head First</xsl:attribute>
<xsl:apply-templates select="@*[not(name()='type')]|node()"/>
</xsl:copy>
</xsl:template>
Upvotes: 3
Reputation: 52858
xsl:copy
is copying the context item, which in this case is keyword
. Basically you're wrapping the existing keyword
with a new one.
Try removing the xsl:copy
:
<xsl:template match="keyword" >
<keyword type="Key Words Head First">
<xsl:apply-templates select="node()|@*[name() != 'type']"/>
</keyword>
</xsl:template>
Note: Your final output will depend on whether you have other templates to handle the children of keyword
(like an identity transform).
You can find more information on copying and the identity transform here: http://www.w3.org/TR/xslt#copying
Upvotes: 3