I don't know of a tool but a few basic concepts will help you here.
//transaction
will select all elements named transaction
in no namespace, located anywhere in your source document.
- the
[...]
expression is a predicate, which is evaluated once for each element selected by the path step it is attached to, and which filters the list to extract only those nodes for which the predicate is true.
To break such an expression down for debugging you'd have to start from the left hand end and add a step at a time, inspecting the results as you go. For a predicate you'd have to manually iterate over the results of the expression that the predicate is attached to, and then evaluate (parts of) the predicate expression with the context node set to each node in that list in turn. Exactly how you do that depends on the XPath tool or library you are using.
So in this specific case we're selecting all transactions whose sumPrice
value is different from the value of
sum(id(@products) /@price)
id(@products)
takes the value of the products
attribute on the transaction
being tested, splits it up at whitespace into a series of tokens, then looks up the set of elements in the document that have an ID attribute (which means an attribute of type ID according to the document's DTD - it may not necessarily be called id
) whose value is the same as any of those tokens. Finally /@price
then gives you the price
attribute for each of those elements, and sum
totals them all up. For example, given this XML:
<!DOCTYPE root [
<!-- rest of DTD omitted -->
<!ATTLIST product ident ID #REQUIRED>
]>
<root>
<transactions>
<transaction sumPrice="5" products="prod1 prod2" />
<transaction sumPrice="10" products="prod2 prod3" />
</transactions>
<product ident="prod1" price="3" />
<product ident="prod2" price="2" />
<product ident="prod3" price="4" />
</root>
The expression
//transaction[@sumPrice != sum(id(@products)/@price)]
would select the second transaction (as the sum of the prod2
and prod3
prices is not 10) but would not select the first (because prod1
+ prod2
gives 5).