Unused namespace declaration appears after XSLT

After cleaning the network of answers, coming up with โ€œalmostโ€ solutions ... I decided to reduce the problem to a very simple case.

Consider the following XML fragment:

<me:root xmlns:me="http://stackoverflow.com/xml" xmlns="http://www.w3.org/1999/xhtml"> <me:element> <p>Some HTML code here.</p> </me:element> </me:root> 

Note that the p element has an XHTML namespace, which is standard for this document.

Now consider the following simple style sheet. I want to create an XHTML document with the contents of me:element as bodies.

 <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:me="http://stackoverflow.com/xml" xmlns="http://www.w3.org/1999/xhtml" exclude-result-prefixes="me"> <xsl:template match="/"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>My Title</title> </head> <body> <xsl:copy-of select="me:root/me:element/node()"/> </body> </html> </xsl:template> </xsl:stylesheet> 

Notice that I turned on exclude-result-prefixes ... But look what I get:

 <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>My Title</title> </head> <body> <p xmlns:me="http://stackoverflow.com/xml">Some HTML code here.</p> </body> </html> 

And what makes me crazy is why, why is xmlns:me appearing inside the p element?

No matter what I tried, I could not get it to work. I have a strange feeling that the problem is related to my xsl:copy-of statement.

+4
source share
1 answer

I have a strange feeling that the problem is with my xsl:copy-of statement.

Exactly because of this reason.

The source XML document contains this snippet :

 <me:element> <p>Some HTML code here.</p> </me:element> 

In the XPath data model, namespace nodes propagate from the subtree root to all their descendants. Therefore, the <p> element has the following namespaces:

  • "http://www.w3.org/1999/xhtml"

  • "http://stackoverflow.com/xml"

  • "http://www.w3.org/XML/1998/namespace"

  • http://www.w3.org/2000/xmlns/

The last two reserved namespaces (for xml: and xmlns prefixes) are available for any node name.

The reported problem is that, by definition, the <xsl:copy-of> command copies all nodes and their full subtrees with all namespaces belonging to each node.

Remember : prefixes specified as the value of the exclude-result-prefixes attribute are excluded only from the elements of the result literal!

Decision

 <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:me="http://stackoverflow.com/xml" xmlns="http://www.w3.org/1999/xhtml" exclude-result-prefixes="me"> <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="/"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>My Title</title> </head> <body> <xsl:apply-templates select="me:root/me:element/*"/> </body> </html> </xsl:template> <xsl:template match="*"> <xsl:element name="{name()}"> <xsl:copy-of select="@*"/> <xsl:apply-templates/> </xsl:element> </xsl:template> </xsl:stylesheet> 

when this conversion is applied to the provided XML document :

 <me:root xmlns:me="http://stackoverflow.com/xml" xmlns="http://www.w3.org/1999/xhtml"> <me:element> <p>Some HTML code here.</p> </me:element> </me:root> 

required, the correct result is obtained :

 <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>My Title</title> </head> <body> <p>Some HTML code here.</p> </body> </html> 
+6
source

All Articles