xsl-list
[Top] [All Lists]

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

2007-09-04 17:44:57
Awesome, thanks very much. It's quite clear. Offhand I can't verify
whether my production tools (a so-called scripting addition for
AppleScript, by Satimage) use XSLT 2.0. I'll check it out tonight. -
mt

On 9/4/07, Abel Braaksma <abel(_dot_)online(_at_)xs4all(_dot_)nl> wrote:
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:

id('bodyContent')/h2[1]/following-sibling::*[position()<count(following::p[1]/preceding-sibling::*)
- 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:

    div/h2[1]/following-sibling::ul
    [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:

    div/h2[1]/following-sibling::ul
    [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.

Cheers,
-- 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.



--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: 
<mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--



--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--