Re: Finding namespace definitions (Was: Re: check if nodes match xpath expression)

Subject: Re: Finding namespace definitions (Was: Re: check if nodes match xpath expression)
From: Dimitre Novatchev <dnovatchev@xxxxxxxxx>
Date: Mon, 4 Dec 2000 05:23:15 -0800 (PST)
Jeni,

I'd have been only too happy to confirm the fact you've found a pure
XSLT solution to a problem, which until now had been considered
impossible (e.g. see Mike Kay's book, page 60, 66).

Unfortunately, the following simple example demonstrates why and what
cannot be achieved in pure XSLT only:

<simple>
   <node1 xmlns:zzz="myNamespace">
	<node21 xmlns:zzz="myNamespace"/>
   </node1>
</simple>

Your template will not produce the namespace definition for the
'node21' element. Therefore, the source code of the original xml
document will lack some of the namespace definitions.

To summarise -- this time Mike wasn't proven wrong... :o)))

Thank you very much for your interest!

Cheers,
Dimitre Novatchev.

--- Jeni Tennison <mail@xxxxxxxxxxxxxxxx> wrote:
> Dimitre,
> 
> > 2. The stylesheet that does 100% of the processing (although
> heavily
> > based on the original MS defaultss.xsl) is pure XSLT and could
> easily
> > be used with another XSLT processor. The only extension function
> that
> > is used is to get the "xml" property of a node. Something like this
> > will be necessary regardless of which XSLT processor is being used.
> The
> > reason is that it is not possible without extensions to determine
> the
> > fact (of) and exact location of a namespace definition. 
> 
> As long as you're happy with pinpointing the element that holds it
> (rather than e.g. where it occurs within the start tag), then can't
> you do that with judicious use of the namespace:: axis?
> 
> The namespace definitions that are in scope for a particular element
> can be accessed with:
> 
>   namespace::*
> 
> The element a namespace is defined on is the top-most ancestor
> element
> that has a namespace:: with the same name() and string value, i.e.:
> 
>   ancestor-or-self::*[namespace::*[name() = $namespace-prefix and
>                                    . = $namespace-uri]][last()]
> 
> So, for example, you can print what namespaces an element defines
> with
> the template:
>                                    
> <xsl:template match="*" mode="namespace">
>    <xsl:for-each select="namespace::*">
>       <xsl:if test="not(../ancestor::*[namespace::*[name() =
> name(current()) and
>                                        . = current()]][last()])">
>          <xsl:value-of select="name(..)" /> defines <xsl:text />
>          <xsl:choose>
>             <xsl:when test="name()">xmlns:<xsl:value-of
> select="name()" /></xsl:when>
>             <xsl:otherwise>xmlns</xsl:otherwise>
>          </xsl:choose>
>          <xsl:text />="<xsl:value-of select="." />"
<xsl:text />
>       </xsl:if>
>    </xsl:for-each>
> </xsl:template>
> 
> [As reported here previously, MSXML3 returns 'xmlns:foo' rather than
> simply 'foo' when accessing the name() of the namespace, but this
> does
> not affect the operation of the above.]
> 
> Note also that the 'xml' namespace is always declared on the top
> element: it needs to be filtered out if you want only those
> namespaces
> that are declared explicitly.
> 
> Cheers,
> 
> Jeni
> 
> ---
> Jeni Tennison
> http://www.jenitennison.com/
> 
> 


__________________________________________________
Do You Yahoo!?
Yahoo! Shopping - Thousands of Stores. Millions of Products.
http://shopping.yahoo.com/


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread