Geebee
Geebee

Reputation: 143

How to convert XML using XSLT and copy nodes along with attributes

I have a following XML which should get transformed to "Expected Output" (As mentioned below. But I am not sure why is node attribute (ABC) is not coming inside the xml tag but outside.

<?xml version="1.0" encoding="UTF-8"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Node ID="ABC">
<Name>Name-ABC</Name>
<Description>Desc-ABC</Description>
</Node>
</Root>

XSL:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:template match="Node">
<xsl:copy>
<xsl:apply-templates select="node() | @*" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

Current Output

<?xml version="1.0" encoding="UTF-8"?>
<Node xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">ABC
Name-ABC
Desc-ABC
</Node>

Expected Output (Attribute should be inside), Also I do not need to copy any node which is not matching the templates I have created:

<?xml version="1.0" encoding="UTF-8"?>
<Node xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ID="ABC"></Node>

Upvotes: 0

Views: 158

Answers (1)

Martin Honnen
Martin Honnen

Reputation: 167716

If you want to copy the attributes of the Node element then add a template <xsl:template match="Node/@*"><xsl:copy/></xsl:template> or make sure you copy them with <xsl:copy-of select="@*"/> inside the template of the Node element. It is not clear what you want to do with the child elements, if you don't want them copied or output at all then remove the <xsl:apply-templates select="node()"/> inside the template.

If you only know the name of the element you want to copy to the output then start your stylesheet with

<xsl:template match="/">
  <xsl:apply-templates select="//Node"/>
</xsl:template>

then use the suggestions already made, that is

<xsl:template match="Node/@*"><xsl:copy/></xsl:template>

and

<xsl:template match="Node"> <xsl:copy> <xsl:apply-templates select="@*" /> </xsl:copy> </xsl:template>

or as an alternative to those two templates you can use a single template for Node doing

<xsl:template match="Node">
  <xsl:copy>
    <xsl:copy-of select="@*"/>
  </xsl:copy>
</xsl:template>

Upvotes: 1

Related Questions