如何将数组转换为PHP中的SimpleXML对象?
当前回答
function toXML($data, $obj = false, $dom) {
$is_first_level = false;
if($obj === false) {
$dom = new DomDocument('1.0');
$obj = $dom;
$is_first_level = true;
}
if(is_array($data)) {
foreach($data as $key => $item) {
$this->toXML($item, $obj->appendChild($dom->createElement($key)), $dom);
}
}else {
$obj->appendChild($dom->createTextNode($data));
}
if($is_first_level) {
$obj->formatOutput = true;
return $obj->saveXML();
}
return $obj;
}
其他回答
我想要一个代码,将一个数组内的所有元素,并把它们作为属性,所有数组作为子元素。
对于像这样的东西
array (
'row1' => array ('head_element' =>array("prop1"=>"some value","prop2"=>array("empty"))),
"row2"=> array ("stack"=>"overflow","overflow"=>"overflow")
);
我会得到这样的结果
<?xml version="1.0" encoding="utf-8"?>
<someRoot>
<row1>
<head_element prop1="some value">
<prop2 0="empty"/>
</head_element>
</row1>
<row2 stack="overflow" overflow="stack"/>
</someRoot>
要实现这一点,代码如下,但要非常小心,它是递归的,实际上可能会导致stackoverflow:)
function addElements(&$xml,$array)
{
$params=array();
foreach($array as $k=>$v)
{
if(is_array($v))
addElements($xml->addChild($k), $v);
else $xml->addAttribute($k,$v);
}
}
function xml_encode($array)
{
if(!is_array($array))
trigger_error("Type missmatch xml_encode",E_USER_ERROR);
$xml=new SimpleXMLElement('<?xml version=\'1.0\' encoding=\'utf-8\'?><'.key($array).'/>');
addElements($xml,$array[key($array)]);
return $xml->asXML();
}
您可能希望添加数组长度检查,以便在数据部分中设置某些元素,而不是作为属性。
下面讨论名称空间。在本例中,构造包装器以包含名称空间定义,并将其传递给函数。使用冒号来标识命名空间。
测试数组
$inarray = [];
$inarray['p:apple'] = "red";
$inarray['p:pear'] = "green";
$inarray['p:peach'] = "orange";
$inarray['p1:grocers'] = ['p1:local' => "cheap", 'p1:imported' => "expensive"];
$xml = new SimpleXMLElement( '<p:wrapper xmlns:p="http://namespace.org/api" xmlns:p1="http://namespace.org/api2 /> ');
array_to_xml($xml,$inarray);
function array_to_xml(SimpleXMLElement $object, array $data)
{
$nslist = $object->getDocNamespaces();
foreach ($data as $key => $value)
{
$nspace = null;
$keyparts = explode(":",$key,2);
if ( count($keyparts)==2)
$nspace = $nslist[$keyparts[0]];
if (is_array($value))
{
$key = is_numeric($key) ? "item$key" : $key;
$new_object = $object->addChild($key,null,$nspace);
array_to_xml($new_object, $value);
}
else
{
$key = is_numeric($key) ? "item$key" : $key;
$object->addChild($key, $value,$nspace);
}
}
}
function array2xml($array, $xml = false){
if($xml === false){
$xml = new SimpleXMLElement('<?xml version=\'1.0\' encoding=\'utf-8\'?><'.key($array).'/>');
$array = $array[key($array)];
}
foreach($array as $key => $value){
if(is_array($value)){
$this->array2xml($value, $xml->addChild($key));
}else{
$xml->addChild($key, $value);
}
}
return $xml->asXML();
}
我发现这个解与原来的问题相似
<?php
$test_array = array (
'bla' => 'blub',
'foo' => 'bar',
'another_array' => array (
'stack' => 'overflow',
),
);
class NoSimpleXMLElement extends SimpleXMLElement {
public function addChild($name,$value) {
parent::addChild($value,$name);
}
}
$xml = new NoSimpleXMLElement('<root/>');
array_walk_recursive($test_array, array ($xml, 'addChild'));
print $xml->asXML();
我认为上面所有的解决方案都很好,但我看到目前为止,它并没有真正创建一个准确的格式良好的XML,因为数组键与$my_array[main_node][multiple_values][] = ARRAY ('id' => '1')然后转换为
<main_node>
<multiple_values>
<0>
<id>1 test</id>
</0>
</multiple_values>
<multiple_values>
<1>
<id>2 test</id>
</1>
</multiple_values>
</main_node>
这是XML解析器方面的一个问题……
I should be like this:
<main_node>
<multiple_values>
<id>1 test</id>
</multiple_values>
<multiple_values>
<id>2 test</id>
</multiple_values>
</main_node>
如果你用load_simple_xml来解析…你会得到完全相同的数组/对象结构。
我的函数还自动创建正确的根节点。
// Code to convert php array to xml document 20211112
function array2xml(array $data, $xml_class_obj = '', $group_by_parent_allowed = '', $options = array())
{
if(!$xml_class_obj) :
$is_root = 1;
$xml_class_obj = new XMLWriter();
$xml_class_obj->openMemory();
$xml_class_obj->setIndent(TRUE);
$xml_class_obj->setIndentString(' ');
if($options['encoding'] != '') $xml_class_obj->startDocument('1.0', $options['encoding']);
else $xml_class_obj->startDocument('1.0');
endif;
foreach ($data as $key => $value) {
if (is_array($value)) { // IS ARRAY
// check if allow below keys are int, if yes group them to same parent tree
$group_by_parent = $key;
foreach(array_keys($value) as $c_keys) :
if(!is_int($c_keys)) $group_by_parent = '';
endforeach;
if(empty($group_by_parent)) $xml_class_obj->startElement($key);
if($group_by_parent_allowed != '') $xml_class_obj->startElement($group_by_parent_allowed);
$this->array2xml($value, $xml_class_obj, $group_by_parent, $options);
if(empty($group_by_parent)) $xml_class_obj->endElement();
} else { // IS VALUE
if(is_string($value)) :
$xml_class_obj->startElement($key);
$xml_class_obj->writeCData($value);
$xml_class_obj->endElement();
else :
$xml_class_obj->writeElement($key, $value);
endif;
}
} // foreach
if($group_by_parent_allowed != '') $xml_class_obj->endElement();
if($is_root == 1) :
$xml_class_obj->endDocument();
return $xml_class_obj->outputMemory();
else :
return $xml_class_obj;
endif;
}
// usage
$ary_new_xml = array();
$ary_new_xml['order']['customer']['customerid'] = '123456';
$ary_new_xml['order']['customer']['customertype'] = 15;
$ary_new_xml['order']['orderprio'] = 2;
$ary_new_xml['order']['orderpos'][] = array('sku' => 9999910001111, 'quantity' => 3);
$ary_new_xml['order']['orderpos'][] = array('sku' => 9999910002222, 'quantity' => 1);
echo array2xml($ary_new_xml,'','',array('enconding' => 'UTF-8'));
结果:
<?xml version="1.0" encoding="UTF-8"?>
<order>
<customer>
<customerid>82936639</customerid>
<customertype>15</customertype>
</customer>
<orderprio>2</orderprio>
<orderpos>
<sku>9999910001111</sku>
<quantity>3</quantity>
</orderpos>
<orderpos>
<sku>9999910002222</sku>
<quantity>1</quantity>
</orderpos>
</order>
我希望这能帮助到一些人;)