Как преобразовать массив в объект SimpleXML в PHP?
короткий:
<?php $test_array = array ( 'bla' => 'blub', 'foo' => 'bar', 'another_array' => array ( 'stack' => 'overflow', ), ); $xml = new SimpleXMLElement('<root/>'); array_walk_recursive($test_array, array ($xml, 'addChild')); print $xml->asXML();
приводит к
<?xml version="1.0"?> <root> <blub>bla</blub> <bar>foo</bar> <overflow>stack</overflow> </root>
ключи и значения меняются местами – вы можете исправить это с помощью array_flip()
перед array_walk. array_walk_recursive
требует PHP 5. вместо этого вы можете использовать array_walk
, но тогда вы не получите 'stack' => 'overflow'
в xml.
Вот код php 5.2, который преобразует массив любой глубины в документ xml:
Array ( ['total_stud']=> 500 [0] => Array ( [student] => Array ( [id] => 1 [name] => abc [address] => Array ( [city]=>Pune [zip]=>411006 ) ) ) [1] => Array ( [student] => Array ( [id] => 2 [name] => xyz [address] => Array ( [city]=>Mumbai [zip]=>400906 ) ) ) )
-Array ( ['total_stud']=> 500 [0] => Array ( [student] => Array ( [id] => 1 [name] => abc [address] => Array ( [city]=>Pune [zip]=>411006 ) ) ) [1] => Array ( [student] => Array ( [id] => 2 [name] => xyz [address] => Array ( [city]=>Mumbai [zip]=>400906 ) ) ) )
-Array ( ['total_stud']=> 500 [0] => Array ( [student] => Array ( [id] => 1 [name] => abc [address] => Array ( [city]=>Pune [zip]=>411006 ) ) ) [1] => Array ( [student] => Array ( [id] => 2 [name] => xyz [address] => Array ( [city]=>Mumbai [zip]=>400906 ) ) ) )
генерируемый XML будет выглядеть так:
<?xml version="1.0"?> <student_info> <total_stud>500</total_stud> <student> <id>1</id> <name>abc</name> <address> <city>Pune</city> <zip>411006</zip> </address> </student> <student> <id>1</id> <name>abc</name> <address> <city>Mumbai</city> <zip>400906</zip> </address> </student> </student_info>
PHP-фрагмент
<?php // function defination to convert array to xml function array_to_xml( $data, &$xml_data ) { foreach( $data as $key => $value ) { if( is_numeric($key) ){ $key = 'item'.$key; //dealing with <0/>..<n/> issues } if( is_array($value) ) { $subnode = $xml_data->addChild($key); array_to_xml($value, $subnode); } else { $xml_data->addChild("$key",htmlspecialchars("$value")); } } } // initializing or creating array $data = array('total_stud' => 500); // creating object of SimpleXMLElement $xml_data = new SimpleXMLElement('<?xml version="1.0"?><data></data>'); // function call to convert array to xml array_to_xml($data,$xml_data); //saving generated xml file; $result = $xml_data->asXML('/file/path/name.xml'); ?>
Документация по SimpleXMLElement::asXML
используемая в этом фрагменте
Представленные здесь ответы только преобразуют массив в XML с узлами, вы не можете устанавливать атрибуты. Я написал функцию php, которая позволяет преобразовать массив в php, а также установить атрибуты для определенных узлов в xml. Недостатком здесь является то, что вы должны построить массив определенным образом с несколькими соглашениями (только если вы хотите использовать атрибуты)
Следующий пример позволит вам также установить атрибуты в XML.
Подробный пример и использование можно найти здесь: http://www.lalit.org/lab/convert-php-array-to-xml-with-attributes/
<?php $books = array( '@attributes' => array( 'type' => 'fiction' ), 'book' => array( array( '@attributes' => array( 'author' => 'George Orwell' ), 'title' => '1984' ), array( '@attributes' => array( 'author' => 'Isaac Asimov' ), 'title' => 'Foundation', 'price' => '$15.61' ), array( '@attributes' => array( 'author' => 'Robert A Heinlein' ), 'title' => 'Stranger in a Strange Land', 'price' => array( '@attributes' => array( 'discount' => '10%' ), '@value' => '$18.00' ) ) ) ); /* creates <books type="fiction"> <book author="George Orwell"> <title>1984</title> </book> <book author="Isaac Asimov"> <title>Foundation</title> <price>$15.61</price> </book> <book author="Robert A Heinlein"> <title>Stranger in a Strange Land</title> <price discount="10%">$18.00</price> </book> </books> */ ?>
Я нашел все ответы, чтобы использовать слишком много кода. Вот простой способ сделать это:
function to_xml(SimpleXMLElement $object, array $data) { foreach ($data as $key => $value) { if (is_array($value)) { $new_object = $object->addChild($key); to_xml($new_object, $value); } else { // if the key is an integer, it needs text with it to actually work. if ($key == (int) $key) { $key = "key_$key"; } $object->addChild($key, $value); } } }
Тогда просто передать массив в функцию, которая использует рекурсию, поэтому она будет обрабатывать многомерный массив:
$xml = new SimpleXMLElement('<rootTag/>'); to_xml($xml, $my_array);
Теперь $ xml содержит красивый XML-объект, основанный на вашем массиве, точно так, как вы его написали.
print $xml->asXML();
<? PHP function array_to_xml (массив $ arr, SimpleXMLElement $ xml) { foreach ($ arr как $ k => $ v) { is_array ($ v) ? array_to_xml ($ v, $ xml-> addChild ($ k)) : $ xml-> addChild ($ k, $ v); } return $ xml; } $ test_array = array ( 'bla' => 'blub', 'foo' => 'bar', 'another_array' => массив ( 'stack' => 'overflow', ), ); echo array_to_xml ($ test_array, новый SimpleXMLElement ('<root />')) -> asXML ();
Еще одно улучшение:
/** * Converts an array to XML * * @param array $array * @param SimpleXMLElement $xml * @param string $child_name * * @return SimpleXMLElement $xml */ public function arrayToXML($array, SimpleXMLElement $xml, $child_name) { foreach ($array as $k => $v) { if(is_array($v)) { (is_int($k)) ? $this->arrayToXML($v, $xml->addChild($child_name), $v) : $this->arrayToXML($v, $xml->addChild(strtolower($k)), $child_name); } else { (is_int($k)) ? $xml->addChild($child_name, $v) : $xml->addChild(strtolower($k), $v); } } return $xml->asXML(); }
Применение:
$this->arrayToXML($array, new SimpleXMLElement('<root/>'), 'child_name_to_replace_numeric_integers');
Из PHP 5.4
function array2xml($data, $root = null){ $xml = new SimpleXMLElement($root ? '<' . $root . '/>' : '<root/>'); array_walk_recursive($data, function($value, $key)use($xml){ $xml->addChild($key, $value); }); return $xml->asXML(); }
Вот моя запись, простая и чистая ..
function array2xml($array, $xml = false){ if($xml === false){ $xml = new SimpleXMLElement('<root/>'); } foreach($array as $key => $value){ if(is_array($value)){ array2xml($value, $xml->addChild($key)); }else{ $xml->addChild($key, $value); } } return $xml->asXML(); } header('Content-type: text/xml'); print array2xml($array);
Так или иначе … Я взял код onokazu (спасибо!) И добавил способность повторять теги в XML, он также поддерживает атрибуты, надеюсь, что кто-то сочтет это полезным!
<?php function array_to_xml(array $arr, SimpleXMLElement $xml) { foreach ($arr as $k => $v) { $attrArr = array(); $kArray = explode(' ',$k); $tag = array_shift($kArray); if (count($kArray) > 0) { foreach($kArray as $attrValue) { $attrArr[] = explode('=',$attrValue); } } if (is_array($v)) { if (is_numeric($k)) { array_to_xml($v, $xml); } else { $child = $xml->addChild($tag); if (isset($attrArr)) { foreach($attrArr as $attrArrV) { $child->addAttribute($attrArrV[0],$attrArrV[1]); } } array_to_xml($v, $child); } } else { $child = $xml->addChild($tag, $v); if (isset($attrArr)) { foreach($attrArr as $attrArrV) { $child->addAttribute($attrArrV[0],$attrArrV[1]); } } } } return $xml; } $test_array = array ( 'bla' => 'blub', 'foo' => 'bar', 'another_array' => array ( array('stack' => 'overflow'), array('stack' => 'overflow'), array('stack' => 'overflow'), ), 'foo attribute1=value1 attribute2=value2' => 'bar', ); $xml = array_to_xml($test_array, new SimpleXMLElement('<root/>'))->asXML(); echo "$xml\n"; $dom = new DOMDocument; $dom->preserveWhiteSpace = FALSE; $dom->loadXML($xml); $dom->formatOutput = TRUE; echo $dom->saveXml(); ?>
Я использую пару функций, которые я написал некоторое время назад, чтобы сгенерировать xml для перехода назад и вперед от PHP и jQuery и т. Д. Ни в каких других фреймворках просто генерируется строка, которая затем может использоваться с SimpleXML (или другой структурой ) …
Если это полезно кому-либо, используйте его 🙂
function generateXML($tag_in,$value_in="",$attribute_in=""){ $return = ""; $attributes_out = ""; if (is_array($attribute_in)){ if (count($attribute_in) != 0){ foreach($attribute_in as $k=>$v): $attributes_out .= " ".$k."=\"".$v."\""; endforeach; } } return "<".$tag_in."".$attributes_out.((trim($value_in) == "") ? "/>" : ">".$value_in."</".$tag_in.">" ); } function arrayToXML($array_in){ $return = ""; $attributes = array(); foreach($array_in as $k=>$v): if ($k[0] == "@"){ // attribute... $attributes[str_replace("@","",$k)] = $v; } else { if (is_array($v)){ $return .= generateXML($k,arrayToXML($v),$attributes); $attributes = array(); } else if (is_bool($v)) { $return .= generateXML($k,(($v==true)? "true" : "false"),$attributes); $attributes = array(); } else { $return .= generateXML($k,$v,$attributes); $attributes = array(); } } endforeach; return $return; }
Всем любви 🙂
Мне нужен код, который будет принимать все элементы внутри массива и рассматривать их как атрибуты, а все массивы – как вспомогательные элементы.
Так что для чего-то вроде
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(); }
Возможно, вы захотите добавить проверки длины массива, чтобы некоторый элемент был установлен внутри части данных, а не как атрибут.
Вот функция, которая сделала трюк для меня:
Просто назовите его чем-то вроде
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; } }
Вы можете использовать XMLParser , над которым я работаю.
$xml = XMLParser::encode(array( 'bla' => 'blub', 'foo' => 'bar', 'another_array' => array ( 'stack' => 'overflow', ) )); // @$xml instanceof SimpleXMLElement echo $xml->asXML();
Это приведет к:
<?xml version="1.0"?> <root> <bla>blub</bla> <foo>bar</foo> <another_array> <stack>overflow</stack> </another_array> </root>
Я нашел это решение аналогичным исходной проблеме
<?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();
Большинство приведенных выше ответов верны. Тем не менее, я придумал этот ответ, который решает проблему array_walk_recursive совместимости, а также проблему с числовыми ключами. Он также прошел все тесты, которые я сделал:
function arrayToXML(Array $array, SimpleXMLElement &$xml) { foreach($array as $key => $value) { // None array if (!is_array($value)) { (is_numeric($key)) ? $xml->addChild("item$key", $value) : $xml->addChild($key, $value); continue; } // Array $xmlChild = (is_numeric($key)) ? $xml->addChild("item$key") : $xml->addChild($key); arrayToXML($value, $xmlChild); } }
Я также добавил тестовый класс для этого, который может оказаться полезным:
class ArrayToXmlTest extends PHPUnit_Framework_TestCase { public function setUp(){ } public function tearDown(){ } public function testFuncExists() { $this->assertTrue(function_exists('arrayToXML')); } public function testFuncReturnsXml() { $array = array( 'name' => 'ardi', 'last_name' => 'eshghi', 'age' => 31, 'tel' => '0785323435' ); $xmlEl = new SimpleXMLElement('<root/>'); arrayToXml($array, $xmlEl); $this->assertTrue($xmlEl instanceOf SimpleXMLElement); } public function testAssocArrayToXml() { $array = array( 'name' => 'ardi', 'last_name' => 'eshghi', 'age' => 31, 'tel' => '0785323435' ); $expectedXmlEl = new SimpleXMLElement('<root/>'); $expectedXmlEl->addChild('name', $array['name']); $expectedXmlEl->addChild('last_name', $array['last_name']); $expectedXmlEl->addChild('age', $array['age']); $expectedXmlEl->addChild('tel', $array['tel']); $actualXmlEl = new SimpleXMLElement('<root/>'); arrayToXml($array, $actualXmlEl); $this->assertEquals($expectedXmlEl->asXML(), $actualXmlEl->asXML()); } public function testNoneAssocArrayToXml() { $array = array( 'ardi', 'eshghi', 31, '0785323435' ); // Expected xml value $expectedXmlEl = new SimpleXMLElement('<root/>'); foreach($array as $key => $value) $expectedXmlEl->addChild("item$key", $value); // What the function produces $actualXmlEl = new SimpleXMLElement('<root/>'); arrayToXml($array, $actualXmlEl); $this->assertEquals($expectedXmlEl->asXML(), $actualXmlEl->asXML()); } public function testNestedMixArrayToXml() { $testArray = array( "goal", "nice", "funny" => array( 'name' => 'ardi', 'tel' =>'07415517499', "vary", "fields" => array( 'small', 'email' => 'ardi.eshghi@gmail.com' ), 'good old days' ), "notes" => "come on lads lets enjoy this", "cast" => array( 'Tom Cruise', 'Thomas Muller' => array('age' => 24) ) ); // Expected xml value $expectedXmlEl = new SimpleXMLElement('<root/>'); $expectedXmlEl->addChild('item0', $testArray[0]); $expectedXmlEl->addChild('item1', $testArray[1]); $childEl = $expectedXmlEl->addChild('funny'); $childEl->addChild("name", $testArray['funny']['name']); $childEl->addChild("tel", $testArray['funny']['tel']); $childEl->addChild("item0", "vary"); $childChildEl = $childEl->addChild("fields"); $childChildEl->addChild('item0', 'small'); $childChildEl->addChild('email', $testArray['funny']['fields']['email']); $childEl->addChild("item1", 'good old days'); $expectedXmlEl->addChild('notes', $testArray['notes']); $childEl2 = $expectedXmlEl->addChild('cast'); $childEl2->addChild('item0', 'Tom Cruise'); $childChildEl2 = $childEl2->addChild('Thomas Muller'); $childChildEl2->addChild('age', $testArray['cast']['Thomas Muller']['age']); // What the function produces $actualXmlEl = new SimpleXMLElement('<root/>'); arrayToXml($testArray, $actualXmlEl); $this->assertEquals($expectedXmlEl->asXML(), $actualXmlEl->asXML()); } }
На основе всего остального здесь обрабатываются числовые индексы + атрибуты с помощью префикса @
и могут вводить xml в существующие узлы:
function simple_xmlify($arr, SimpleXMLElement $root = null, $el = 'x') { // based on, among others http://stackoverflow.com/a/1397164/1037948 if(!isset($root) || null == $root) $root = new SimpleXMLElement('<' . $el . '/>'); if(is_array($arr)) { foreach($arr as $k => $v) { // special: attributes if(is_string($k) && $k[0] == '@') $root->addAttribute(substr($k, 1),$v); // normal: append else simple_xmlify($v, $root->addChild( // fix 'invalid xml name' by prefixing numeric keys is_numeric($k) ? 'n' . $k : $k) ); } } else { $root[0] = $arr; } return $root; }//-- fn simple_xmlify
// lazy declaration via "queryparam" $args = 'hello=4&var[]=first&var[]=second&foo=1234&var[5]=fifth&var[sub][]=sub1&var[sub][]=sub2&var[sub][]=sub3&var[@name]=the-name&var[@attr2]=something-else&var[sub][@x]=4.356&var[sub][@y]=-9.2252'; $q = array(); parse_str($val, $q); $xml = simple_xmlify($q); // dump $xml, or... $result = get_formatted_xml($xml); // see below
-// lazy declaration via "queryparam" $args = 'hello=4&var[]=first&var[]=second&foo=1234&var[5]=fifth&var[sub][]=sub1&var[sub][]=sub2&var[sub][]=sub3&var[@name]=the-name&var[@attr2]=something-else&var[sub][@x]=4.356&var[sub][@y]=-9.2252'; $q = array(); parse_str($val, $q); $xml = simple_xmlify($q); // dump $xml, or... $result = get_formatted_xml($xml); // see below
<?xml version="1.0"?> <x> <hello>4</hello> <var name="the-name" attr2="something-else"> <n0>first</n0> <n1>second</n1> <n5>fifth</n5> <sub x="4.356" y="-9.2252"> <n0>sub1</n0> <n1>sub2</n1> <n2>sub3</n2> </sub> </var> <foo>1234</foo> </x>
function get_formatted_xml(SimpleXMLElement $xml, $domver = null, $preserveWhitespace = true, $formatOutput = true) { // http://stackoverflow.com/questions/1191167/format-output-of-simplexml-asxml // create new wrapper, so we can get formatting options $dom = new DOMDocument($domver); $dom->preserveWhiteSpace = $preserveWhitespace; $dom->formatOutput = $formatOutput; // now import the xml (converted to dom format) /* $ix = dom_import_simplexml($xml); $ix = $dom->importNode($ix, true); $dom->appendChild($ix); */ $dom->loadXML($xml->asXML()); // print return $dom->saveXML(); }//-- fn get_formatted_xml
другое решение:
$marray=array(....); $options = array( "encoding" => "UTF-8", "output_type" => "xml", "version" => "simple", "escaping" => array("non-ascii, on-print, markup") ); $xmlres = xmlrpc_encode_request('root', $marray, $options); print($xmlres);
Если массив ассоциативно и правильно введен, возможно, было бы проще сначала превратить его в 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» для каждого узла массива.
Я попробую это позже и обновить этот пост с обеих версий.
Просто отредактируйте функцию выше, когда ключ является числовым, добавьте префикс "key_"
// initializing or creating array $student_info = array(your array data); // creating object of SimpleXMLElement $xml_student_info = new SimpleXMLElement("<?xml version=\"1.0\"?><student_info></student_info>"); // function call to convert array to xml array_to_xml($student,$xml_student_info); //saving generated xml file $xml_student_info->asXML('file path and name'); function array_to_xml($student_info, &$xml_student_info) { foreach($student_info as $key => $value) { if(is_array($value)) { if(!is_numeric($key)){ $subnode = $xml_student_info->addChild("$key"); array_to_xml($value, $subnode); } else{ $subnode = $xml_student_info->addChild("key_$key"); array_to_xml($value, $subnode); } } else { if(!is_numeric($key)){ $xml_student_info->addChild("$key","$value"); }else{ $xml_student_info->addChild("key_$key","$value"); } } } }
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; }
<RoomGroup> <Room> <numberOfAdults>1</numberOfAdults> <numberOfChildren>2</numberOfChildren> <childAges>1,2,0</childAges> </Room> <Room> <numberOfAdults>2</numberOfAdults> <numberOfChildren>0</numberOfChildren> <childAges>1,2,0</childAges> </Room> </RoomGroup>
Я хочу одно и то же имя узла «Комната», конвертируя php в xml. Здесь я нашел его. http://www.codeproject.com/Questions/553031/JSONplusTOplusXMLplusconvertionpluswithplusphp
С FluidXML вы можете сгенерировать, начиная с PHP Array , XML для SimpleXML с … двумя строками кода.
$fluidxml = fluidxml($array); $simplexml = simplexml_import_dom($fluidxml->dom());
Пример массива может быть
$array = [ 'doc' => [ 'fruit' => 'orange', 'cake' => [ '@id' => '123', '@' => 'tiramisu' ], [ 'pasta' => 'matriciana' ], [ 'pasta' => 'boscaiola' ] ] ];
Вы можете использовать xmlrpc_encode для создания xml из массива, если подробный xml не является проблемой. http://www.php.net/xmlrpc_encode
будьте осторожны, созданный xml отличается тем, что вы используете ассоциативные и / или цифровые клавиши
<?php // /params/param/value/struct/member // there is a tag "member" for each element // "member" contains a tag "name". its value is the associative key $xml1 = xmlrpc_encode(array('a'=>'b','c'=>'d')); $simplexml1 = simplexml_load_string($xml1); print_r($xml1); print_r($simplexml1); // /params/param/value/array/data // there is a tag "data" for each element // "data" doesn't contain the tag "name" $xml2 = xmlrpc_encode(array('a','b')); $simplexml2 = simplexml_load_string($xml2); print_r($xml2); print_r($simplexml2); ?>
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-данных в массив php
function xml_to_array ($xml_data) { $p = xml_parser_create(); xml_parse_into_struct($p,$xml_data,$vals,$index); xml_parser_free($p); return $vals; }
См. Эту ссылку для получения дополнительной информации.
Мой ответ, собрав ответы других. Это должно исправить ошибку при сбое цифровых клавиш:
function array_to_xml($array, $root, $element) { $xml = new SimpleXMLElement("<{$root}/>"); foreach ($array as $value) { $elem = $xml->addChild($element); xml_recurse_child($elem, $value); } return $xml; } function xml_recurse_child(&$node, $child) { foreach ($child as $key=>$value) { if(is_array($value)) { foreach ($value as $k => $v) { if(is_numeric($k)){ xml_recurse_child($node, array($key => $v)); } else { $subnode = $node->addChild($key); xml_recurse_child($subnode, $value); } } } else { $node->addChild($key, $value); } } }
Функция array_to_xml()
предполагает, что сначала массив состоит из числовых клавиш. Если в вашем массиве был начальный элемент, вы должны отбросить операторы foreach()
и $elem
из функции array_to_xml()
и вместо этого просто передать $xml
.
Я бы прокомментировал второй наиболее проголосовавший ответ, потому что он не сохраняет структуру и генерирует плохой xml, если есть числовые индексированные внутренние массивы.
Я разработал свою собственную версию на основе этого, потому что мне нужен простой конвертер между json и xml независимо от структуры данных. Моя версия сохраняет информацию о числовом ключе и структуру исходного массива. Он создает элементы для числовых индексированных значений путем переноса значений в элементы с именем, обозначаемыми именем, с ключевым атрибутом, который содержит числовой ключ.
Например
array('test' => array(0 => 'some value', 1 => 'other'))
конвертирует в
<test><value key="0">some value</value><value key="1">other</value></test>
Моя версия array_to_xml -функция (надеюсь, что это поможет кому-то 🙂
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); } } } }
Вы можете использовать следующую функцию в своем коде напрямую,
function artoxml($arr, $i=1,$flag=false){ $sp = ""; for($j=0;$j<=$i;$j++){ $sp.=" "; } foreach($arr as $key=>$val){ echo "$sp<".$key.">"; if($i==1) echo "\n"; if(is_array($val)){ if(!$flag){echo"\n";} artoxml($val,$i+5); echo "$sp</".$key.">\n"; }else{ echo "$val"."</".$key.">\n"; } } }
Вызовите функцию с первым аргументом как ваш массив, а второй аргумент должен быть 1, это будет увеличено для идеального отступа, а третье должно быть истинным.
например, если переменная массива, подлежащая преобразованию, равна $ array1, тогда вызов будет, вызывающая функция должна быть инкапсулирована с <pre>
.
artoxml ($ array1,1, правда);
Пожалуйста, смотрите источник страницы после выполнения файла, потому что символы <и> не будут отображаться на странице html.
Вся структура XML определена в $ data Array:
function array2Xml($data, $xml = null) { if (is_null($xml)) { $xml = simplexml_load_string('<' . key($data) . '/>'); $data = current($data); $return = true; } if (is_array($data)) { foreach ($data as $name => $value) { array2Xml($value, is_numeric($name) ? $xml : $xml->addChild($name)); } } else { $xml->{0} = $data; } if (!empty($return)) { return $xml->asXML(); } }
Если вы работаете в magento, и у вас есть этот тип ассоциативного массива
$test_array = array ( '0' => array ( 'category_id' => '582', 'name' => 'Surat', 'parent_id' => '565', 'child_id' => '567', 'active' => '1', 'level' => '6', 'position' => '17' ), '1' => array ( 'category_id' => '567', 'name' => 'test', 'parent_id' => '0', 'child_id' => '576', 'active' => '0', 'level' => '0', 'position' => '18' ), );
то это лучше всего преобразовать ассоциативный массив в формат xml. Используйте этот код в файле контроллера.
$this->loadLayout(false); //header ("content-type: text/xml"); $this->getResponse()->setHeader('Content-Type','text/xml'); $this->renderLayout(); $clArr2xml = new arr2xml($test_array, 'utf-8', 'listdata'); $output = $clArr2xml->get_xml(); print $output; class arr2xml { var $array = array(); var $xml = ''; var $root_name = ''; var $charset = ''; public function __construct($array, $charset = 'utf-8', $root_name = 'root') { header ("content-type: text/xml"); $this->array = $array; $this->root_name = $root_name; $this->charset = $charset; if (is_array($array) && count($array) > 0) { $this->struct_xml($array); } else { $this->xml .= "no data"; } } public function struct_xml($array) { foreach ($array as $k => $v) { if (is_array($v)) { $tag = ereg_replace('^[0-9]{1,}', 'item', $k); // replace numeric key in array to 'data' $this->xml .= "<$tag>"; $this->struct_xml($v); $this->xml .= "</$tag>"; } else { $tag = ereg_replace('^[0-9]{1,}', 'item', $k); // replace numeric key in array to 'data' $this->xml .= "<$tag><![CDATA[$v]]></$tag>"; } } } public function get_xml() { $header = "<?xml version=\"1.0\" encoding=\"" . $this->charset . "\"?><" . $this->root_name . ">"; $footer = "</" . $this->root_name . ">"; return $header . $this->xml . $footer; } }
I hope it helps to all.