I'm writing an XSLT 1.0 stylesheet to transform multi-namespace XML documents to HTML. At some place in the result HTML I want to list all the namespaces, that occured in the document.
Is this possibile?
I thought about something like
<xsl:for-each select="//*|//@*">
<xsl:value-of select="namespace-uri(.)" />
</xsl:for-each>
but of course I'd get gazillions of duplicates. So I'd have to filter somehow, what I already printed.
Recursively calling templates would work, but I can't wrap my head around how to reach all elements.
Accessing //@xmlns:*
directly doesn't work, because one can't access this via XPath (one isn't allowed to bind any prefix to the xmlns:
namespace).
This transformation:
when applied on this XML document:
produces the wanted, correct result:
Update:
As @svick has commented, the above solution will still occasionally produce duplicate namespaces such as with the following XML document:
the namespace
"mynamespace2"
will be produced twice in the output.The following transformation fixes this issue:
when this transformation is applied on the above XML document, it produces only all unique namespaces in the document:
Part II: An XSLT 2.0 solution.
The XSLT 2.0 solution is a simple XPath 2.0 one-liner:
Another without extension functions:
Output (With Dimitre's input sample):
EDIT: Also this XPath expression:
As proof, this stylesheet:
Output:
EDIT 4: Same efficient as two pass transformation.
This stylesheet:
Output:
EDIT 5: When you are dealing with a XSLT processor without
namespace
axe implementation (Like TransforMiix), you can only extract namespaces actually used with this stylesheet:TransforMiix output: