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?
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?
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/
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:
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);
}
}
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