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

Re: [xsl] Specify/determine element's "logical" parent


Subject: Re: [xsl] Specify/determine element's "logical" parent
From: David Carlisle <davidc@xxxxxxxxx>
Date: Fri, 24 Sep 2004 10:22:32 +0100

> >           <xsl:value-of select="key( 'ids', (@parentid|../@id)[last()
> > ])/@id" />
> > 
> 
> I think this says to look up the element pointed to by the key @parentid if it
> is defined, ../@id otherwise, but I am not sure I understand the [last()] -
> does that mean that if both parentid and ../@id are defined, ../@id will be
> used (in which case I want the reverse, first()?  or is this just defensive
> programming, habit or something else?

XPath is an expression based language in which (pretty much always) any
expression can be used anywhere, and it has the same meaning.

Especially in the area of conditionals it's often easy to fall in to the
trap of giving the same operator different _readings_ in different
contexts (eg often its helpful to read | as "or" but it is really set
union and different from the boolean or which is "or" in XPath). Which
ramble is just a long way of saying that to understand a long XPath you
can always read it from the inside out.



@parentid 

selects the node set of nodes matching that, which is a set of 0 or 1
attribute nodes (depending on whether the current element has a
parentid)


 ../@id


selects the node set of nodes matching that, which is a set of 0 or 1
attribute nodes (depending on whether the parent of the current element
has an id)


| is set union, so

(@parentid|../@id)

is the node set of 0 1 or 2 nodes consisting of at most one id node from
the patrent and one parentid from here.

In the case that there are two nodes in this set you want (or at least I
thought you wanted) the parentid from the current node. In document
order the attributes of a parent come before the current element which
comes before the current elements attributes so if if this node set does
have two nodes, @parentid is the last of them so

(@parentid|../@id)[last()]

last() returns a number, the position of teh last node in document order
(ie its the cardinality of the set) If you use a number in a filter
predicate it is short for


(@parentid|../@id)[position()=last()]

The predicate position()=last() is true just for the last node in
document order and false for all other nodes in the set, so this is a
node set of 0 or 1 nodes consisting of an 
@parentid if there is one and a ../@id otherwise.

key( 'ids', (@parentid|../@id)[last()])

looks up the value of that attribute node as a key value in the 'ids'
key and returns the node (or nodes) that matches (if there is one).
the key was defined by xsl:key to match *[@id] that is, any element taht
has an id attribute, so an element node will be returned.

key( 'ids', (@parentid|../@id)[last()> ])/@id

and that selects teh id attribute of that element node.


> I had expected the system (IE) to throw an error in this undefined case, but
> it recovers (somewhat randomly) I guess.

It's not random, it takes the last in the stylesheet, that is teh
specified optional recovery acyion in the XSLt spec.  A system built in
a browser like IE typically takes every allowed possibility to avoid
making run time errors, that being the way of life in browser land.

A command line system like saxon is much better for debugging it gives
lots of helpful warnings, and in particular has a three way switch that
lets you choose whether errors that teh XSLt spec says are recoverable
are
0) silently ignored and the recovery actiojn taken
1) warning given and recovery action taken
2) stop with a message and fatal error

David

________________________________________________________________________
This e-mail has been scanned for all viruses by Star. The
service is powered by MessageLabs. For more information on a proactive
anti-virus service working around the clock, around the globe, visit:
http://www.star.net.uk
________________________________________________________________________


Current Thread
Keywords