RE: [xsl] filtering elements by single xpath

Subject: RE: [xsl] filtering elements by single xpath
From: "Tomas Kolaci" <kolaci@xxxxxxx>
Date: Thu, 6 Apr 2006 11:24:54 +0200
 Thank you, Michael, for all these useful hints! Br, Tomas

> -----Original Message-----
> From: Michael Kay [mailto:mike@xxxxxxxxxxxx]
> Sent: Wednesday, April 05, 2006 7:12 PM
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: RE: [xsl] filtering elements by single xpath
> 
> Try to avoid using copy-of here - copying nodes is expensive and often
> unnecessary.
> 
> The simplest way is to avoid the inner predicate:
> 
>  <xsl:variable
>      name="filtered-items"
>      select="item[/root/item-filter/allow-items/@with-name = @name]"
>  />
> 
> Saxon 8.x will do this automatically, but 6.x and other processors will
> perform better if you pull the constant expression out of the loop:
> 
> <xsl:variable name="names"
> select="/root/item-filter/allow-items/@with-name"/>
> <xsl:variable
>      name="filtered-items"
>      select="item[$names = @name]"
>  />
> 
> Better still is to use keys:
> 
> <xsl:key name="k" match="allow-items" use="@with-name"/>
> 
> then
> 
> select="item[key('k', @name)]"
> 
> Michael Kay
> http://www.saxonica.com/
> 
> 
> > -----Original Message-----
> > From: Tomas Kolaci [mailto:kolaci@xxxxxxx]
> > Sent: 05 April 2006 15:46
> > To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> > Subject: [xsl] filtering elements by single xpath
> >
> >  Hi!
> >
> >  I'm using XSLT 1.1 and Saxon 6.5.3.
> >
> >  I have following XML structure:
> >
> > <root>
> >    <body>
> >       <item pos="1" name="n1"/>
> >       <item pos="2" name="n2"/>
> >       <item pos="3" name="n2"/>
> >       <item pos="4" name="n3"/>
> >       <item pos="5" name="n4"/>
> >    </body>
> >    <item-filter>
> >       <allow-items with-name="n2"/>
> >       <allow-items with-name="n4"/>
> >    </item-filter>
> > </root>
> >
> > and in template:
> >
> > <xsl:template match="body">
> >    <xsl:variable
> >      name="filtered-items"
> >      select="item[/root/item-filter/allow-items[@with-name =
> > ???/@name]"
> >    />
> >    ...
> > </xsl:template>
> >
> > I'm trying to fill variable filtered-items with elements item
> > with "allowed"
> > name (= there is an element /root/item-filter/allow-items
> > with attribute
> > @with-name containing same value as item's @name)*, but I
> > don't know how to
> > reach current item on ??? position in my select (function
> > current() points
> > to current body element).
> >
> >  I can handle it by sequential processing (copy of item is
> > good enough for
> > my needs):
> >
> > <xsl:variable name="filtered-items">
> >    <xsl:for-each select="item">
> >       <xsl:if
> >         test="/root/item-filter/allow-items[@with-name =
> > current()/@name]">
> >          <xsl:copy-of select="."/>
> >       </xsl:if>
> >    </xsl:for-each>
> > </xsl:variable>
> >
> > but I'm just curious if it is possible to achieve this by
> > single xpath?
> >
> >  Thanks in advance!
> >
> >  Best regards, Tomas
> >
> > *resultant filtered-items content for given example should be:
> >
> > <item pos="2" name="n2"/>
> > <item pos="3" name="n2"/>
> > <item pos="5" name="n4"/>

Current Thread