Changing namespace for XML file in XSL Translation
This transformation:
<xsl:template match="*">
<xsl:element name="cmp:{name()}" namespace="CompanyURL">
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="/*">
<cmp:container xmlns:cmp="CompanyURL">
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</cmp:container>
</xsl:template>
</xsl:stylesheet>
when performed on the provided XML document:
<foo xmlns="companyURL">
<num1>asdf</num1>
<num2>ghjkl</num2>
</foo>
produces the wanted, correct result:
<cmp:container xmlns:cmp="CompanyURL">
<cmp:num1>asdf</cmp:num1>
<cmp:num2>ghjkl</cmp:num2>
</cmp:container>
adam_0
Updated on July 20, 2022Comments
-
adam_0 almost 2 years
So I have an input file that uses my company's namespace in the default namespace (
xmlns="companyURL"
) but I want my output file to use something other than the default namespace (xmlns:cmp="companyURL"
). So I construct my file using thecmp
namespace, but then I want to copy some of the inner elements:<xsl:element name="cmp:container"> <xsl:for-each select="foo"> <xsl:copy-of select="." /> </xsl:for-each> </xsl:element>
Unfortunately, what this does is define the default namespace for each of those inner elements, making the file incredibly verbose and ugly. Simplified example:
Source:
<foo xmlns="companyURL"> <num1>asdf</num1> <num2>ghjkl</num2> </foo>
Turns into:
<cmp:container xmlns:cmp="companyURL"> <num1 xmlns="companyURL">asdf</num1> <num2 xmlns="companyURL">ghjkl</num2> </cmp:container>
Of course,
companyURL
is big and long and ugly, and it's the same in both places, so I would prefer the above result to just be the following:<cmp:container xmlns:cmp="companyURL"> <cmp:num1>asdf</cmp:num1> <cmp:num2>ghjkl</cmp:num2> </cmp:container>
Is there an easy way to do this, or should I convert everything under the
cmp
namespace to the default namespace? I would prefer to use the explicit namespace naming if possible, it aids in understanding the XSLT in my experience. -
adam_0 over 13 yearsWhy do you have
<xsl:copy-of select="@*"/>
in your XSLT? -
Dimitre Novatchev over 13 years@adam_0: This copies all attributes of the element. In your concrete example there are no attributes, but if we want to use this code as a general convertor, it must be able to convert correctly all documents -- including such in which there are elements with attributes.
-
adam_0 over 13 yearsMy XML Schema specifies that there will be no attributes, so I'm guessing it's fine to leave that line out?
-
Dimitre Novatchev over 13 yearsIf you are 100% sure you can remove it, but leaving it doesn't hurt anything -- simply no attributes will be copied. It is always better to have more generic code. Imagine that tomorrow there is a change in the schema and there would be attributes. Then you'd need to add copying of attributes. In case you used the more generic code from the very start, this change in schema will not affect you at all.
-
adam_0 over 13 yearsThanks for your help and powerful, concise answers. +1
-
adam_0 over 13 yearsA follow-up I just thought about: could I make this work for any namespace prefix by changing the top template line of
<xsl:element name="cmp:{name()}" namespace="CompanyURL">
to<xsl:element name="cmp:{local-name()}" namespace="CompanyURL">
(effectively trimming off any namespace prefix and putting on my own)? -
Dimitre Novatchev over 13 years@adam_0: Yes, this is the way to do prefix-renaming.