Skip to content

Instantly share code, notes, and snippets.

@dolmen
Created October 1, 2010 16:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dolmen/606472 to your computer and use it in GitHub Desktop.
Save dolmen/606472 to your computer and use it in GitHub Desktop.
My answer to StackOverflow #3747049
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- My answer to StackOverflow #3747049 -->
<xsl:output method="text"/>
<xsl:key name="ns" match="//* | //*/@* | //*/processing-instruction()" use="namespace-uri(.)"/>
<xsl:key name="ns-prefixes" match="//* | //*/@*" use="concat(substring-before(name(.), ':'), ':', namespace-uri(.))"/>
<!-- Only the nodes -->
<xsl:variable name="all-nodes" select="//* | //*/@*"/>
<xsl:variable name="all-namespaces" select="//namespace::*"/>
<xsl:template match="/">
Used namespaces:
<xsl:call-template name="output-used-namespaces-ordered"/>
All namespaces:
<xsl:call-template name="output-all-namespaces-ordered"/>
</xsl:template>
<xsl:template name="output-used-namespaces-ordered">
<xsl:apply-templates select="$all-nodes[count(key('ns', namespace-uri(.))[1] | .) = 1]" mode="output-used-namespaces">
<xsl:sort select="namespace-uri(.)"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="* | @*" mode="output-used-namespaces">
<xsl:variable name="ns" select="namespace-uri(.)"/>
<xsl:call-template name="output-namespace">
<xsl:with-param name="ns" select="$ns"/>
<xsl:with-param name="prefixes">
<xsl:call-template name="list-used-prefixes">
<xsl:with-param name="ns" select="$ns"/>
</xsl:call-template>
</xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template name="output-namespace">
<xsl:param name="ns"/>
<xsl:param name="prefixes"/>
<xsl:value-of select="concat(&quot;'&quot;, $ns, &quot;'&quot;, ' ', $prefixes, '&#xA;')"/>
</xsl:template>
<xsl:template name="list-all-prefixes">
<xsl:param name="ns"/>
<xsl:call-template name="list-uniq-name">
<xsl:with-param name="list" select="$all-namespaces[. = $ns]"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="list-used-prefixes">
<xsl:param name="ns"/>
<xsl:call-template name="list-uniq-name">
<xsl:with-param name="list" select="$all-namespaces[. = $ns][starts-with(.., name())]"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="list-uniq-name">
<xsl:param name="list"/>
<xsl:param name="sep" select="', '"/>
<xsl:if test="count($list)">
<xsl:variable name="head" select="name($list[1])"/>
<xsl:variable name="tail" select="$list[name(.) != $head]"/>
<xsl:value-of select="concat(&quot;'&quot;, $head, &quot;'&quot;)"/>
<xsl:if test="count($tail)">
<xsl:value-of select="$sep"/>
<xsl:call-template name="list-uniq-name">
<xsl:with-param name="list" select="$tail"/>
</xsl:call-template>
</xsl:if>
</xsl:if>
</xsl:template>
<xsl:template name="output-all-namespaces-unordered">
<xsl:param name="list" select="$all-namespaces"/>
<xsl:if test="count($list)">
<xsl:variable name="head" select="$list[1]"/>
<xsl:variable name="tail" select="$list[. != $head]"/>
<!-- Output item -->
<xsl:call-template name="output-namespace">
<xsl:with-param name="ns" select="$head"/>
<xsl:with-param name="prefixes">
<xsl:call-template name="list-all-prefixes">
<xsl:with-param name="ns" select="$head"/>
</xsl:call-template>
</xsl:with-param>
</xsl:call-template>
<xsl:call-template name="output-all-namespaces">
<xsl:with-param name="list" select="$tail"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="output-all-namespaces-ordered">
<xsl:for-each select="$all-namespaces">
<xsl:sort select="."/>
<xsl:variable name="cur" select="current()"/>
<xsl:for-each select="$all-namespaces[. = $cur][1][generate-id(.) = generate-id(cur)]">
<xsl:call-template name="output-namespace">
<xsl:with-param name="ns" select="."/>
<xsl:with-param name="prefixes">
<xsl:call-template name="list-all-prefixes">
<xsl:with-param name="ns" select="."/>
</xsl:call-template>
</xsl:with-param>
</xsl:call-template>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment