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

Discussion in 'XML' started by Jorn W Janneck, Sep 3, 2003.

  1. 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
     
    Jorn W Janneck, Sep 3, 2003
    #1
    1. Advertisements

  2. There is no function min() in XPath 1.0
    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
     
    Dimitre Novatchev, Sep 4, 2003
    #2
    1. Advertisements

  3. 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, Sep 4, 2003
    #3
  4. 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]
    This is what I ended up doing. Does the job beautifully.

    Thanks again,

    -- j
     
    Jorn W Janneck, Sep 5, 2003
    #4
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.