Q: (XSLT) finding the position of the first occurrence of an attribute value


J

Jorn W Janneck

hello everyone.

i have the sort of question that makes me feel like i am missing the forest
for the trees, so apologies if i am missing the blatantly obvious here. i am
using saxon, and mostly xslt version 1.1 (the unofficial one).

i have a template parameter, say v, which contains a sequence of nodes of
the same kind, say A, which all have an attribute, say n. these attributes
may have different numeric values. i have identified the least of those like
this:
<xsl:variable name="minN" select="min($v/@n)"/>

what i'd like to do now is to compute the index (in v) of the *first* node
whose n attribute has value $minN. iow, i'd like to write something like
<xsl:variable name="pos" select="???"/>

where ??? would be an xpath-expression computing the desired position. so
e.g. if v contained the nodes
<A n="5"/><A n="3"/><A n="4"/><A n="5"/><A n="3"/>
then minN would be 3, and pos should be 2. i have tried a few things that
seemed to produce correct results if there was only one node with the
corresponding attribute value, but i was not successful at finding a
solution that works in cases like the one above.

any input is greatly appreciated. thanks for your time.

regards,

-- j
 
Ad

Advertisements

D

Dimitre Novatchev

Jorn W Janneck said:
hello everyone.

i have the sort of question that makes me feel like i am missing the forest
for the trees, so apologies if i am missing the blatantly obvious here. i am
using saxon, and mostly xslt version 1.1 (the unofficial one).

i have a template parameter, say v, which contains a sequence of nodes of
the same kind, say A, which all have an attribute, say n. these attributes
may have different numeric values. i have identified the least of those like
this:
<xsl:variable name="minN" select="min($v/@n)"/>

There is no function min() in XPath 1.0
what i'd like to do now is to compute the index (in v) of the *first* node
whose n attribute has value $minN. iow, i'd like to write something like
<xsl:variable name="pos" select="???"/>

In the general case this is:

count(set:leading($v[@n = $minN][1])) + 1

where set:leading is the identically named extention function from EXSLT.

In case if all nodes in $v belong to the same document, then one can use
this XPath expression:

count(
$v[count(. | $v[@n = $minN][1]/preceding::*) = count($v[@n =
$minN][1]/preceding::*)
or
count(. | $v[@n = $minN][1]/ancestor::*) = count($v[@n =
$minN][1]/ancestor::*)
]
) + 1

Or you may first produce from $v an RTF, convert it to a tree $v1 and then
use just:

count($v1/*[@n = $minN][1]/preceding-sibling::*) + 1



=====
Cheers,

Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL
 
D

Dimitre Novatchev

Also, for an efficient XSLT implementation of set:leading() see my
article in xml.com "EXSLT for MSXML" at:

http://www.xml.com/pub/a/2003/08/06/exslt.html


=====
Cheers,

Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL



Dimitre Novatchev said:
Jorn W Janneck said:
hello everyone.

i have the sort of question that makes me feel like i am missing the forest
for the trees, so apologies if i am missing the blatantly obvious here. i am
using saxon, and mostly xslt version 1.1 (the unofficial one).

i have a template parameter, say v, which contains a sequence of nodes of
the same kind, say A, which all have an attribute, say n. these attributes
may have different numeric values. i have identified the least of those like
this:
<xsl:variable name="minN" select="min($v/@n)"/>

There is no function min() in XPath 1.0
what i'd like to do now is to compute the index (in v) of the *first* node
whose n attribute has value $minN. iow, i'd like to write something like
<xsl:variable name="pos" select="???"/>

In the general case this is:

count(set:leading($v[@n = $minN][1])) + 1

where set:leading is the identically named extention function from EXSLT.

In case if all nodes in $v belong to the same document, then one can use
this XPath expression:

count(
$v[count(. | $v[@n = $minN][1]/preceding::*) = count($v[@n =
$minN][1]/preceding::*)
or
count(. | $v[@n = $minN][1]/ancestor::*) = count($v[@n =
$minN][1]/ancestor::*)
]
) + 1

Or you may first produce from $v an RTF, convert it to a tree $v1 and then
use just:

count($v1/*[@n = $minN][1]/preceding-sibling::*) + 1



=====
Cheers,

Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL
 
Ad

Advertisements

J

Jorn W Janneck

Dimitre:

Thanks so much for your extensive and knowledgeable answer. Not only did you
solve my problem, it was also quite instructive. I really appreciate the
effort you put into it. I had stared at that problem for quite a while.

[snip several suggestions]
Or you may first produce from $v an RTF, convert it to a tree $v1 and then
use just:

count($v1/*[@n = $minN][1]/preceding-sibling::*) + 1

This is what I ended up doing. Does the job beautifully.

Thanks again,

-- j
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top