views:

1668

answers:

4

Can anyone please suggest an XPath expression format that returns a string value containing the concatenated values of certain qualifying child nodes of an element, but ignoring others:

<div>
    This text node should be returned.
    <em>And the value of this element.</em>
    And this.
    <p>But this paragraph element should be ignored.</p>
</div>

The returned value should be a single string:

This text node should be returned. And the value of this element. And this.

Is this possible in a single XPath expression?

Thanks.

A: 

This look that works:

Using as context "/div/":

"text() | em/text()"

Or without the use of context:

"/div/text() | /div/em/text()"

It's ok?

If you want to concat the first two strings, use this:

"concat(/div/text(), /div/em/text())"
eLZahR
Thanks. This is a good step in the right direction. But I can't see how to concatenate the results. When I wrap this in a call to the string() function, it only returns the value of the first selected node.
Tim Coulter
Yes, and, as you could see, my solution does the same as the "correct" solution.. ¬¬You can concat(...) nodes, but, you wont see the third "text".Try this: concat(/div/text(), /div/em/text())
eLZahR
A: 
/div//text()

double slash forces to extract text regardless of intermediate nodes

Dewfy
+2  A: 

You can use

/div//text()[not(parent::p)]

to capture the wanted text nodes. The concatenation itself cannot be done in XPath, I recommend doing it in the "outside" application.

Tomalak
Thanks - you're absoluately right. I just read the XPath reference and discovered that all string functions implicitly work on the first node in a node-set, so there's consequently no way to combine selection and concatenation.
Tim Coulter
In Xpath 2.0 this is done easily -- see my answer :)
Dimitre Novatchev
+3  A: 

In XPath 2.0 :

string-join(/*/node()[not(self::p)], '')

Dimitre Novatchev
+1 Traditionally, I leave the XPath 2.0 answers to you. ;-)
Tomalak