3

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.

2 Answers 2

3

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".

Sign up to request clarification or add additional context in comments.

3 Comments

I think the * is a typo, yes?
@pguardiario It certainly was, yes. Thanks.
Good answer, but there are some peculiarities to be considered, such as the many times unnecessary use of // and not taking into account surrounding white space.
2

You have generally found the right answer:

//text()[.="foo"] 

However, please note the following:

  1. 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()

  2. 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' 

1 Comment

You get the accept mark because: you confirmed what seemed to work; you are not me; the excellent note on normalize-space. Thanks (as always) for sharing your XPath expertise.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.