NYCPHP Meetup

[nycphp-talk] simplexml xpath bug ? (long post)

Emmanuel M. Décarie emm at scriptdigital.com
Thu Aug 9 15:51:22 EDT 2007


Hi there,

I'm not sure if this is the way it’s supposing to work or if this is  
a bug. Anyway, here's the problem.

I have to parse a very complex XML document where I need to do a  
xpath query against a previous found xpath query.

I use simplexml for that.

For the sake of the discussion, I wrote a script to illustrate the  
problem (see below or the attachment). And yes, with this example, I  
could use just one xpath query to get the same result. But this is an  
example, so bare with me.

Ok let's start.

* What I want to do: *

Do a xpath query against a previous xpath query.

* What happened: *

The second xpath query is made against the whole xml tree instead of  
a subset of the tree found by the first xpath query.

* Work-around: *

You have to deference the tree.

* My question *

Clearly, what I see is not what I get when I use var_dump or print_r  
against the second xpath query. I wonder if there is a bug here.  
Also, why the fragment of XML that I get from the first xpath query  
still reference the whole tree.

Thanks!


=========================


* Example: The Script*

$xml = <<<END
<?xml version="1.0" encoding="UTF-8"?>
<world>
   <continent name='europe'>
     <country name='france'>paris</country>
     <country name='uk'>london</country>
   </continent>
   <continent name='africa'>
     <country name='zimbabwe'>harare</country>
     <country name='egypt'>cairo</country>
   </continent>
</world>
END;

$obj      = simplexml_load_string ($xml);
$result   = $obj->xpath ('//continent');

echo "----------------\n";
echo "result\n";
echo "----------------\n";
var_dump ($result);
echo "\n\n";

$counter = 0;
foreach ($result as $elem) {
   $counter++;
   echo "----------------\n";
   echo "Counter: $counter\n";
   echo "----------------\n";


   echo "----------------\n";
   echo "elem\n";
   echo "----------------\n";
   var_dump ($elem);
   echo "\n";

   echo "----------------\n";
   echo "elem->xpath('//country')\n";
   echo "----------------\n";
   var_dump ($elem->xpath ('//country'));

   $elem2 = simplexml_load_string ($elem->asXML ());
   echo "----------------\n";
   echo "elem2->xpath('//country')\n";
   echo "----------------\n";
   var_dump ($elem2->xpath ('//country'));
}

* The Result: *

----------------
result
----------------
array(2) {
   [0]=>
   object(SimpleXMLElement)#2 (2) {
     ["@attributes"]=>
     array(1) {
       ["name"]=>
       string(6) "europe"
     }
     ["country"]=>
     array(2) {
       [0]=>
       string(5) "paris"
       [1]=>
       string(6) "london"
     }
   }
   [1]=>
   object(SimpleXMLElement)#3 (2) {
     ["@attributes"]=>
     array(1) {
       ["name"]=>
       string(6) "africa"
     }
     ["country"]=>
     array(2) {
       [0]=>
       string(6) "harare"
       [1]=>
       string(5) "cairo"
     }
   }
}


----------------
Counter: 1
----------------
----------------
elem
----------------
object(SimpleXMLElement)#2 (2) {
   ["@attributes"]=>
   array(1) {
     ["name"]=>
     string(6) "europe"
   }
   ["country"]=>
   array(2) {
     [0]=>
     string(5) "paris"
     [1]=>
     string(6) "london"
   }
}

----------------
elem->xpath('//country')
----------------
array(4) {
   [0]=>
   object(SimpleXMLElement)#4 (2) {
     ["@attributes"]=>
     array(1) {
       ["name"]=>
       string(6) "france"
     }
     [0]=>
     string(5) "paris"
   }
   [1]=>
   object(SimpleXMLElement)#5 (2) {
     ["@attributes"]=>
     array(1) {
       ["name"]=>
       string(2) "uk"
     }
     [0]=>
     string(6) "london"
   }
   [2]=>
   object(SimpleXMLElement)#6 (2) {
     ["@attributes"]=>
     array(1) {
       ["name"]=>
       string(8) "zimbabwe"
     }
     [0]=>
     string(6) "harare"
   }
   [3]=>
   object(SimpleXMLElement)#7 (2) {
     ["@attributes"]=>
     array(1) {
       ["name"]=>
       string(5) "egypt"
     }
     [0]=>
     string(5) "cairo"
   }
}
----------------
elem2->xpath('//country')
----------------
array(2) {
   [0]=>
   object(SimpleXMLElement)#6 (2) {
     ["@attributes"]=>
     array(1) {
       ["name"]=>
       string(6) "france"
     }
     [0]=>
     string(5) "paris"
   }
   [1]=>
   object(SimpleXMLElement)#5 (2) {
     ["@attributes"]=>
     array(1) {
       ["name"]=>
       string(2) "uk"
     }
     [0]=>
     string(6) "london"
   }
}
----------------
Counter: 2
----------------
----------------
elem
----------------
object(SimpleXMLElement)#3 (2) {
   ["@attributes"]=>
   array(1) {
     ["name"]=>
     string(6) "africa"
   }
   ["country"]=>
   array(2) {
     [0]=>
     string(6) "harare"
     [1]=>
     string(5) "cairo"
   }
}

----------------
elem->xpath('//country')
----------------
array(4) {
   [0]=>
   object(SimpleXMLElement)#5 (2) {
     ["@attributes"]=>
     array(1) {
       ["name"]=>
       string(6) "france"
     }
     [0]=>
     string(5) "paris"
   }
   [1]=>
   object(SimpleXMLElement)#6 (2) {
     ["@attributes"]=>
     array(1) {
       ["name"]=>
       string(2) "uk"
     }
     [0]=>
     string(6) "london"
   }
   [2]=>
   object(SimpleXMLElement)#4 (2) {
     ["@attributes"]=>
     array(1) {
       ["name"]=>
       string(8) "zimbabwe"
     }
     [0]=>
     string(6) "harare"
   }
   [3]=>
   object(SimpleXMLElement)#8 (2) {
     ["@attributes"]=>
     array(1) {
       ["name"]=>
       string(5) "egypt"
     }
     [0]=>
     string(5) "cairo"
   }
}
----------------
elem2->xpath('//country')
----------------
array(2) {
   [0]=>
   object(SimpleXMLElement)#7 (2) {
     ["@attributes"]=>
     array(1) {
       ["name"]=>
       string(8) "zimbabwe"
     }
     [0]=>
     string(6) "harare"
   }
   [1]=>
   object(SimpleXMLElement)#4 (2) {
     ["@attributes"]=>
     array(1) {
       ["name"]=>
       string(5) "egypt"
     }
     [0]=>
     string(5) "cairo"
   }
}

-------------- next part --------------
A non-text attachment was scrubbed...
Name: simplexml_xpath_example.php
Type: text/php
Size: 1133 bytes
Desc: not available
URL: <http://lists.nyphp.org/pipermail/talk/attachments/20070809/b923150b/attachment.bin>
-------------- next part --------------



More information about the talk mailing list