[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

Re: [xsl] namespace aware template matching


Subject: Re: [xsl] namespace aware template matching
From: tom.kirkpatrick@xxxxxxxxxxxx
Date: Thu, 27 Oct 2005 09:32:28 +0100

tom.kirkpatrick@xxxxxxxxxxxx wrote on 27/10/2005 09:03:18:

> I'm trying to do some rather complicated, namespace aware XPath (XSLT1) 
> template matching:
> 
> Given a structure like this, where <dynamic> could actually be any 
number 
> (including 0) of elements in a namespace other than 
'uri://ns-namespace':
> 
> <ns:root xmlns:ns="uri://ns-namespace">
>     <ns:id> id from ns:root/ns:id </ns:id>
>     <dynamic>
>         <ns:article>
>             <dynamic>
>                 <ns:id> id from ns:root/ns:article/ns:id </ns:id>
>             </dynamic>
>         </ns:article>
>         <ns:issue>
>             <dynamic>
>                 <more tags>
>                    <ns:id> id from ns:root/ns:issue/ns:id </ns:id>
>                 </more tags>
>             </dynamic>
>         </ns:issue>
>     </dynamic>
> </ns:root>
> 
> 
> I need a template which matches all <ns:id> elements whoose path from 
the 
> <ns:root> node is simply 'ns:root/ns:article/ns:id'. So I need to be 
able 
> o exclude all elements from any namespace which is not 'ns'.
> 
> What I mean is something like this: (although it doesn't work!)
> 
> <xsl:template match="ns:root/*[namespace-uri() != 
> 'uri://ns-namespace']/ns:article/*[namespace-uri() != 
> 'uri://ns-namespace']/ns:id"/>
> </xsl:template>
> 
> But this doesn't match the case where there are no foreign elements 
(whose 
> namespace is not 'ns') or more than one foreign element in between 
ns:root 
> and ns:article or between ns:article and ns:id.
> 
> 
> The clocest I came was:
> <xsl:template match="ns:id[ancestor::ns:article/ancestor::ns:root]"/>
> 
> But this one doesn't stipulate that the ancestor::ns:article who has an 
> ancestor::ns:root must be the first 'ns' ancestor we meet, so It will 
also 
> match:
> 
> <ns:root xmlns:ns="uri://ns-namespace">
>     <ns:id> id from ns:root/ns:id </ns:id>
>     <dynamic>
>         <ns:test>
>             <ns:article>
>                 <ns:test2>
>                     <dynamic>
>                         <ns:id> id from 
> ns:root/ns:test/ns:article/ns:test2/ns:id </ns:id>
> 
> How can I specify that the ancestor::ns:article element must be the 
first 
> one we come accross when working up the acnestor chain?

originally I had tried saying ancestor::ns:article[1], which did not seem 
to work as it would test to see if the first ancestor element was a 
ns:article, which is not what I want. I want to find the first ns:article 
element up the ancestor chain...

What I have just tried now, which seems to work (fingers crossed) is 
ancestor::ns:article[position()=1], which look very similar, yet seems to 
act differently - in the way that I want it to.

So I end up with 
ns:id/ancestor::ns:article[position()=1]/ancestor::ns:root[position()=1]

Can anyone see any problems with this method? Are there any optimizations 
I could make?


> any thoughts?
> 
> 
> thanks
> 
> -- 
> Tom Kirkpatrick
> Web Developer - Virus Bulletin
> 


-- 
Tom Kirkpatrick
Web Developer - Virus Bulletin


Current Thread
Keywords