Reputation: 25
I have a problem with a xsl template that outputs nodes with am empty xmlns attribute.
The template is:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0"/>
<xsl:template match="/">
<X xmlns="a_ns">
<Y>
<xsl:value-of select="a/b/b2"/>
</Y>
<Z>
<xsl:copy-of select="a/d/d1/d11"/>
</Z>
</X>
</xsl:template>
The input is:
<a>
<b>
<b1>b1_text</b1>
<b2>b2_text</b2>
</b>
<c>
<c1>c1_text</c1>
<c2>c2_text</c2>
</c>
<d>
<d1>
<d11>
<d111 ls="op">d111_text</d111>
<d112>d112_text</d112>
</d11>
<d12>d12_text</d12>
</d1>
<d2>d2_text</d2>
<d3>d3_text</d3>
</d>
An the output:
<?xml version="1.0" encoding="utf-8"?>
<X xmlns="a_ns">
<Y>b2_text</Y>
<Z>
<d11 xmlns="">
<d111 ls="op">d111_text</d111>
<d112>d112_text</d112>
</d11>
</Z>
</X>
How can i modify the template so that the xmlns="" won't appear any more?
Thanks!
Upvotes: 0
Views: 2942
Reputation: 163458
The key thing to note is that you want to change the name of elements such as d11. In the input the name is {}d11 - that is, d11 in no namespace, while in the output you want it to be named {a_ns}d11 - that is, d11 in namespace a_ns. The xsl:copy-of instruction copies the node exactly, so it retains the name {}d11, and the serializer has to add the xmlns="" declaration to make sure it retains this name. To change the name (specifically, the namespace part of the name) you need to transform the nodes rather than copying them, using a procedure such as that provided by Dimitre.
Upvotes: 0
Reputation: 243529
This transformation:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<X xmlns="a_ns">
<Y>
<xsl:value-of select="a/b/b2"/>
</Y>
<Z>
<xsl:apply-templates select="a/d/d1/d11"/>
</Z>
</X>
</xsl:template>
<xsl:template match="*[ancestor-or-self::d11]">
<xsl:element name="{name()}" namespace="a_ns">
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
when applied on the provided XML document:
<a>
<b>
<b1>b1_text</b1>
<b2>b2_text</b2>
</b>
<c>
<c1>c1_text</c1>
<c2>c2_text</c2>
</c>
<d>
<d1>
<d11>
<d111 ls="op">d111_text</d111>
<d112>d112_text</d112>
</d11>
<d12>d12_text</d12>
</d1>
<d2>d2_text</d2>
<d3>d3_text</d3>
</d>
</a>
produces the wanted, correct result:
<X xmlns="a_ns">
<Y>b2_text</Y>
<Z>
<d11>
<d111 ls="op">d111_text</d111>
<d112>d112_text</d112>
</d11>
</Z>
</X>
Explanation:
xsl:copy-of
produces an exact copy of each node selected by the expression specified in its select
attribute. Thus, it cannot be used to change the (default) namespace of any copied element.
The elements being copied in this case belong to "no namespace". the fact that the copied elements still belong to the "no namespace" is expressed by xmlns=""
-- correctly as this should be -- by the XSLT processor.
Upvotes: 4