I\'m hesitating whether to write preceding
or preceding-sibling
in XSL such as an example xml below.
It looks to me that you are (also) asking what these axes actually do. As Michael and Har already pointed out, it really depends on the larger picture whether or not to choose one over the other. In practice, the need for preceding
, and to a lesser extend preceding-sibling
can be a sign of code smell and their performance can be detrimental, depending on input and predicates.
Let's suppose your input is slightly different:
<sales_division>
<team area="New York">
<staff>John</staff>
</team>
<team area="Tokyo">
<staff>Sato</staff>
<staff>Tanaka</staff>
</team>
<staff />
<team area="Osaka">
<staff>Ueda</staff>
<staff>Suzuki</staff>
</team>
</sales_division>
1) preceding-sibling::team/staff[1]
The preceding-sibling axis is a reverse axis, which means it goes from bottom to top through your siblings. The staff
step is actually child::staff
, which is itself a forward step.
Here you are asking:
team
staff
2) preceding::staff[2]
The preceding axis is also a reverse axis, but instead of going over the siblings, it goes over all nodes that have already been passed (meaning: if a node is still in the present ancestor axis, it is not selected), depth first (meaning: text nodes in staff
come before staff
children, which come before team
siblings).
Here you are asking:
staff
, that is empty, Tanaka, Sato and John (in that order).3) ../team[1]/staff[1]
..
is short for parent::node()
. It means take the parent of the current node (which is the root element sales_division
)
Here you are asking:
sales_division
team
staff
So, in conclusion, it depends on the actual XML structure. Typical use-cases for preceding-sibling
are where the order of your XML is known and meaningful (for instance, two coordinates, where the previous sibling is longitude, the current is latitude).
In practice, I see more often that you need an element that is a sibling before or after the current node. In that case, the ..
(parent) syntax is probably the best way to go, possibly excluding the current node from the node set. This is easier in XSLT 2.0 and 3.0 than in 1.0.
If you know exactly what is in your XML, you don't need any of these expressions, you could just write "Sato". You presumably need to navigate the XML because you know something about its structure but you don't have complete knowledge of its content. So the way you navigate it is by using what you know in order to discover what you don't know. This makes it impossible for us to help you, because you haven't told us how much of the XML is variable and how much is fixed.
It is better to write a meaningful XPath as it is easier to read and will be easier to maintain. So, I would say I prefer the first way, since it is the closest to the English description of your intention :
preceding-sibling::team/staff[1]
or even more specific (if necessary) :
preceding-sibling::team[@area='Tokyo']/staff[1]
Also, element positions is generally less meaningful and tends to break easily upon slight changes on the XML arrangement, so I'd suggest not to rely on element position index too much.