Subject: [xsl] Can I use xsl:key to select elements up to certain ancestor From: "Michael Müller-Hillebrand mmh@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> Date: Wed, 30 Aug 2017 18:49:12 -0000 |
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 -> |
---|---|---|
Re: [xsl] XPath string comparison o, Eliot Kimber ekimber | Thread | Re: [xsl] Can I use xsl:key to sele, David Carlisle d.p.c |
Re: [xsl] XPath string comparison o, Syd Bauman s.bauman@ | Date | Re: [xsl] Can I use xsl:key to sele, David Carlisle d.p.c |
Month |