Subject: Re: [xsl] How to output the unused namespaces in the XML document? From: Hermann Stamm-Wilbrandt <STAMMW@xxxxxxxxxx> Date: Tue, 31 Aug 2010 16:58:42 +0200 |
Evan, > Your solution includes a lot of repeat messages. You also don't check > for whether attributes use the namespace. Here's one that avoids both > problems: > > <xsl:template match="/"> > <xsl:for-each select="//namespace::*[not(. = > (preceding::*|../ancestor::*)/namespace::*)]"> > <xsl:if test="not((//* | //@*)[namespace-uri(.) = current()])"> > This namespace is unused: <xsl:value-of select="."/> > </xsl:if> > </xsl:for-each> > </xsl:template> nice solution! > Neither of our solutions checks for unused prefixes, e.g., if the > document had multiple declarations for the same URI but uses only one of > the prefixes on element/attribute names. That could be done in XSLT 2.0, > but whether or not it would work in XSLT 1.0 is dependent on how your > processor implements name(). (XPath 2.0 provides direct access to what > prefix was used, but XPath 1.0 does not.) Find the little modification to your stylesheet for making it work for unused prefix detection as diff below. This solution works fine for these XSLT processors: Chrome, DataPower, Internet Explorer, Opera, Safari, Saxon, Xalan, xsltproc It does not work for Firefox because Firefox does not support the namespace:: axis at all. $ diff unused-namespace.xsl unused-prefix.xsl 10,11c10,12 < <xsl:if test="not((//* | //@*)[namespace-uri(.) = current()])"> < This namespace is unused: <xsl:value-of select="."/> --- > <xsl:if test="not((//* | //@*)[starts-with(name(.), concat (substring-before(concat(name(current()),':'),':'),':'))])"> > This namespace prefix is unused: <xsl:value-of select="name()"/> > <br/> $ $ cat nsu.xml <?xml-stylesheet href="unused-namespace.xsl" type="text/xsl"?> <a><b xmlns:ns1="urn:same" xmlns:ns2="urn:same" ns1:a="x"/></a> $ $ xsltproc unused-namespace.xsl nsu.xml <html><pre> <br> This namespace is unused: http://www.w3.org/XML/1998/namespace </pre></html> $ $ xsltproc unused-prefix.xsl nsu.xml <html><pre> <br> This namespace prefix is unused: xml<br> This namespace prefix is unused: ns2<br> </pre></html> $ Mit besten Gruessen / Best wishes, Hermann Stamm-Wilbrandt Developer, XML Compiler, L3 WebSphere DataPower SOA Appliances ---------------------------------------------------------------------- IBM Deutschland Research & Development GmbH Vorsitzender des Aufsichtsrats: Martin Jetter Geschaeftsfuehrung: Dirk Wittkopp Sitz der Gesellschaft: Boeblingen Registergericht: Amtsgericht Stuttgart, HRB 243294 From: Evan Lenz <evan@xxxxxxxxxxxx> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx Date: 08/30/2010 11:19 PM Subject: Re: [xsl] How to output the unused namespaces in the XML document? Your solution includes a lot of repeat messages. You also don't check for whether attributes use the namespace. Here's one that avoids both problems: <xsl:template match="/"> <xsl:for-each select="//namespace::*[not(. = (preceding::*|../ancestor::*)/namespace::*)]"> <xsl:if test="not((//* | //@*)[namespace-uri(.) = current()])"> This namespace is unused: <xsl:value-of select="."/> </xsl:if> </xsl:for-each> </xsl:template> Things are much easier in XSLT/XPath 2.0 (assuming current() bound to document node): distinct-values(//namespace::*)[not(. = (current()//*|current()//@*)/namespace-uri(.))] Neither of our solutions checks for unused prefixes, e.g., if the document had multiple declarations for the same URI but uses only one of the prefixes on element/attribute names. That could be done in XSLT 2.0, but whether or not it would work in XSLT 1.0 is dependent on how your processor implements name(). (XPath 2.0 provides direct access to what prefix was used, but XPath 1.0 does not.) Keep in mind that the above tests don't guarantee that the namespace isn't "used." If your input document is XSLT, XSD, or any other vocabulary that uses QNames in content, you can't safely assume the namespace isn't being used. Evan -- Evan Lenz Lenz Consulting Group, Inc. http://lenzconsulting.com +1 (360) 297-0087 Costello, Roger L. wrote: > Hi Folks, > > Consider this XML document: > > <?xml version="1.0"?> > <N1:NumberList xmlns:N1="http://www.example1.org" > xmlns:N2="http://www.example2.org"> > <Number>23</Number> > <Number>41</Number> > <Number xmlns:N3="http://www.example3.org">70</Number> > <Number>103</Number> > <Number>99</Number> > <Number>6</Number> > </N1:NumberList> > > Notice that there are three (3) namespaces, but two of them are unused: > > http://www.example2.org > > http://www.example3.org > > I want an XSLT transform that will output all the unused namespaces in the input XML document. > > Here's the solution I came up with: > > > <xsl:template match="*"> > <xsl:variable name="elem" select="." /> > <xsl:for-each select="namespace::*[. != 'http://www.w3.org/XML/1998/namespace']"> > <xsl:variable name="ns" select="." /> > <xsl:if test="not($elem/ancestor::*[namespace::* = $ns])"> > <xsl:if test="not ($elem/descendant-or-self::*[namespace-uri() = $ns])"> > This namespace is unused: <xsl:value-of select="$ns" /> > </xsl:if> > </xsl:if> > </xsl:for-each> > <xsl:apply-templates select="*" /> > </xsl:template> > > > Is there a better solution? (I am using XSLT 1.0) > > /Roger
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] How to output the unused , Evan Lenz | Thread | Re: [xsl] How to output the unused , Michael Kay |
Re: [xsl] mode computation case, ac | Date | [xsl] Performance with Saxon and Ke, Fabien Tillier |
Month |