PHP Doku:: Evaluates the XPath Location Path in the given string - function.xpath-eval.html

Verlauf / Chronik / History: (1) anzeigen

Sie sind hier:

Ein Service von Reinhard Neidl - Webprogrammierung.





(PHP 4)

xpath_eval Evaluates the XPath Location Path in the given string


XPathObject XPathContext::xpath_eval ( string $xpath_expression [, domnode $contextnode ] )
XPathObject xpath_eval ( XPathContext $xpath_context , string $xpath_expression [, domnode $contextnode ] )

The optional contextnode can be specified for doing relative XPath queries.

See also xpath_new_context().

15 BenutzerBeiträge:
- Beiträge aktualisieren...
marius kreis (email to mariuskreis . de)
8.07.2005 16:26
If the namespace is subject to change you can write even more portable code if you extend brandon dot whitehead at orst dot edu's solution like this:

$doc = domxml_open_mem($xml);

$xpath = $doc->xpath_new_context();
$namespace = $xpath->xpath_eval('namespace-uri(//*)')->value; // returns the namespace uri

xpath_register_ns($xpath, "pre", $namespace); // sets the prefix "pre" for the namespace
$obj = $xpath->xpath_eval('//pre:Offer'); // finds all Offer tags

$nodeset = $obj->nodeset;


This code will determine the namespace of the root element and set a prefix for XPath queries. Thus it doesn't matter if the namespace is changing in your XML (like some webservices do...)
patrikG at home dot net
16.03.2004 17:42
Just an example of how to grab XML attributes with xpath - which took me a while to figure out. I'm filtering the returned object function node_content() which is a somewhat quick'n dirty solution, but I don't always need XML's child-parent relationships.

        <SERVICE TYPE="books">
        <SERVICE TYPE="books">
            <NAME>The Poisonwood Bible</NAME>
        <SERVICE TYPE="cars">
        <SERVICE TYPE="vehicle sans wheels">


