[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

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


Subject: Re: [xsl] Unexpected Context Node at Points in XPath Expression
From: "Michael Terry" <formido@xxxxxxxxx>
Date: Tue, 4 Sep 2007 17:44:56 -0700

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.online@xxxxxxxxx> 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.


Current Thread
Keywords