Subject: Re: [xsl] MSXML ancestor-or-self From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx> Date: Wed, 7 Mar 2001 19:12:01 +0000 |
Hi Richard, > Ok my example is a bit poor sorry for that but really my context is > C with a file like... > > <A> > <P name="hello" value="blue"/> > <P name="aval" value="uppest"/> > <B> > <P name="bval" value="upper"/> > <P name="goodbye" value="red"/> > <P name="hello" value="green"/> > <C> > <P name="goodbye" value="yellow"/> > </C> > <P name="goodbye" value="orange"/> > </B> > </A> > > Expecting output like... > ;goodbye=yellow;hello=green;bval=upper;hello=uppest I think that you want (a) the children of the current node and (b) the preceding-siblings of any ancestors of the current node (or the current node itself). So that gives you: P | ancestor-or-self::*/preceding-sibling::P Now, from that set of nodes, you want the final P element with a particular 'name' attribute. So you want to cycle over those P elements (in reverse document order) and only output information for those P elements for which there's no following P element with the same name attribute that's also in the list: <xsl:variable name="Ps" select="P | ancestor-or-self::*/preceding-sibling::P" /> <xsl:for-each select="$Ps"> <xsl:sort select="position()" data-type="number" order="descending" /> <xsl:if test="not(following::P [@name = current()/@name and count(.|$Ps) = count($Ps)]"> <xsl:text />;<xsl:value-of select="@name" /> <xsl:text />=<xsl:value-of select="@value" /> </xsl:if> </xsl:for-each> You could also do it with a key, which may be a little more efficient and would allow you to number the P elements if you wanted to. Define a key to easily access the P elements by name: <xsl:key name="Ps" match="P" use="@name" /> Give a particular name, the key will produce all the P elements in the document with that name. To find the one that you want, you need to filter it according to those P elements that are in your $Ps list: key('Ps', $name)[count(.|$Ps) = count($Ps)] and then take the last of those in document order: key('Ps', $name)[count(.|$Ps) = count($Ps)][last()] So to get the P elements that are the nearest, you need the hideous expression: $Ps[count(.|key('Ps', @name)[count(.|$Ps) = count($Ps)][last()]) = 1] You can use this expression as the path for the xsl:for-each: <xsl:for-each select="$Ps[count(.|key('Ps', @name) [count(.|$Ps) = count($Ps)][last()]) = 1]"> <xsl:sort select="position()" data-type="number" order="descending" /> <xsl:text />;<xsl:value-of select="@name" /> <xsl:text />=<xsl:value-of select="@value" /> </xsl:for-each> I hope that helps, Jeni --- Jeni Tennison http://www.jenitennison.com/ XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
RE: [xsl] MSXML ancestor-or-self, Richard Mitchell | Thread | RE: [xsl] MSXML ancestor-or-self, Chris Bayes |
Re: [xsl] [exsl] EXSLT 1.0 - Common, David Carlisle | Date | RE: [xsl] MSXML ancestor-or-self, Chris Bayes |
Month |