0

I am dealing with an XML vocabulary that has "default values": i.e., if a node does not have a certain subnode, I'd like to find the nearest enclosing node that has that subnode, and use its string value as the value of the original node's subnode.

E.g., if I have a tree

Super_node
    sub_node: XXX
    ...
        context_node
            /* does not have a child with name sub_node */

and no intervening nodes between Super_node and context_node have a child sub_node, I want an expression that evaluates to XXX.

I was thinking that the following query should work, but I always get a node list:

string(ancestor-or-self::*/sub_node[1]/text())

My thinking is that ancestor-or-self::* returns, in reverse document order, the list of context_node, parent_of_context_node, ..., Super_node. I apply the sub_node test to that, and get the list of sub_nodes in that list, again, hopefully, in reverse document order.

I then apply the predicate [1], which should return the first element of that list. However, this predicate seems to be not effective: in my implementation (which I think is based on libxml2), I still receive a list.

What does work, I found after poking around on Stack Exchange a bit, is

string((ancestor-or-self::*/sub_node)[last()]/text())

Why is the predicate [1] above not effective?

user1254127
  • 118
  • 6

1 Answers1

0

The expression

ancestor-or-self::*/sub_node[1]

means

ancestor-or-self::*/(child::sub_node[1])

which selects the first sub_node element child of every ancestor element.

I suspect you were thinking of

(ancestor-or-self::*/sub_node)[1]

which selects all the sub_node children of all the ancestor elements, sorts them into document order, and then returns the first node in this list.

Predicates like [1] bind more strongly than "/".

Michael Kay
  • 156,231
  • 11
  • 92
  • 164