1

Background of Problem

I have a large XML file I am trying to parse it into a PHP array.

The structure of my file is as such

<orders>
  <order>
    <value1></value1>
    <value2></value3>
    <value2></value3>
    <items>
      <item></item>
      <price></price>
    </items>
  </order>
</orders>

And so on for many more values. My PHP function looks like this

public function outputNodes() {
    // this function creates/returns an array of all the XML nodes and child nodes
    // we do not know how many custom attributes there may be for orders, so this
    // handles them programmatically with count

if (file_exists($this->getFilePath())) { // this checks to make sure there is a file

    $orders = array(); //create blank array for orders

    $obj = $this->getXML($this->getFilePath()); // start by getting XML object

    $order = $obj->children();
    $oCount = count($order);  //How many orders are there?

    $topNodes = $obj->order->children();
    $topNodesCount = count($topNodes); //How many nodes does each order have?

    //begin looping through orders

    for($i=0;$i<$oCount;$i++) {

        $vals = array(); //for each order create the array to store the values of items node

         foreach($topNodes as $key => $value) { //for each top level nodes do something

             if((string)$key == "items"){ //checks to see if this top level node is the items node
                $cobj = $obj->order->items->children(); //if it is create object of the children of node
                foreach($cobj as $k =>$v) { //for each child of items node do something
                    $v[(string)$k] = (string)$v; //creates a temporary array of the child names/values of items node
                    }
                $vals[] = $v; //places them into $vals array
                $ord[(string)$key] = $vals; //places entire $vals array into temp ord array for output
                }
            else {
            $ord[(string)$key] = (string)$value;
            }           
         }
         $orders[] = $ord;
    }
    return $orders;
}
 else {
     return "Error";
     }
}

Now to be clear, this code works fine in theory, it does put $vals[] array into the $orders[] array, however it does so like this:

[items] => Array ( [0] => SimpleXMLElement Object ( [@attributes] => Array ( [item] => ) [item_name] => Nameof Product [item_price] => $8.00 [item_quantity] => 12 ) ) )

Questions

So then I have two questions. Firstly how can I stop it from putting Array ( [0] => SimpleXMLElement Object ( [@attributes] this erroneous information in?

Secondly, and more to the point, how can I modify the code so rather than having to call the items node by name, I can rather have it check to see if any given node has more children that it automatically pulls them out into an array?

I'd prefer to not have to write new code every time there is more subnodes and simply have it check: Is there subnodes? If yes, get them and display them in a nested array

Thanks in advance

3
  • I have a question, too: What's wrong with having a SimpleXMLElement instead of an array? It is way more flexible that an array. So why bother with the conversion? Commented Apr 5, 2015 at 21:39
  • There is another part to this program which will add an jQuery/AJAX layer and PHP arrays play more nicely with AJAX than SimpleXMLElements, at least that's what I've been lead to believe. Also its sort of a proof of concept I just want to fully understand all angles to parsing XML. Commented Apr 5, 2015 at 22:17
  • jQuery accepts XML as well as response.Just saying. Commented Apr 5, 2015 at 22:55

1 Answer 1

0

One way to achieve this, is to iterate over all the elements in the document and then build the array based on the data-flow:

$builder = new StructureBuilder();

foreach ($xml->xpath('//*') as $element) {
    $depth  = count($element->xpath("./ancestor::*"));
    $builder->add($depth, $element->getName(), trim($element));
}

print_r($builder->getStructure());

With the example data of yours this is:

Array
(
    [orders] => Array
        (
            [order] => Array
                (
                    [value1] => 
                    [value2] => 
                    [value3] => 
                    [items] => Array
                        (
                            [item] => 
                            [price] => 
                        )

                )

        )

)

How does it work? The StructureBuilder keeps track on which element in the structure is ready for $depth. You can find the full example code as gist.

You can also see this previous answer PHP Parse XML response with many namespaces which asked also about how to convert. The example there is more verbose regarding the indenting.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks I will try this sometime in the next 24 hrs and let you know how it goes. Its late where I am and I've been coding all day lol

Your Answer

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