[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] Re: how to get position of node in node-set
Erwin,
At 12:32 PM 9/11/2003, David wrote: Node sets are sets and so don't have an intrinsic order. So nodes don't really have a position in a set (you can't for example sort the nodes and save the sorted list in a set) Of course you can try, but then in XSLT you have a result-tree-fragment, not a node set, which is where my answer (of a few minutes ago) starts. (Sorry if this assumption on my part was incorrect.) In XSLT 1.0, whether a variable refers to a node set or to an RTF, depends on how it's created. For example, if (using a key-based technique to de-duplicate) you declare your variable like this: <xsl:variable name="legend" select="//entry[count(.|key('entries-by-text',@text)[1])=1]"/> you'll have a true node set, in which case all David's admonitions apply. They are not in order within $legend, and if you process them using for-each or apply-templates, they'll be processed in the order they appear in the source document. If, however, in order to sort the nodes, you say <xsl:variable name="legend"> <xsl:apply-templates select="//entry" mode="de-duplicate"> <xsl:sort select="@text"/> </xsl:apply-templates> </xsl:variable> you'll get your order but you won't have a node set, rather an RTF. To convert an RTF to a node-set requires the extension function in XSLT 1.0. Then you can operate on it again. The only things you can do with an RTF are copy it to the result (as many times as you like :-), or turn it into a string and do stuff with that. (David continues) You can ask what is the position if the nodes in the set were sorted into document order, although actually it's not so easy. If the nodes are siblings and you are on <entry text="ccc"/> then you want count(preceding-sibling::entry)+1 however you only want to count nodes that are in $legend so that would be count(preceding-sibling::entry[@text=$legend])+1 Unfortunately this counts the preceding siblings whose @text attribute has a string value equal to the value of some node in $legend ... maybe not so useful. if your text attribute uniquely determines the node, Right (but Erwin said it wasn't: bummer). or something like count(preceding-sibling::entry[count(.|$legend)=count($legend)]+1 otherwise. That's very sneaky, and might just work. *If* your nodes are siblings (I'm betting they're not). They are all pure xpath solutions, or you could use xsl, as in Which suggests a way to avoid the node-set() extension ... assuming $legend is a node set (which has no intrinsic order): <xsl:template match="entry"/> <xsl:variable name="text" select="@text"/> <xsl:for-each select="$legend"> <xsl:sort select="@text"/> <xsl:if test="@text=$text"> <xsl:value-of select="position()"/> </xsl:if> </xsl:for-each> </xsl:template> Who said it's not possible in XSLT 1.0? (Thanks, David.) Will the language be easier or harder when RTFs disappear and become node sequences? Who's to say? Cheers, Wendell
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
|
PURCHASE STYLUS STUDIO ONLINE TODAY!Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced! Download The World's Best XML IDE!Accelerate XML development with our award-winning XML IDE - Download a free trial today! Subscribe in XML format
|