Dave
Dave

Reputation: 63

Select text from a node and omit child nodes

I need to select the text in a node, but not any child nodes. the xml looks like this

<a>
  apples  
  <b><c/></b>
  pears
</a>

If I select a/text(), all I get is "apples". How would I retreive "apples pears" while omitting <b><c/></b>

Upvotes: 6

Views: 3409

Answers (3)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243459

If I select a/text(), all i get is "apples". How would i retreive "apples pears"

Just use:

normalize-space(/)

Explanation:

The string value of the root node (/) of the document is the concatenation of all its text-node descendents. Because there are white-space-only text nodes, we need to eliminate these unwanted text nodes.

Here is a small demonstration how this solution works and what it produces:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

 <xsl:template match="/">
  '<xsl:value-of select="normalize-space()"/>'
 </xsl:template>
</xsl:stylesheet>

when this transformation is applied on the provided XML document:

<a>
 apples
    <b><c/></b>
 pears
</a>

the wanted, correct result is produced:

  'apples pears'

Upvotes: 0

Scott
Scott

Reputation: 106

To retrieve all the descendants I advise using the // notation. This will return all text descendants below an element. Below is an xquery snippet that gets all the descendant text nodes and formats it like Martin indicated.

xquery version "1.0";
let $a := 
<a>
  apples  
  <b><c/></b>
  pears
</a>
return normalize-space(string-join($a//text(), " "))

Or if you have your own formatting requirements you could start by looping through each text element in the following xquery.

xquery version "1.0";
let $a := 
<a>
  apples  
  <b><c/></b>
  pears
</a>
for $txt in $a//text()
return $txt

Upvotes: 0

Martin Honnen
Martin Honnen

Reputation: 167436

Well the path a/text() selects all text child nodes of the a element so the path is correct in my view. Only if you use that path with e.g. XSLT 1.0 and <xsl:value-of select="a/text()"/> it will output the string value of the first selected node. In XPath 2.0 and XQuery 1.0: string-join(a/text()/normalize-space(), ' ') yields the string apples pears so maybe that helps for your problem. If not then consider to explain in which context you use XPath or XQuery so that a/text() only returns the (string?) value of the first selected node.

Upvotes: 4

Related Questions