Search code examples
xsltsaxon

Unexpected namespace declaration


I'm porting old transformations to a new transformation platform (based on Saxon 9.9). I have an issue where the new platform creates slightly different results than the old platform (based on an ancient bug-ridden Oracle XSLT1+ implementation).

Consider the following source document:

<root xmlns="http://root.invalid">
  <model xmlns="http://root.invalid">
    <keys>
      <id xmlns:foo="http://foo.invalid" foo:nil="true"/>
    </keys>
    <instance>
      <id xmlns:foo="http://foo.invalid" foo:nil="true"/>
      <whatever type="String">whatever</whatever>
    </instance>
  </model>
</root>

When the following transformation is applied:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:root="http://root.invalid"
  exclude-result-prefixes="root"
>
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
  
  <xsl:strip-space elements="*"/>

  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>
  
  <xsl:template match="root:id">
    <id xmlns:foo="http://foo.invalid" foo:nil="true" type="String">1234</id>
  </xsl:template>

</xsl:stylesheet>

The following (correct) output is generated:

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="http://root.invalid">
  <model>
    <keys>
      <id xmlns:foo="http://foo.invalid" xmlns="" foo:nil="true" type="String">1234</id>
    </keys>
    <instance>
      <id xmlns:foo="http://foo.invalid" xmlns="" foo:nil="true" type="String">1234</id>
      <whatever type="String">whatever</whatever>
    </instance>
  </model>
</root>

The problem here is that in the new platform I get a xmlns="" namespace definition that didn't exists in the old platform (that is breaking existing consumers of the output transformation).

Can you explain why the xmlns="" appers here and is there any chance I could get:

<id xmlns:foo="http://foo.invalid" foo:nil="true" type="String">1234</id>

instead (with Saxon 9.9 based XSLT)?


Solution

  • If you want your result element(s) to be in that namespace then use e.g. xmlns="http://root.invalid" on the xsl:stylesheet or at least on the literal result id elements e.g. <id xmlns="http://root.invalid" .../>. Or use an xsl:copy and add the new attribute and text e.g. <xsl:copy><xsl:copy-of select="@*"/><xsl:attribute name="type">string</xsl:attribute>1234</xsl:copy> in your template matching the id elements.