Tuesday, June 17, 2008

Unwanted "xmlns=" Attribute in Elements After Transformation

I was doing a simple XSLT transformation that involved renaming elements. Starting with a basic example like:


<?xml version="1.0" encoding="UTF-8"?>
<mydoc xmlns="http://finegameofnil.blogger.com/xml-examples/rename">
 <foo someattr1="a" someattr2="b">
 </foo>
</mydoc>


I want to change "foo" to "foobar".

I run the the stylesheet:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xsl="http://www.w3.org/1999/XSL/Transform" xsi="http://www.w3.org/2001/XMLSchema-instance" fgon="http://finegameofnil.blogger.com/xml-examples/rename" version="2.0">
<xsl:import href="copy.xsl">
<xsl:output method="xml" version="1.0" standalone="yes" indent="yes" encoding="UTF-8">
<xsl:template match="fgon:foo">
 <xsl:element name="foobar">
  <xsl:apply-templates select="@* | node()">
  </xsl:apply-templates>
 </xsl:element>
</xsl:template>


I get:


<?xml version="1.0" encoding="UTF-8"?>
<mydoc xmlns="http://finegameofnil.blogger.com/xml-examples/rename">
 <foobar xmlns="" someattr1="a" someattr2="b">
 </foobar>
</mydoc>


So what's with the xmlns=""? I'm not sure what the semantics of an empty namespace are. It seems to mean the that element and its children are not in any namespace. In a case where you are renaming a document to conform to a schema change you will get a schema validation error.

To prevent this I tried the following stylesheet which explicitly sets the namespace for the target element to the default namespace:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xsl="http://www.w3.org/1999/XSL/Transform" xsi="http://www.w3.org/2001/XMLSchema-instance" fgon="http://finegameofnil.blogger.com/xml-examples/rename" version="2.0">
<xsl:import href="copy.xsl">
<xsl:output method="xml" version="1.0" standalone="yes" indent="yes" encoding="UTF-8">
<xsl:template match="fgon:foo">
 <xsl:element name="foobar" namespace="{namespace-uri()}">
  <xsl:apply-templates select="@* | node()">
  </xsl:apply-templates>
 </xsl:element>
</xsl:template>


Finally, this gives me what I wanted:

<?xml version="1.0" encoding="UTF-8"?>
<mydoc xmlns="http://finegameofnil.blogger.com/xml-examples/rename">
 <foobar someattr1="a" someattr2="b">
 </foobar>
</mydoc>


The copy.xsl imported in the examples above is from Sal Magnano's "XSLT Cookbook - 2nd Edition".


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
 <!-- General purpose copy translation stylesheet.
Taken from XSLT Cookbook, 2nd Edition, page 275. -->
 <xsl:template match="node() | @*">
  <xsl:copy>
   <xsl:apply-templates select="@* | node()"/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>
 
Creative Commons License
finegameofnil by Clay Fink is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License.