$node->nodeset as $content){
$return[]    =    $content->{$attribute};

//needs PHP's xPath extension installed
$dom    =domxml_open_mem($xml);
$calcX = &$dom->xpath_new_context();

The code above returns:

    [merchandise] => Array
            [0] => Ulysses

            [1] => The Poisonwood Bible
            [2] => Van
            [3] => UFO

    [service] => Array
            [0] => books
            [1] => books
            [2] => cars
            [3] => vehicle sans wheels

brandon dot whitehead at orst dot edu
6.09.2003 22:52
In order to use the default namespace you must understand
how namespace prefixes work.  Prefixes are simply convenient mappies to the namespace URI.

For example, if you set the namespace:


and you have the following document fragment:


this is essentially equivalent to:


because the namespace URI is what matters, not the namespace prefix.

Unfortuantly, if you have a default namespace:


then all elements without a prefix belong to that namespace, and yet, it appears that PHP, and the underlying LIBXML2 don't let you register a default namespace with

"xpath_register_ns(context, prefix, uri)"

i.e. by leaving the prefix = "".  Therefore, to get around the problem, simply give the default prefix a simple name, such as "pre". 

For example, if you have a default namespace declaration such as the following document:

<?xml version="1.0" encoding="UTF-8"?>
<rootname xmlns="" xml:lang="en-US">
   <childnode>Some text</childnode>

And you want to evaluate the xpath expression:


then you need to register the default namespace in PHP like this:

xpath_register_ns(context, "pre", "");

and then use the following xpath expression:


As you can see this is a lot prettier and more intuititive than using the local-name() function.  In addition, it makes your code more portable, because you are guaranteed to always be working on nodes that belong to your explicitly stated namespace, uniquely identified by your URI.
6.09.2003 19:05
Querying documents closed inside a namespace can be tricky
tuxo at gmx dot net
21.05.2003 20:47
PHP Version: 4.3.1

I tried out how to get a part of a xml document with the xpath functions in domxml.
Try the following solution:

// get dom object
$xmldoc = domxml_open_mem($xml);

// init xpath
$xpath = xpath_new_context($xmldoc);
$xpresult = xpath_eval($xpath, "/root/info");

// dump all nodes directly in plain text
foreach ($xpresult->nodeset as $node)
$newxml .= $node->dump_node($node);

If you wanna get a new dom object of the result just add

$newxmldoc = domxml_open_mem($newxml);
tk dot lists at fastmail dot fm
20.01.2003 2:46
You can indeed use the result object of xpath_eval(). You just have to be careful to pass the result by reference! (note the ampersand's position).

$objXP = xpath_new_context($objDom)
$objTest = &xpath_eval($objXP,"//lalala");
$objTest->nodeset[0]->set_attribute("test","test data");
echo htlentities($objDom->dump_mem());

just be careful that is you pass around values from $objTest then they also need to be passed by reference.
chregu at php dot net
29.11.2002 11:32
If you want to apply an XPath-Expression to a particular node:

arthur at ischium dot net
9.11.2002 0:54
If you want to get the XPath for a particular node:

function getXPath($node) {
    /* node id is held in a property named '1', this is
    illegal in php so we use a workaround */
    $one = '1';
    $xpath = '';
    while ($parent = $node->parent_node()) {
        $siblings = $parent->child_nodes();
        $index = 1;
        foreach ($siblings as $sibling) {
            if ($sibling->type != XML_ELEMENT_NODE || $sibling->tagname != $node->tagname) continue;
            if ($sibling->$one == $node->$one) {
                $xpath = '/' . $node->tagname . '[' . $index . ']' . $xpath;
        $node = $parent;
    return $xpath;
bate at php dot net
4.10.2002 13:58
= xmldocfile('file.xml');
$xpath = $xml->xpath_new_context();

* object access
$ret = $xpath->xpath_eval('//tag');

* function access
$ret2 = xpath_eval($xpath, '//tag');

sbarnum@pointsystems com
21.03.2002 3:33
This function has come in handy for recursively viewing the results of xpath searches.  It iterates through a node and converts it to a big associative array:

* Recursive function to convert xml root node to big assoc array
function xmlnode2array($node) {
    if ($node->type==XML_ELEMENT_NODE) {
        if ($attrArray = $node->attributes()) {
            // parse attributes //
            foreach($attrArray AS $attr) {
                $out['ATTRIBUTE'][$attr->name] = $attr->value;
        if ($childArray = $node->children()) {
            // add child nodes //
            foreach($childArray AS $child) {
                if ($child->type==XML_ELEMENT_NODE) {
                    $out[$child->tagname][] = xmlnode2array($child);
                } else {
                    if ($content = xmlnode2array($child))
                        $out['CONTENT'] = $content;

    } else {
        // this is a CONTENT NODE //
        $out = trim($node->content);
        if (!$out) return false;
    return $out;
ziw at ifirst dot ru
22.10.2001 14:34
it seems that namespaces are not yet (PHP 4.06) implemented - xpath_eval($cnx,"/ns:tag") does work on w2k and does NOT on linux
sofnology at xtra dot co dot nz
26.08.2001 3:45
I hope this little example helps someone out. If the XML data doesn't come thru in the post feel free to contact me via email.

= xslt_create();

$o += 0;
$s '';
$s .= "<query type='create'>";
$s .=     "<resourceClass id='12345678901234567890' displayName='DAISY'>";
$s .=         "<group family='global' id='kind'>";
$s .=             "<node id='NODE_A' displayName='Red Ferrari' description='Red always goes faster'/>";
$s .=         "</group>";
$s .=     "</resourceClass>";
$s .=     "<resourceClass id='12345678901234567890' displayName='BETTY'>";
$s .=         "<group family='global' id='kind'>";
$s .=             "<node id='NODE_B' displayName='Blue Porsche' description='But Porsches are a drivers car'/>";
$s .=         "</group>";
$s .=     "</resourceClass>";
$s .= "</query>";


$query_xo = xpath_eval($ctx,"count(/query/resourceClass)");
$num_rc = $query_xo->value;
"<BR>There are $num_rc classes in this list");

$x=1; $x <= $num_rc; $x++){
$query_xo = xpath_eval($ctx,"/query/resourceClass[position()=$x]");
$query_ns = $query_xo->nodeset;
$resourceClass_dn = $query_ns[0];

//        echo("<PRE>");
//        print_r( $query_xo );
//        echo("<PRE><HR>");
//        print_r( $query_ns );
//        echo("<PRE><HR>");
//        print_r( $rc_dn );

mfkahn2_NOSPAM at yahoo dot com
24.06.2001 23:35
$ctx = xpath_new_context($doc);
$xpath_nodes = xpath_eval($ctx, "//some_element");

$xpath_nodes->nodeset[i]->set_content($string) allows you to set the node content.  Try it and then do a $doc->dumpmem, you'll see the nodes in the original document are indeed updated properly.

I've used this feature lots.  It does work.
newsforsam at bigfoot dot de
24.05.2001 17:46
xpath_eval() returns only a copy of your document. So you cant for example change the $foo->nodeset[id]->content's of the resulting matches. If you want to, you have to do it yourself by going recursive through your doc, which makes xpath_eval at least useless except for checking if you have to ;).
pking at hoovers dot com
7.03.2001 2:22
This is a very (very) minor point, but there is a comma missing in the function definition for xpath_eval.  This being my first experience with xpath, I thought "object xpath context" was refering to a single parameter produced by a previous call to xpath_new_context().  Then I couldn't see where you would add the query (which is actually the context parameter)

So the proper definition should be
array xpath_eval (object xpath, context)

Additionally an example would be nice.  I found one from a post to
Message # 1002772:
Date: 01/02/01 06:40
By: Luis Argerich
Subject: new DOM features im 4.0.4

Just wanted to add that PHP 4.0.4 has improved DOM support including Xpath and
Xpointer support:

Try this:

$xml='SOME XML ....';

It returns an object that contains a property called Nodeset with an array of DomNodes with the result of the Xpath expression. print_r($foo) to see the full structure.

4.0.4 has also added Xpointer support, so with Xpath and Xpointer support we can really do a lot of things from PHP to XML files.


PHP Powered Diese Seite bei
The PHP manual text and comments are covered by the Creative Commons Attribution 3.0 License © the PHP Documentation Group - Impressum - mail("TO:Reinhard Neidl",...)