Subject: Re: [xsl] Can I use xsl:key to select elements up to certain ancestor From: "David Carlisle d.p.carlisle@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> Date: Wed, 30 Aug 2017 19:08:17 -0000 |
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 |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[xsl] Can I use xsl:key to select e, Michael Müller-Hille | Thread | Re: [xsl] Can I use xsl:key to sele, Wolfgang Laun wolfga |
[xsl] Can I use xsl:key to select e, Michael Müller-Hille | Date | Re: [xsl] Can I use xsl:key to sele, Syd Bauman s.bauman@ |
Month |