Subject: Re: [xsl] Can I use xsl:key to select elements up to certain ancestor From: "Syd Bauman s.bauman@xxxxxxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> Date: Wed, 30 Aug 2017 19:19:16 -0000 |
I think there may be a more efficient way to do this overall, but certainly if you declare those @id attributes as ID, then you could use the id() function. E.g.: --------- <?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="topicID" select="ancestor-or-self::*[@id][1]/@id"/> <xsl:variable name="ancestors-in-topic" select="ancestor-or-self::*[ ancestor-or-self::* intersect id($topicID) ]"/> <xsl:copy> <xsl:attribute name="topic" select="$topicID"/> <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> --------- works iff you declare the @id attrs as type ID: --------- <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE bars [ <!ELEMENT bars ( bar+ )> <!ATTLIST bars id ID #IMPLIED> <!ELEMENT bar ( bar | div )+> <!ATTLIST bar id ID #IMPLIED> <!ELEMENT div ( bar | div | p )+> <!ELEMENT p EMPTY > ]> <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> --------- > 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> > -- Syd Bauman, EMT-Paramedic Senior XML Programmer/Analyst Northeastern University Women Writers Project s.bauman@xxxxxxxxxxxxxxxx or Syd_Bauman@xxxxxxxxxxxxxxxx
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Can I use xsl:key to sele, Wolfgang Laun wolfga | Thread | Re: [xsl] Can I use xsl:key to sele, Michael Kay mike@xxx |
Re: [xsl] Can I use xsl:key to sele, David Carlisle d.p.c | Date | Re: [xsl] Can I use xsl:key to sele, Wolfgang Laun wolfga |
Month |