如何将数组转换为PHP中的SimpleXML对象?
当前回答
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();
}
其他回答
我会评论投票次数第二多的答案,因为如果有数字索引的内部数组,它不会保留结构并生成糟糕的xml。
我基于它开发了自己的版本,因为我需要简单的json和xml之间的转换器,而不管数据的结构。我的版本保留了数字键信息和原始数组的结构。它为数值索引值创建元素,方法是将值包装为值命名的元素,其key-attribute包含数值key。
例如
阵列('测试' = >阵列(0 = >“值”,1 = > '其他'))
皈依
<test><value key="0">some value</value><value key="1">other</value></test>
我的版本的array_to_xml -function(希望它能帮助到某人:)
function array_to_xml($arr, &$xml) {
foreach($arr as $key => $value) {
if(is_array($value)) {
if(!is_numeric($key)){
$subnode = $xml->addChild("$key");
} else {
$subnode = $xml->addChild("value");
$subnode->addAttribute('key', $key);
}
array_to_xml($value, $subnode);
}
else {
if (is_numeric($key)) {
$xml->addChild("value", $value)->addAttribute('key', $key);
} else {
$xml->addChild("$key",$value);
}
}
}
}
我想要一个代码,将一个数组内的所有元素,并把它们作为属性,所有数组作为子元素。
对于像这样的东西
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();
}
您可能希望添加数组长度检查,以便在数据部分中设置某些元素,而不是作为属性。
我认为上面所有的解决方案都很好,但我看到目前为止,它并没有真正创建一个准确的格式良好的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>
我希望这能帮助到一些人;)
如果数组是关联的并且键是正确的,那么首先将它转换为xml可能会更容易。喜欢的东西:
function array2xml ($array_item) {
$xml = '';
foreach($array_item as $element => $value)
{
if (is_array($value))
{
$xml .= "<$element>".array2xml($value)."</$element>";
}
elseif($value == '')
{
$xml .= "<$element />";
}
else
{
$xml .= "<$element>".htmlentities($value)."</$element>";
}
}
return $xml;
}
$simple_xml = simplexml_load_string(array2xml($assoc_array));
另一种方法是首先创建基本的xml,例如
$simple_xml = simplexml_load_string("<array></array>");
然后对于数组的每个部分,使用类似于我的文本创建循环的东西,而不是使用simplexml函数“addChild”用于数组的每个节点。
稍后我将尝试使用这两个版本来更新这篇文章。
这里有一个函数帮我解决了这个问题:
就像这样叫它
echo arrayToXml("response",$arrayIWantToConvert);
function arrayToXml($thisNodeName,$input){
if(is_numeric($thisNodeName))
throw new Exception("cannot parse into xml. remainder :".print_r($input,true));
if(!(is_array($input) || is_object($input))){
return "<$thisNodeName>$input</$thisNodeName>";
}
else{
$newNode="<$thisNodeName>";
foreach($input as $key=>$value){
if(is_numeric($key))
$key=substr($thisNodeName,0,strlen($thisNodeName)-1);
$newNode.=arrayToXml3($key,$value);
}
$newNode.="</$thisNodeName>";
return $newNode;
}
}