0

How can I get current node position in Xpath 1.0?

I'm trying /position() but it's not working. I also tried /@position().

D. Caan
  • 1,907
  • 6
  • 22
  • 36

2 Answers2

3

It depends what you mean by "position" - the position() function doesn't necessarily bear any relation to the node's location in the XML tree it belongs to, it simply means the position of the current context node in the "current node list" (and the meaning of that depends on the host language that is evaluating the XPaths, in XSLT for example it means the list of nodes select-ed by the nearest apply-templates or for-each).

If you have an element named foo and you want to know whether it is the first, second, etc. foo within its parent (i.e. the number N you would need to get back to it as ../foo[N]) then you can do this by counting its preceding siblings with the same name

count(preceding-sibling::foo) + 1

However for this you need to know the name up front when you build the XPath expression - pure XPath 1.0 doesn't let you count the number of "preceding siblings that have the same name as the current node".

Some host languages may provide a variable or function that allows this - using XSLT as the example again, there you can use the current() function to refer to the current context node from anywhere in an expression, including inside predicates. In XPath 2.0 you could do it with

for $cur in . return (count(preceding-sibling::*[name() = name($cur)]) + 1)
Ian Roberts
  • 120,891
  • 16
  • 170
  • 183
0
<xsl:template name="node-index-of">
    <xsl:param name="nodes" />
    <xsl:param name="node" />
    <xsl:param name="index" />
    <xsl:choose>
        <xsl:when test="$nodes[position()=$index]=$node">
            <xsl:value-of select="$index"/>    
        </xsl:when>
        <xsl:when test="$index=count($nodes)">
            <xsl:value-of select="$index"/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:call-template name="node-index-of">
                <xsl:with-param name="nodes" select="$nodes" />
                <xsl:with-param name="node" select="$node" />
                <xsl:with-param name="index">
                    <xsl:value-of select="$index+1"/>
                </xsl:with-param>
            </xsl:call-template>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

$index begins from 1