Pepijn Gieles
Pepijn Gieles

Reputation: 727

How can I convert a multidimensional PHP Array To XML?

1. What I can do

I know how to convert XML to a multidimensional PHP array, I do it like this:

$xml = file_get_contents('data.xml');
$data = json_decode(json_encode((array) simplexml_load_string($xml)),1);

Now $data is my PHP array.

2. What I should be able to do

But what if I changed that array and want to put it back to the file? I should be able to do the opposite right? But I can't find out how..

3. What doesn't solve my problem

This post comes close, but doesn't return the data in the same order: How to convert array to SimpleXML

And it shouldn't get as difficult as this right?: Convert multidimensional array into XML

Upvotes: 2

Views: 1807

Answers (3)

Dominik Mayrhofer
Dominik Mayrhofer

Reputation: 491

I didn't find a satisfying way for that too so i wrote this methods using the inputs from the answers above. It converts the array to an xml using DOMDocument and calling itself recursive.

 /**
     * Creates an XML from a multidimensional array
     * @param $xml DOMDocument
     * @param $array
     * @param false $base_xml
     */
    private function xmlBuilder(&$xml, $array, $base_xml = false)
    {
        /*
         * If a child branch contains an array the method Recursive is called.
         * In this case the original XML must be preserved, since createElement is no longer available on generated elements,
         * only in the original DOMDocument class
         */
        $base_xml = !empty($base_xml) ? $base_xml : $xml;
        foreach($array AS $key => $value){ //Get through the array and assign the entries to the XML
            if(is_array($value)){
                $element = $base_xml->createElement($key); //Create element from the key
                $this->xmlBuilder($element, $value, $base_xml); //Append the child elements under the element
            }
            else{ //The element can be generated from key/value
                $element = $base_xml->createElement($key, $value);
            }
            $xml->appendChild($element); //Add element to XML
        }
    }

You can call this method using the following one.

/**
     * Returns an XML string from a data array
     * @param array $data
     * @return mixed
     */
    private function getXml(array $data)
    {         
        $xml = new DOMDocument(self::XML_API_VERSION, self::XML_API_ENCODING); //generate new XML with version and encoding

        $this->xmlBuilder($xml, $data); //Pass through the array and generate the XML from it.
        $string = $xml->saveXML(); //generate a string from the generated XML

        return $string; //return the generated string
    }

Upvotes: -1

David Rutherford
David Rutherford

Reputation: 81

I had the same issue and problems finding a simple solution. The solution below makes use of DOMDocument to allow for Pretty Printing. If you don't want Pretty Printing set $doc->formatOutput = FALSE;

I humbly submit the following PHP function:

function array2xml($data, $name='root', &$doc=null, &$node=null){
    if ($doc==null){
        $doc = new DOMDocument('1.0','UTF-8');
        $doc->formatOutput = TRUE;
        $node = $doc;
    }

    if (is_array($data)){
        foreach($data as $var=>$val){
            if (is_numeric($var)){
                array2xml($val, $name, $doc, $node);
            }else{
                if (!isset($child)){
                    $child = $doc->createElement($name);
                    $node->appendChild($child);
                }

                array2xml($val, $var, $doc, $child);
            }
        }
    }else{
        $child = $doc->createElement($name);
        $node->appendChild($child);
        $textNode = $doc->createTextNode($data);
        $child->appendChild($textNode);
    }

    if ($doc==$node) return $doc->saveXML();
}//array2xml

Using the following test data and call:

$array = [
    'name'   => 'ABC',
    'email'  => '[email protected]',
    'phones' =>
    [
        'phone' =>
        [
            [
                'mobile' => '9000199193',
                'land'   => '9999999',
            ],
            [
                'mobile' => '9000199193',
                'land'   => '9999999',
            ],
            [
                'mobile' => '9000199194',
                'land'   => '5555555',
            ],
            [
                'mobile' => '9000199195',
                'land'   => '8888888',
            ],
        ],
    ],
];

//Specify the $array and a name for the root container
echo array2xml($array, 'contact');

You get the following results:

<?xml version="1.0" encoding="UTF-8"?>
<contact>
  <name>ABC</name>
  <email>[email protected]</email>
  <phones>
    <phone>
      <mobile>9000199193</mobile>
      <land>9999999</land>
    </phone>
    <phone>
      <mobile>9000199193</mobile>
      <land>9999999</land>
    </phone>
    <phone>
      <mobile>9000199194</mobile>
      <land>5555555</land>
    </phone>
    <phone>
      <mobile>9000199195</mobile>
      <land>8888888</land>
    </phone>
  </phones>
</contact>

I hope this helps.

Upvotes: 5

developerwjk
developerwjk

Reputation: 8659

Traverse the array and put it into XML with simplexml's dom operations. Or, for an oldschool way, go through a loop concatenating XML into a string like. $xmlstring .= '<tag>' . $arr[x][y] .'</tag>' and then load the result in simplexml with simplexml_load_string.

But the best thing to do is not switch from using simplexml to an array, if you intend to make changes and save the XML again. Traverse the XML file with the simplexml DOM rather than convert it to an array. Then whatever changes you make with the DOM you can save without the hassle of converting back and forth.

Upvotes: 1

Related Questions