Re: [xsl] Unexpected Context Node at Points in XPath Expression

Subject: Re: [xsl] Unexpected Context Node at Points in XPath Expression
From: Abel Braaksma <>
Date: Wed, 05 Sep 2007 02:34:48 +0200
Michael Terry wrote:
I should look more carefully: the link that my mailprog (thunderbird)
makes of it does not include the trailing dot (as normally a link
wouldn't end on any and the dot it part of the sentence). Anyway, I see
now that the other page *is* different and does contain <h2> tags. And
now both queries select something (and different things). Sorry for my
first mistaken interpretation of your queries...

-- Abel Braaksma

I think I misunderstood what becomes the context node. Take the first one I mentioned:

- count(preceding-sibling::*)]

I thought that while the position() filter was running, 'h2[1]' would
be the context node. Instead, it seems the result of
'following-sibling::*' is the context node? What, does it change the
context node to each item in that set as it applies the filter? I
don't suppose there's a way to refer to the previous context node in a
relative way, is there?

In XSLT 2.0, your expression could be shortened to something like this:

div/h2[1]/following-sibling::*[. &lt;&lt; ../h2[1]/following-sibling::p[1]]

or the inverse, meaning the same:

$input/div/h2[1]/following-sibling::p[1]/preceding-sibling::*[. >> ../h2[1]]

the operator >> or << (here &lt;&lt;) means "after" and "before" respectively. If you are stuck with XSLT 1.0 (I hope not, 2.0 is so much more fun) but, here you go:

[generate-id(following-sibling::p[1]) = generate-id(../h2[1]/following-sibling::p[1])]

This is more readable and understandable if written also for XSLT 2.0:

   [following-sibling::p[1] is ../h2[1]/following-sibling::p[1]]

What we actually do here is selecting the stop-point (the P element) from two perspectives: from the parent (naive implementation would do ../p[1], but there are more P around, so we need to check it relative, following, to our h2[1], hence: ../h2[1]/following-sibling[1]) and holding every next P element (following-sibling::p[1]) against it for identity comparison.

Identity comparison is done in XSLT 2.0 with the 'is' operator. In XSLT 1.0 you have to pull a 'trick' with the generate-id() function which is guaranteed to output a different identifier string for each node in the input tree.

Hope this makes it more clear to you.

-- Abel Braaksma

PS: when you use functions like generate-id(), you cannot use it inside the XPath Checker, you can only do it inside an XSLT file. The XPath checker gives an error, probably because it is an XSLT function and not an XPath function. And of course, XPath checker cannot deal with XSLT 2.0, use the open source Saxon, Gestalt or the free for personal use AltovaXML for that.

Current Thread