How to get all streaming text content in XML using XPath

XML file

<TEXT>
    <DESCR>
         Here is the first part...
         <PLUS>The second</PLUS>
         And the third
    </DESCR>
</TEXT>

      

What I expect to get:

Here is the first part...The secondAnd the third

      

What I actually get:

Here is the first part...And the third.

      

I tried descendant-or-self::*

the xPath function, child and stream, with no result.

If anyone can tell me how to get text in child nodes too.

+3


source to share


2 answers


XPath 1.0

You cannot do concatenation of all text descendants of a given node in XPath 1.0. You can select nodes in XPath,

/TEXT/DESCR//text()

      

but then you have to do the concatenation in the hosting language.

In PHP:

$xml = '<TEXT>
    <DESCR>
         Here is the first part...
         <PLUS>The second</PLUS>
         And the third
    </DESCR>
</TEXT>';
$dom = new DOMDocument();
$dom->loadXML($xml);
$x= new DOMXpath($dom);
foreach($x->query("/TEXT/DESCR//text()") as $node) echo trim($node->textContent); 

      

Will output the result you requested:

Here is the first part...The secondAnd the third

      



[Otherwise, unless you have any other reason to iterate over the text nodes, replace the loop foreach

above:]

$xml = '<TEXT>
    <DESCR>
         Here is the first part...
         <PLUS>The second</PLUS>
         And the third
    </DESCR>
</TEXT>';
$dom = new DOMDocument();
$dom->loadXML($xml);
$x= new DOMXpath($dom);
echo str_replace(PHP_EOL, '', $x->evaluate('normalize-space(/TEXT/DESCR)'));

      

What gives:

Here is the first part... The second And the third

      

XPath 2.0

You can concatenate all text descendants of a given node in XPath 2.0:

string-join(/TEXT/DESCR//text(), '')

      

+4


source


If you cannot change your input XML, this might work:

concat(/TEXT/DESCR,/TEXT/DESCR/PLUS)

      



or

string-join(/TEXT/DESCR/descendant-or-self::text())

      

0


source







All Articles