PHP Doku:: Runs XPath query on XML data - simplexmlelement.xpath.html

Verlauf / Chronik / History: (1) anzeigen

Sie sind hier:
Doku-StartseitePHP-HandbuchFunktionsreferenzXML-ManipulationSimpleXMLThe SimpleXMLElement classSimpleXMLElement::xpath

Ein Service von Reinhard Neidl - Webprogrammierung.

The SimpleXMLElement class

<<SimpleXMLElement::saveXML

SimpleXML-Funktionen>>

SimpleXMLElement::xpath

(PHP 5 >= 5.2.0)

SimpleXMLElement::xpathRuns XPath query on XML data

Beschreibung

public array SimpleXMLElement::xpath ( string $path )

The xpath method searches the SimpleXML node for children matching the XPath path.

Parameter-Liste

path

An XPath path

Rückgabewerte

Returns an array of SimpleXMLElement objects or FALSE in case of an error.

Beispiele

Beispiel #1 Xpath

<?php
$string 
= <<<XML
<a>
 <b>
  <c>text</c>
  <c>stuff</c>
 </b>
 <d>
  <c>code</c>
 </d>
</a>
XML;

$xml = new SimpleXMLElement($string);

/* Search for <a><b><c> */
$result $xml->xpath('/a/b/c');

while(list( , 
$node) = each($result)) {
    echo 
'/a/b/c: ',$node,"\n";
}

/* Relative paths also work... */
$result $xml->xpath('b/c');

while(list( , 
$node) = each($result)) {
    echo 
'b/c: ',$node,"\n";
}
?>

Das oben gezeigte Beispiel erzeugt folgende Ausgabe:

/a/b/c: text
/a/b/c: stuff
b/c: text
b/c: stuff

Notice that the two results are equal.


17 BenutzerBeiträge:
- Beiträge aktualisieren...
stefan at efectos dot nl
9.11.2010 11:33
Having problems selecting information through xpath when there are namespaces in the XML?

Try this quick and dirty solution, but it works:

<?php
$objImageXml
= new SimpleXMLElement($objImageXml->asXML());
?>
eleg
10.05.2010 13:25
to be able to use the default namespace:

<?php
    $xml
= simplexml_load_file('test.xfdf');
   
$namespaces = $xml->getDocNamespaces();
   
$xml->registerXPathNamespace('__empty_ns', $namespaces['']);
   
$result = $xml->xpath('//__empty_ns:field/@name');
?>
grummfy at gmail dot com
11.02.2010 13:08
On a xml that have namespace you need to do this before your xpath request (or empty array will be return) :

<?php
$string
= str_replace('xmlns=', 'ns=', $string); //$string is a string that contains xml...
?>
DrupalFocus at earthlink dot net
2.12.2009 21:27
Looks like the relative path is relative to the SimpleXMLElement object that you call the Xpath() method on.  Basically chopping off the root element.

<?php
$string
= <<<XML
<foo>
  <bar>
    <a>
     <b>
      <c>text</c>
      <c>stuff</c>
     </b>
     <d>
      <c>code</c>
     </d>
    </a>
  </bar>
</foo>
XML;

$xml = new SimpleXMLElement($string);
/* Search for children using 2nds level relative <bar><a><b><c> */
$result = $xml->xpath('a/b/c');
if (
$result)
foreach(
$result as $node) {
   
drupal_set_message(t('a/b/c: @node.', array('@node' => $node)));
}
else
 
drupal_set_message(t('a/b/c: failed.'));
                    
/* it relative to the SimpleXMLElement Search for 2nds level relative <bar><a><b><c> but where is foo */
$bar = $xml->bar;
$result = $bar->xpath('a/b/c');
foreach(
$result as $node) {
   
drupal_set_message(t('bar->a/b/c: @node.', array('@node' => $node)));
}
?>

results in :
#
# a/b/c: failed.
# bar->a/b/c: text.
# bar->a/b/c: stuff.
behnam@zwnj
24.09.2009 22:34
Seems like this function cannot return the result of XPath string() [1] function.  For example if you query xpath("string(a/@b)") you will get bool(false) although the node "a" may have the attribute "b" set to a non-empty string.

[1] http://www.w3.org/TR/xpath#section-String-Functions
Anti Veeranna
17.06.2009 12:50
Whether it returns a false or empty array for a non-existing path seems to depend on libxml version.

I tried the following code:

<?php
$data
= '<foo><bar></bar></foo>';
$xml = simplexml_load_string($data);
print
gettype($xml->xpath('/first/second'));
?>

On a machine with libxml 2.6.16 and PHP 5.2.8 I got back boolean. On a different machine with libxml 2.7.3 and PHP 5.2.8/5.2.9 I got back empty array.

You can check the libxml version from command line by executing: php --ri libxml

or simply look at phpinfo() output
arealzone-czernobyl at yahoo dot de
12.06.2009 0:23
The simplest way to count nodes in a XML doc:

<?php
$xml
= new SimpleXMLElement($xmlstr);

$xmlNode = $xml->xpath('root/yourNodeName');
$nodeCount = count($xmlNode);

echo
$nodeCount;
?>
anemik
3.07.2008 0:46
If you want to find easly all records satisfying some condition in XML data like

....
   <book id="bk101">
      <author>Gambardella, Matthew</author>
      <title>XML Developer's Guide</title>
      <genre>Computer</genre>
      <price>44.95</price>
   </book>
   <book id="bk102">
      <author>Ralls, Kim</author>
      <title>Midnight Rain</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
   </book>
...

try example below

<?php

$xmlStr
= file_get_contents('data/books.xml');
$xml = new SimpleXMLElement($xmlStr);
// seach records by tag value:
// find all book records with price higher than 40$
$res = $xml->xpath("book/price[.>'40']/parent::*");
print_r($res);

