Re: [xsl] Can I use xsl:key to select elements up to certain ancestor

Subject: Re: [xsl] Can I use xsl:key to select elements up to certain ancestor
From: "Wolfgang Laun wolfgang.laun@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Wed, 30 Aug 2017 19:24:14 -0000
Wouldn't assigning any element with an @id to a temporaty document and
running rules against this reduce the overhead?
-W

On 30 August 2017 at 21:08, David Carlisle d.p.carlisle@xxxxxxxxx <
xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:

> You seem to be listing ancestor-or-self rather than ancestor, I think
> you only need to go up the ancestor axis once in each case, something
> like
>
> <xsl:stylesheet version="2.0"
>         xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
>
>
>  <xsl:template match="/">
>   <xsl:apply-templates select="//p"/><!-- just for testing-->
>  </xsl:template>
>
>
>  <xsl:template match="*">
>   <xsl:copy>
>    <xsl:apply-templates select="." mode="a"/>
>   </xsl:copy>
>  </xsl:template>
>
>  <xsl:template match="*" mode="a">
>   <xsl:param name="trail" select="()"/>
>   <xsl:apply-templates select="parent::*" mode="a">
>    <xsl:with-param name="trail" select="name(),$trail"/>
>   </xsl:apply-templates>
>  </xsl:template>
>
>  <xsl:template match="*[@id]" mode="a">
>   <xsl:param name="trail" select="()"/>
>    <xsl:copy-of select="@id,'Ancestors:', name(), $trail"/>
>  </xsl:template>
>
> </xsl:stylesheet>
>
>
> which makes
>
>
> <p id="x13">Ancestors: bar div p</p>
>
> On 30 August 2017 at 19:49, Michael MC<ller-Hillebrand mmh@xxxxxxxxx
> <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:
> > Hi all,
> >
> > I had an embarrassing moment today, when I found that the source of a
> severe performance problem was sitting in front of the screen.
> >
> > Using XSLT 2.0 I am transforming elements and at many points I have to
> look up the ancestor axis, but only up to an element with an attribute
> "id". Basically I have a deeply nested structure of topics and I want to
> analyze ancestors inside the current topic.
> >
> > The nearest topic is easy to find:
> >
> > <xsl:variable name="topic" select="ancestor-or-self::*[@id][1]"
> as="element()"/>
> >
> > And then I was doing the following to find all ancestors that share the
> same "topic ancestor":
> >
> > <xsl:variable name="ancestors-in-topic"
> >   select="ancestor-or-self::*[ancestor-or-self::* = $topic]"
> as="element()*"/>
> >
> > This did not what I expected and also wasted a lot of resources because
> the predicate was true for all or most elements. After some testing I went
> with this:
> >
> > <xsl:variable name="ancestors-in-topic"
> >   select="ancestor-or-self::*[ancestor-or-self::*/generate-id() =
> generate-id($topic)]" as="element()*"/>
> >
> > Since that calculation is done very often I am wondering if xsl:key
> could be used to speed things up?
> >
> > Any pointers are very welcome, as always, thanks,
> >
> > - Michael
> >
> > PS: My sample XML and XSLT below.
> >
> > <?xml version="1.0" encoding="UTF-8"?>
> > <bars id="x0">
> >   <bar id="x1">
> >     <bar id="x11">
> >       <bar id="x12">
> >         <div>
> >           <bar id="x13">
> >             <div>
> >               <p/>
> >             </div>
> >           </bar>
> >         </div>
> >       </bar>
> >     </bar>
> >   </bar>
> > </bars>
> >
> >
> > <?xml version="1.0" encoding="UTF-8"?>
> > <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
> xmlns:xs="http://www.w3.org/2001/XMLSchema"; version="2.0">
> >   <xsl:output method="xml" indent="yes" omit-xml-declaration="no"/>
> >   <xsl:strip-space elements="*"/>
> >
> >   <xsl:template match="p">
> >     <xsl:variable name="topic" select="ancestor-or-self::*[@id][1]"
> as="element()"/>
> >     <xsl:variable name="ancestors-in-topic" select="ancestor-or-self::*[
> ancestor-or-self::*/generate-id() = generate-id($topic)]"
> as="element()*"/>
> >     <xsl:copy>
> >       <xsl:attribute name="topic" select="$topic/@id"/>
> >       <xsl:text>Ancestors: </xsl:text>
> >        <xsl:sequence select="$ancestors-in-topic/name()"/>
> >     </xsl:copy>
> >   </xsl:template>
> >
> >   <xsl:template match="* | @*">
> >     <xsl:copy>
> >       <xsl:apply-templates select="@*, node()"/>
> >     </xsl:copy>
> >   </xsl:template>
> > </xsl:stylesheet>
> >
> >
> > Expected output for <p>: <p topic="x13">Ancestors: bar div p</p>

Current Thread