php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #62260 XPath does not search correctly in nodes with text and other nodes
Submitted: 2012-06-08 07:34 UTC Modified: 2012-06-15 09:03 UTC
From: yajo dot sk8 at gmail dot com Assigned:
Status: Closed Package: *XML functions
PHP Version: 5.3.13 OS: Linux
Private report: No CVE-ID: None
 [2012-06-08 07:34 UTC] yajo dot sk8 at gmail dot com
Description:
------------
When a node has inner nodes and you want to search into its text value, only the first text node is selected.

This is wrong because, as http://www.w3.org/TR/xpath/#path-abbrev says:
> text() selects all text node children of the context node

Test script:
---------------
$xml = <<<END
<?xml version="1.0" encoding="UTF-8"?>
<root>
    <first>
        Hello
        <second>
            world
        </second>
        world
    </first>
</root>
END;

$doc = DOMDocument::loadXML($xml);
$xpath = new DOMXPath($doc);

foreach ($xpath->query('//*[contains(text(), "world")]') as $node)
    echo $node->nodeName . PHP_EOL;

Expected result:
----------------
first
second

Actual result:
--------------
second

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2012-06-08 08:29 UTC] salathe@php.net
I may be wrong, but my understanding is as follows.

text() returns a list of node [1], whereas contains() expects two string arguments [2].  Because of this the list of 
text nodes is converted to a string, as with string():

"A node-set is converted to a string by returning the string-value of the node in the node-set that is first in 
document order. If the node-set is empty, an empty string is returned." [3]

[1] http://www.w3.org/TR/xpath/#path-abbrev
[2] http://www.w3.org/TR/xpath/#function-contains
[3] http://www.w3.org/TR/xpath/#function-string
 [2012-06-15 09:03 UTC] yajo dot sk8 at gmail dot com
-Status: Open +Status: Closed
 [2012-06-15 09:03 UTC] yajo dot sk8 at gmail dot com
Salathe, thanks for the point, you are right.

Replacing the xquery by '//text()[contains(., "world")]/..' works perfectly.
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Wed Aug 12 16:01:25 2020 UTC