?>

You will see response like:
Array (
[0] => SimpleXMLElement Object
        (
            [@attributes] => Array
                (
                    [id] => bk101
                )

            [author] => Gambardella, Matthew
            [title] => XML Developer's Guide
            [genre] => Computer
            [price] => 44.95
            [publish_date] => 2000-10-01
            [description] => An in-depth look at creating applications
      with XML.
        )
...
paul at pmtlogic dot com
18.06.2008 21:17
xpath doesn't seem to be able to handle single quotes embedded in the query itself. For instance, I want to find geo coordinates in an xml file based on country name.

xml snippet:

<zones>
<zone country="Cote d'Ivoire" fullName="Yamoussoukro" geo="6.82,-5.28" id="1050"><url prefix="1001" value="fiji.html" /><url prefix="1002" value="C" /></zone>
</zones>

The following code does not work:

<?php
$xml
= simplexml_load_file("my.xml");
$result = $xml->xpath("//zone[@country='Cote d\'Ivoire']");

foreach (
$result[0]->attributes() as $key => $val ) {
    print
"<div class='coords'>$key: $val</div>\n";
}
?>

I have tried many variations on the embedded single quote (i.e. escape codes) but with no result. W3C offers no explanation either.

In addition, there doesn't seem to be any way of embedding wildcards in the attribute value (you can embed wildcards in the attribute name). Otherwise the following might be a reasonable substitute in this context:

<?php $result = $xml->xpath("//zone[@country='Cote d*Ivoire']"); ?>
canuemail at gmail dot com
5.05.2008 14:05
If you want to search multiple values from xml on the behalf or one value then this code can be helpfull to you.

if there is:
<Record>
  <country>Pakistan</country>
  <code>+92</code>
  <Value>100<Value>
</Record>

then try this one:
<?php
$sxe
simplexml_load_file("countries.XML");
foreach(
$sxe->xpath('//RECORD') as $item) {

   
$row = simplexml_load_string($item->asXML());
   
$v = $row->xpath('//country[. ="Pakistan"]');
    if(
$v[0]){
        print
$item->country;
        print
$item->code;
        print
$item->value;
    }
   
}
?>
brettz9 through yah
13.09.2006 16:31
I was looking to find all of a given element type with attributes which were not of a particular value (including null items).

I tried this...
<?php
   $xml
->xpath("//pg[@show!='none']");
?>
...But that only worked if there was in fact some attribute.

I thought this should work (shouldn't it?), but it didn't:
<?php
   $xml
->xpath("//pg[@show!='none' or !@show]");
?>

The solution is to use the not() function:

<?php
   $xml
->xpath("//pg[not(@show='none')]");
?>
ron @ rotflol dot cx
29.03.2006 19:07
xpath returning references to the parent simplexml object can bite you performance wise when processing large trees.
this bit me big time so looking for a solution I came up with a simple way to speed up the code.

'dereferencing' will yield instant results, code will be lighting fast.
sacrifice is losing the reference to the parent object, for simple read-only operation this should be ok.

<?php
$data
= 'data.xml';
$rs = simplexml_load_file($data);
foreach(
$rs->xpath('//row') as $rsrow){
   
// 'derefence' into a seperate xml tree for performance
   
$row = simplexml_load_string($rsrow->asXML());
   
$v = $row->xpath('//field[@name="id"]');

}
?>
drewish at katherinehouse dot com
10.01.2006 8:40
here's a simple work-around for the lack of support for default namespaces, just overwrite the xmlns attribute of the root element:
<?php
$xml
= simplexml_load_file('http://example.com/atom_feed.xml');
// hack to work around php 5.0's problems with default namespaces and xpath()
$xml['xmlns'] = '';
// now our queries work:
$titles = $xml->xpath('entry/title');
foreach ((array)
$titles as $title) {
    print
"$title\n";
}
?>
Hugh
19.12.2005 0:23
Note that this function does not ALWAYS return an array. It seems that if the specified path is not found in the document, it will return false. You need to check for the false value before using foreach, if you wish to avoid a warning (and often to handle errors or control program flow in this situation).
retardis at gmail dot com
24.08.2005 10:21
Xpath actually returns an array full of references to elements in the parent SimpleXML object. Therefore, in addition to preserving attributes, you can actually modify them and the result will be reflected in the parent.

Example:

<?php

$xml_str
= <<<END
<a>
    <b attr="foo"/>
</a>
END;

$xml = simplexml_load_string ($xml_str);
$result = $xml->xpath ('/a/b'); // returns an array with one element
$result[0]['attr'] = 'bar';
print
$xml->asXML ();
?>

Outputs:
<a>
    <b attr="bar"/>
</a>
drewish at katherinehouse dot com
11.07.2005 3:16
xpath() can also be used to select elements by their attributes. For a good XPath reference check out: http://www.w3schools.com/xpath/xpath_syntax.asp

<?php
$string
= <<<XML
<sizes>
    <size label="Square" width="75" height="75" />
    <size label="Thumbnail" width="100" height="62" />
    <size label="Small" width="112" height="69" />
    <size label="Large" width="112" height="69" />
</sizes>
XML;

$xml = simplexml_load_string($string);
$result = $xml->xpath("//size[@label='Large']");

// print the first (and only) member of the array
echo $result[0]->asXml();
?>

The script would print:
<size label="Large" width="112" height="69"/>
matt@roughest[d0t]net
3.09.2004 9:17
This may be obvious, but in case you're wondering, the array resulting from the xpath() operation doesn't retain any of the nodes' attributes.

In other words, it won't return any of the tags' attributes



PHP Powered Diese Seite bei php.net
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",...)