0

I'm parsing xml nodes and I'm doing something wrong but I don't know what. I have this xml:

$xml="    <root>
        <info>
        <company/>
        <user_id>43</user_id>
        <currency>EUR</currency>
        </info>
        <products>
         <product>
          <id>1336</id>
          <pn>NX.RZNAA.003</pn>
          <stock>1.00</stock>
         </product>
         <product>
          <id>1337</id>
          <pn>NX.RZNAA.004</pn>
          <stock>4.00</stock>
          <item_number>5</item_number>
         </product>
        </products>
     </root>";

As you can see I have two "product" nodes with child nodes. But in first node "product" I have one node less then in second. In second the node "item_number" is added (it's optional node, if it has value it is in xml otherwise not) . When I'm parsing this nodes my parser returns value from second nodes "product" even if I'm on first node.

Anyone know what is the problem here?

Here is my code:

$xmlDoc = new DOMDocument();
$xmlDoc->load($xml) ; 
$xpath = new DOMXPath($xmlDoc);
$tagForCount="count(//".$arrayPolja[0].")"; 
$x=$xmlDoc->getElementsByTagName("product");
$xpath = new DomXpath($xmlDoc);
$count = 3;
$arrayPolja[0] = "id";
$arrayPolja[1] = "pn";
$arrayPolja[2] = "stock";
$arrayPolja[3] = "item_number";
$r=0;
foreach ($x as $product) {
     $i=0;
     while ($i<=$count)
     {
        $polje=$arrayPolja[$i];
        $values[$i]=$xpath->query($polje, $product)->item($r)->textContent;     
        $i++;
     }
    $r++;
}

1 Answer 1

1

For one, the second iteration in the loop is overriding the values of your array "$values" which is why you'd only be seeing the values from the second product node (if you are inspecting the "$values" array which is what I'm assuming you are doing).

Try this:

$xmlDoc = new DOMDocument();
$xmlDoc->load($xml); 
$xpath = new DOMXPath($xmlDoc);
$x = $xmlDoc->getElementsByTagName("product");
$array = array('id','pn','stock','item_number');
$values = array();

foreach ($x as $product) {
    $data = array();

    // node name here
    $data['node'] = $product->nodeName;

    foreach ($array as $v){
        $obj = $xpath->query($v, $product)->item(0);
        if (gettype($obj) == 'object'){
            $data[$v] = $obj->textContent; 
        }  
    }
    $values[] = $data;
}
echo '<pre>' . print_r($values, true). '</pre>';

That should produce this:

Array
(
[0] => Array
    (
        [node] => product
        [id] => 1336
        [pn] => NX.RZNAA.003
        [stock] => 1.00
    )

[1] => Array
    (
        [node] => product
        [id] => 1337
        [pn] => NX.RZNAA.004
        [stock] => 4.00
        [item_number] => 5
    )
Sign up to request clarification or add additional context in comments.

2 Comments

If you don't mind, how to get node attribute with this sample?
Ivan, no problem. To get a list of all child nodes try $nodes = $xpath->query("/child::") and just iterate through the result. You should see a DOMElement Object with all of its attributes listed if you "print_r" during each iteration. If you're just wanting the parent node name, it depends on how you want to structure your array, but look at the edit I made with the new "node" key in the $data array. That would be one way to do it. Also check out w3.org/TR/xpath/#location-paths that might help with discovering nodes attributes/values. Hope that helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.