3

Say I have an array like this:

<?php
$colors=array();

$colors[0]['id']=1;
$colors[0]['color']='blue';


$colors[1]['id']=2;
$colors[1]['color']='green';

......
?>

What's the easiest way to have the entire array converted to XML?

Pascal MARTIN
  • 395,085
  • 80
  • 655
  • 663
Ali
  • 261,656
  • 265
  • 575
  • 769

4 Answers4

0

Some working Example for the Data in Question that is on-site: https://stackoverflow.com/a/14143759/367456

Original answer follows:

Take a look at these pre-defined implementations:

http://snipplr.com/view/3491/convert-php-array-to-xml-or-simple-xml-object-if-you-wish/

http://vantulder.net/f2o/notities/arraytoxml/

Community
  • 1
  • 1
Alex Weinstein
  • 9,823
  • 9
  • 42
  • 59
  • 1
    The first link does not answer the question, the second link is gone. Please review your answer. I also added an additional link to an answer to a similar question. – hakre Jan 03 '13 at 17:28
0

You could create yourself a simple function that just outputs it. For example passing the array with the elements to the function and telling the name of the parent element (root element of the document) and the name of each element.

I assume colors for the parent and color for each element.

I also assumed that the named keys are children of the color elements:

function xml_from_indexed_array($array, $parent, $name) {

    echo '<?xml version="1.0"?>', "\n";
    echo "<$parent>\n";
    foreach ($array as $element) {
        echo "  <$name>\n";
        foreach ($element as $child => $value) {
            echo "    <$child>$value</$child>\n";
        }
        echo "  </$name>\n";
    }
    echo "</$parent>\n";
}

As you can see, this is pretty straight forward, just iterating over all elements.

Usage Example:

<?php
$colors = array();

$colors[0]['id']    = 1;
$colors[0]['color'] = 'blue';

$colors[1]['id']    = 2;
$colors[1]['color'] = 'green';

xml_from_indexed_array($colors, 'colors', 'color');

Example Output:

<?xml version="1.0"?>
<colors>
  <color>
    <id>1</id>
    <color>blue</color>
  </color>
  <color>
    <id>2</id>
    <color>green</color>
  </color>
</colors>

If you have more advanced array structures that is more deeply nested, you might want to solve this in a recursive manner. Some related questions:

Community
  • 1
  • 1
hakre
  • 193,403
  • 52
  • 435
  • 836
0

It took me many hours to do this. I really can't believe PHP doesn't have a function that does this for you. Anyway, I hope this is helpful to someone. Enjoy!

<?php
class Xml
{
  public function getXmlFromArray($value, \SimpleXMLElement &$xmlElement, $entity, $starting = null)
{

    $handleValue = function($value){
        $entityHandler = $this->getEntityHandler();
        if($entityHandler && $entityHandler instanceof \Closure){
            $value = $entityHandler($value);
        }
        if(is_string($value)){
            $value = htmlspecialchars($value);
        }
        return $value;
    };
    $addChild = function($name, $value, &$subNode = null)use(&$xmlElement, $handleValue, $entity){
        if(is_array($value)){
            if(!$subNode instanceof \SimpleXMLElement){
                $currentKey = key($value);
                $initialValue = null;
                if(is_numeric($currentKey)){
                    if(!is_array($value[$currentKey])){
                        $initialValue = $value[$currentKey];
                        unset($value[$currentKey]);
                    }
                }
                $subNode = $xmlElement->addChild($this->cleanXmlTagName($name), $initialValue);
            }
            $this->getXmlFromArray($handleValue($value), $subNode, $name);
        } else {
            $xmlElement->addChild($this->cleanXmlTagName($name), $handleValue($value));
        }
    };

    if(is_array($value))
    {
        if(is_numeric(key($value))){
            $setSubNodePrimitiveValue = function($value)use(&$xmlElement, $entity, $handleValue){
                $value = $handleValue($value);
                $children = $xmlElement->children();
                $children[] = $value;
            };
            foreach ($value as $item)
            {
                if(!is_array($item)){
                    $setSubNodePrimitiveValue($item);
                } else {
                    if($starting === true){
                        $addChild($entity, $item);
                    } else {
                        $addChild($entity, $item, $xmlElement);
                    }
                }
            }
        } else {
            foreach ($value as $subEntity => $subEntityItem)
            {
                if(is_array($subEntityItem) && is_array(current($subEntityItem)) && is_numeric(key($subEntityItem))){
                    $this->getXmlFromArray($subEntityItem, $xmlElement, $subEntity, true);
                    continue;
                }
                $addChild($subEntity, $subEntityItem);
            }
        }
    } else {
        $xmlElement->addChild($this->cleanXmlTagName($entity), $handleValue($value));
    }
}

public function cleanXmlTagName(string $tagName)
{
    if(is_numeric($tagName[0])){
        $tagName = '_'.$tagName;
    }
    return preg_replace('/[^A-Za-z0-9.\-_]/', '_', $tagName);
}

  /**
   * @param array $array
   * @param string $openingTag
   * @param string $entity
   * @param string $nameSpace
   * @param bool $isPrefixed
   * @return \SimpleXMLElement
   */
  public function generateXmlFromArray(array $array, string $openingTag, string $entity, $nameSpace = '', $isPrefixed = false)
  {
      $xmlString = '<'.$openingTag.'></'.$openingTag.'>';
      $xml = new \SimpleXMLElement($xmlString, LIBXML_NOERROR, false, $nameSpace, $isPrefixed);
      $this->getXmlFromArray($array, $xml, $entity, true);
      return $xml;
  }

  /**
   * @param string $xml
   * @return bool
   */
  public function validateXml(string $xml)
  {
      $dom = new \DOMDocument();
      $dom->loadXML($xml);
      return $dom->validate();
  }

  public function loadXmlPathAsArray(string $xmlPath)
  {
      $xml   = simplexml_load_file($xmlPath);
      $array = json_decode(json_encode($xml), TRUE);
      return (array)$array;
  }

  /**
   * @param string $xmlString
   * @return array
   */
  public function loadXmlStringAsArray(string $xmlString)
  {
      $array = (array) @simplexml_load_string($xmlString);
      if(!$array){
          $array = (array) @json_decode($xmlString, true);
      } else{
          $array = (array)@json_decode(json_encode($array), true);
      }
      return $array;
  }

  /**
   * @param string $xmlString
   * @return \SimpleXMLElement
   */
  public function loadXmlString(string $xmlString)
  {
      return @simplexml_load_string($xmlString);
  }
}
kurtbr
  • 1
  • 1
  • You call it by $xml = new Xml(); $xml-> generateXmlFromArray($array, 'entities', 'entity'); – kurtbr May 31 '17 at 14:58
0

If you also want attribute support for converting array to XML, you can use this implementation: http://www.lalit.org/lab/convert-php-array-to-xml-with-attributes/

For attribute support it requires you to construct your array in a particular way. For xml without attributes you can directly pass any array to the function and get an XML

Lalit
  • 1,469
  • 1
  • 9
  • 4