Given the desire to use XPath to select an XML Text Node based on its value, is there a better way than:
//*[text()="foo"]/text() I'm assuming that there's something like:
//text()[self="foo"] ...but I don't know what to put for self.
In XPath the period or dot character . is the self, also known as the "context node".
This query…
//text()[.="foo"] …will select all text nodes with the value of "foo".
// and not taking into account surrounding white space.You have generally found the right answer:
//text()[.="foo"] However, please note the following:
The XPath // pseudo-operator should be avoided as much as possible whenever the structure of the XML document is statically known, because its evaluation causes complete subtrees (in the worst case the complete document tree) to be traversed and is very inefficient. If you know that all text nodes are children of c and all c in the document can be selected by /a/b/c, then use: /a/b/c/text(). If you only know that all text nodes are descendants of c, then it is still much better to use: /a/b/c//text() than //text() or even than //c//text()
Quite often the text nodes contain whitespace that we tend not to notice. In such cases one needs to write:
normalize-space(.) = 'foo' rather than
. = 'foo' normalize-space. Thanks (as always) for sharing your XPath expertise.