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"
  }
}

<?php 

$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'));
  
}

?>

_______________________________________________
New York PHP Community Talk Mailing List
http://lists.nyphp.org/mailman/listinfo/talk

NYPHPCon 2006 Presentations Online
http://www.nyphpcon.com

Show Your Participation in New York PHP
http://www.nyphp.org/show_participation.php

Reply via email to