Search code examples
xmlxsltxslt-2.0

Obtain the number of specific nodes between a node and its ancestor


Let's say you have the following XML structure (whatever the string values might be, it has very little importance in my case)

<a>
  <b>
    <a>
      <c>
        <a>
          <b>
            <mynode>
            </mynode>
          </b>
          <c>
            <b>
            </b>
          </c>
        </a>
      </c>
      <d>
      </d>
    </a>
  </b>
</a>

When I'm at mynode, I'd like to count all the nodes b that are ancestors of mynode, since the last a node that I have as an ancestor (in other words, the number of b there is between last a and mynode, so here, 1, which is in fact the direct parent in my example).

I feel like I probably have to do something with ancestor::a[last()]//b, and maybe use generate-id() on mynode in a <xsl:test> but I'm not very confident.

What would be the correct thing to do here?


Solution

  • There may be a more elegant way in XSLT 3.0, but in any version you could do:

    count(ancestor::b) - count(ancestor::a[1]/ancestor::b)
    

    If mynode has no b descendants, then:

    count(ancestor::a[1]/descendant::b)
    

    will return the same result. (That's probably what you tried to express by ancestor::a[last()]//b. But the ancestor axis is a reverse axis. The nearest ancestor is the first one, not the last.)