This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: Improving efficiency of an XPath expression?
- From: Jeni Tennison <jeni at jenitennison dot com>
- To: "Michael Beddow" <mbnospam at mbeddow dot net>
- Cc: XSL-list at lists dot mulberrytech dot com
- Date: Fri, 7 Jun 2002 13:50:27 +0100
- Subject: Re: [xsl] Improving efficiency of an XPath expression?
- Organization: Jeni Tennison Consulting Ltd
- References: <02ca01c20e1c$b4cb9830$0201010a@michaelnt2k>
- Reply-to: xsl-list at lists dot mulberrytech dot com
Hi Michael,
> Now the challenge: given the id attribute value of any one <l>, find
> an XPath expression that will efficiently select a node-set
> containing only: the <lg> that immediately precedes the one where
> the <l> concerned is found, plus the <lg> that is the parent of that
> <l> and the <lg> that immediately follows the one that is the parent
> of the <l> specified. (i.e. "L2063" as input id would return
> precisely the three <lg> elements in the example.)
Assuming that there's only one l with a particular id, try something
like:
/example/lg[l/@id = $targetid][1]/preceding-sibling::lg[1] |
/example/lg[l/@id = $targetid][1] |
/example/lg[l/@id = $targetid][1]/following-sibling::lg[1]
Or, if you can, store the lg that contains the relevant l element in a
variable:
<xsl:variable name="lg" select="/example/lg[l/@id = $targetid][1]" />
... select="$lg/preceding-sibling::lg[1] |
$lg |
$lg/following-sibling::lg[1]" ...
In XPath 2.0, you'd be able to use a general step instead of a
variable, and still get the benefit of only finding the relevant lg
once:
/example/lg[l/@id = $targetid][1]
/(preceding-sibling::lg[1] | . | following-sibling::lg[1])
You could alternatively use something closer to what you had already:
/example/lg[following-sibling::lg[1]/l/@id = $targetid or
l/@id = $targetid or
preceding-sibling::lg[1]/l/@id = $targetid]
but that would mean going through all the lg elements in the document
rather than stopping at the one that contains the relevant l element.
The important things for efficiency here are:
- avoidance of the descendant axis -- step down the lg elements
rather than using //
- using [1], so that the processor only has to make one step rather
than collecting *all* the lg elements and preceding/following
siblings
If you're doing this multiple times in the same transformation, then
setting up a key so that you can quickly find the relevant lg by the
ids of its l elements would be a good idea:
<xsl:key name="lgs" match="lg"
use="preceding-sibling::lg[1]/l/@id |
l/@id |
following-sibling::lg[1]/l/@id" />
and then just use:
key('lgs', $targetid)
Cheers,
Jeni
---
Jeni Tennison
http://www.jenitennison.com/
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list