I have the following xml doc:

<shop id="123" name="xxx">
  <product id="123456">
  <product id="789012">
  <product id="345678">
<shop id="456" name="yyy">
  <product id="123456">

I have the following loop to gather the information for each product:

$data_feed = 'www.mydomain.com/xml/compression/gzip/';
$xml = simplexml_load_file("compress.zlib://$data_feed");

        foreach ($xml->xpath('//product') as $row) {
                        $id = $row["id"]; // product id eg. "123456"
                        $name = $row->name;
                        $price = $row->price;

        // update database etc.

HOWEVER, I also want to gather the information for each product's parent shop ("id" and "name").

I can easily change my xpath to start from shop as opposed to product, but I'm unsure of the most efficient way to then construct an additional loop within my foreach to loop each indented product

Make sense?


I'd go without xpath and just use two nested foreach-loops:

$xml = simplexml_load_string($x); // assume XML in $x

foreach ($xml->shop as $shop) {
    echo "shop $shop[name], id $shop[id] <br />";
    foreach ($shop->product as $product) {
        echo "- $product->name (id $product[id]), $product->price <br />";

see it working: http://codepad.viper-7.com/vFmGvY

BTW: your XML is broken, probably a typo. Each closing </price> is missing its last >.

drlq92444 我同意这一点。 如果你需要遍历每个节点,我不会看到XPath给你的东西。
大约 7 年之前 回复

Sure, makes sense, you want one iteration, not a nested product of iterations (albeit that won't cut you much, @michi showed already), which is possible as well:

foreach ($xml->xpath('//product') as $row) 
    $id       = $row["id"]; // product id eg. "123456"
    $name     = $row->name;
    $price    = $row->price;
    $shopId   = $row->xpath('../@id')[0];
    $shopName = $row->xpath('../@name')[0];

    // update database etc.

As this example shows, you can run xpath() on each element-node and the context-node is automatically set to the node itself, therefore the realtive path .. in xpath works to access the parent element (see as well: Access an element's parent with PHP's SimpleXML?). Of that then both attributes are read and then via PHP 5.4 array de-referencing the first (and only) attribute is accessed.

I hope this helps and shed some light how it works. Your question reminds me a bit of an earlier one where I suggested some kind of generic solution to these kind of problems:

Csdn user default icon