Namespaces in XSLT

I am using XSLT to restructure an XML file. The following code copies all the child nodes to a new XML file:

<!--Add all child elements of the zzz node--> <xsl:template match="zzz"> <Trade> <xsl:attribute name="ID"> <xsl:value-of select="TradeId" /> </xsl:attribute> <xsl:copy-of select="*"></xsl:copy-of> </Trade> </xsl:template> 

I would like to change the code so that it places the nodes in a specific namespace that is not in the source document. What do i need to change?

+4
source share
3 answers

The previous two answers (by Theun and Craig Bovis) are incorrect - see my comments for each of them.

. The method of converting this element to a new namespace is used to recreate this element, as shown below. :

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:template match="zzz"> <trade ID="{TradeId}"> <xsl:apply-templates select="*[not(self::TradeId)]"/> </trade> </xsl:template> <xsl:template match="zzz/*"> <xsl:element name="{name()}" namespace="my:Trade"> <xsl:copy-of select="@* | node()"/> </xsl:element> </xsl:template> </xsl:stylesheet> 

When this conversion is applied to the following XML source document :

 <zzz> <TradeId>153</TradeId> <x:item xmlns:x="x:x">A</x:item> <x:item xmlns:x="x:x">B</x:item> <x:item xmlns:x="x:x">C</x:item> </zzz> 

the required result is created :

 <trade ID="153"> <x:item xmlns:x="my:Trade">A</x:item> <x:item xmlns:x="my:Trade">B</x:item> <x:item xmlns:x="my:Trade">C</x:item> </trade> 
+5
source

You can simply include the namespace in the stylesheet like this:

 <!--Add all child elements of the zzz node--> <xsl:template match="zzz" xmlns:my="your target ns"> <my:Trade> <xsl:attribute name="my:ID" > <xsl:value-of select="TradeId" /> </xsl:attribute> <xsl:copy-of select ="*"></xsl:copy-of> </my:Trade> </xsl:template> 

Edit: as Dimitar noted, this does not put the copied nodes in the new namespace, but only the Trade element.

0
source

Dimitre Novatchev's solution is fine, but I would also like to point out that if you also need to change the namespaces of the nested elements, the following will work better:

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:template match="zzz"> <trade ID="{TradeId}"> <xsl:apply-templates select="*[not(self::TradeId)]" mode="change-ns"/> </trade> </xsl:template> <xsl:template match="@*|node()" priority="-10" mode="change-ns"> <xsl:copy/> </xsl:template> <xsl:template match="*" mode="change-ns"> <xsl:element name="{name()}" namespace="my:Trade"> <xsl:apply-templates select="@*|node()" mode="change-ns"/> </xsl:element> </xsl:template> </xsl:stylesheet> 

eg. if you have the following input

 <trade ID="153"> <x:item xmlns:x="my:Trade" someattr="1"> <x:subitem anotherattr="2">A1</x:subitem> <x:subitem anotherattr="3">A2</x:subitem> </x:item> <x:item xmlns:x="my:Trade">B</x:item> <x:item xmlns:x="my:Trade">C</x:item> </trade> 

You'll get

 <zzz> <TradeId>153</TradeId> <x:item xmlns:x="x:x" someattr="1"> <x:subitem anotherattr="2">A1</x:subitem> <x:subitem anotherattr="3">A2</x:subitem> </x:item> <x:item xmlns:x="x:x">B</x:item> <x:item xmlns:x="x:x">C</x:item> </zzz> 

Attributes are added to demonstrate that they are copied correctly, and a separate mode is used to change the namespace templates so that they do not interfere with another code if you want to use them as part of a larger style sheet.

0
source

All Articles