ключи и значения меняются местами - это можно исправить с array_flip()помощью метода array_walk. array_walk_recursiveтребует PHP 5. вы можете использовать array_walkвместо этого, но вы не получите 'stack' => 'overflow'в XML тогда.
Это не будет работать, если $ test_array имеет значение «more_another_array», например «another_array», поскольку ключ «another_array» не преобразуется. Следовательно, у вас будет несколько <overflow> stack </ overflow> '.
Понять
11
Не array_flipбудет работать, так как не может переворачивать массивы (как another_arrayвнутри основного массива).
Лоде
14
Где находится элемент "another_array" xml? Все
сплющено
2
Отлично работал, когда я добавил array_flip перед array_walk_recursive. Спасибо.
Майк Перселл
12
Downvoting, потому что array_flipработает, только если массив не содержит одинаковых значений.
Мартейн
388
Вот код php 5.2, который преобразует массив любой глубины в документ XML:
мы использовали это 'echo $ xml_student_info-> asXML ();' чтобы отобразить этот XML напрямую, но он работает для больших массивов данных. если данные массива меньше десяти элементов, формат xml не отображается, а только в простом формате. мы использовали эту функцию header («Content-type: text / xml»); отображать формат в XML.
Бхарат Ходвадия
1
В этом примере явным образом экранируются специальные символы в текстовых данных элемента с использованием htmlspecialchars, но SimpleXMLElement :: addChild автоматически переводит специальные символы xml в свои объекты char, поэтому htmlspecialchars можно не указывать. Интересно, что это, по-видимому, не приводит к получению дважды экранированных данных.
Мбайтон
1
Пустые значения массива [(string) ""] будут заменены на пустой SimpleXML-узел вместо того, чтобы оставаться пустым.
Джонатан
3
@ Алекс, ваш Edit # 5 делает пример неудачным. Он вставляет <item $ x> перед каждой записью <student>, что делает вывод XML не тем, что задумал автор. Возможно, приведите пример проблемы, которую вы пытаетесь устранить, и мы можем найти другое решение для обоих случаев. Мне потребовалось некоторое время, прежде чем я понял, что авторский код был изменен.
Николас Блазген
1
Если опубликовать два ответа, этот измененный ответ сломал мои запросы, как он добавил <itemN></itemN>. Эта редакция: stackoverflow.com/revisions/5965940/2 была моим победителем
zanderwar
124
Ответы, представленные здесь, только преобразовывают массив в XML с узлами, вы не можете установить атрибуты. Я написал функцию php, которая позволяет вам преобразовывать массив в php, а также устанавливать атрибуты для определенных узлов в xml. Недостатком здесь является то, что вы должны создать массив определенным образом с несколькими соглашениями (только если вы хотите использовать атрибуты)
Следующий пример позволит вам также установить атрибуты в XML.
Меня беспокоит, что никто не отреагировал на это. Этот класс действительно полезен, так как он делает противоположное тому, что сгенерирует simpleXMLElement. Так что это дает вам возможность использовать SimpleXMLElement в обоих направлениях.
FMaz008
4
Я бы отметил это как ответ, а не текущий. Текущий ответ не строит рекурсивные массивы
Александр IY
2
Хороший класс. Я изменил линию 128 , if(!is_array($arr)) {чтобы if(!is_array($arr) && $arr !== '') {таким образом , что она не будет добавлять новый текстовый узел для пустых строк и , следовательно , сохраняет сокращенную пустой формат тегов т.е. 'tag'=>''это <tag/>вместо<tag></tag>
user1433150
Это лучший ответ на данный момент. Также это имеет правильную структуру нескольких элементов с одинаковым ключом: 1-й - это ключ имени узла, затем он содержит массив с числовыми ключами. (противоположность ответа Hanmant)
Я нашел все ответы, чтобы использовать слишком много кода. Вот простой способ сделать это:
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);}}}
Тогда это просто вопрос отправки массива в функцию, которая использует рекурсию, поэтому он будет обрабатывать многомерный массив:
Я люблю это решение больше всего. Хотя, было бы неплохо добавить тест на цифровые клавиши, как: if ( is_numeric( $key ) ) $key = "numeric_$key"; .
Wout
@ Wout Хороший улов. Добавлен. Я сделал проверку приведения типа вместо is_numeric, потому что is_numeric может дать некоторые, хотя и технически ожидаемые результаты, которые действительно отбросят вас.
Фрэнсис Льюис
Я использую эту функцию, но изменил $xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8" ?><rootTag/>');для правильной кодировки UTF-8.
Даантье
Мне также больше всего нравится это решение, простое оно делает :-) Одно замечание: вы можете захотеть изменить $object->addChild($key, $value);его, $object->addChild($key, htmlspecialchars($value));чтобы предотвратить сбой, когда $ value содержит такие символы, как «&», для которых требуется XML-кодировка.
Так или иначе ... Я взял код onokazu (спасибо!) И добавил возможность повторять теги в XML, он также поддерживает атрибуты, надеюсь, кто-то найдет его полезным!
Может быть полезно прокомментировать ваши изменения, чтобы сделать код более понятным; еще, приятное дополнение
StormeHawke
Это сработало для меня с WP All Export. У меня было немного изменить is_numeric часть: if (is_numeric($k)) { $i = $k + 1; $child = $xml->addChild("_$i"); array_to_xml($v, $child); }
Успешность
4
Я использую пару функций, которые я написал некоторое время назад, чтобы сгенерировать xml для передачи туда и обратно из PHP, jQuery и т. Д. Ни один из дополнительных каркасов не используется, просто генерируется строка, которую затем можно использовать с SimpleXML (или другим каркасом ) ...
Если это кому-нибудь пригодится, пожалуйста, используйте его :)
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 =newDOMDocument($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());// printreturn $dom->saveXML();}//-- fn get_formatted_xml
Большинство из приведенных выше ответов являются правильными. Однако я пришел к этому ответу, который решает проблему совместимости array_walk_recursive, а также проблему числовых ключей. Это также прошло все испытания, которые я сделал:
function arrayToXML(Array $array,SimpleXMLElement&$xml){foreach($array as $key => $value){// None arrayif(!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);}}
Я также добавил тестовый класс для этого, который вы можете найти полезным:
classArrayToXmlTestextendsPHPUnit_Framework_TestCase{publicfunction setUp(){}publicfunction tearDown(){}publicfunction testFuncExists(){
$this->assertTrue(function_exists('arrayToXML'));}publicfunction testFuncReturnsXml(){
$array = array('name'=>'ardi','last_name'=>'eshghi','age'=>31,'tel'=>'0785323435');
$xmlEl =newSimpleXMLElement('<root/>');
arrayToXml($array, $xmlEl);
$this->assertTrue($xmlEl instanceOf SimpleXMLElement);}publicfunction testAssocArrayToXml(){
$array = array('name'=>'ardi','last_name'=>'eshghi','age'=>31,'tel'=>'0785323435');
$expectedXmlEl =newSimpleXMLElement('<root/>');
$expectedXmlEl->addChild('name', $array['name']);
$expectedXmlEl->addChild('last_name', $array['last_name']);
$expectedXmlEl->addChild('age', $array['age']);
$expectedXmlEl->addChild('tel', $array['tel']);
$actualXmlEl =newSimpleXMLElement('<root/>');
arrayToXml($array, $actualXmlEl);
$this->assertEquals($expectedXmlEl->asXML(), $actualXmlEl->asXML());}publicfunction testNoneAssocArrayToXml(){
$array = array('ardi','eshghi',31,'0785323435');// Expected xml value
$expectedXmlEl =newSimpleXMLElement('<root/>');foreach($array as $key => $value)
$expectedXmlEl->addChild("item$key", $value);// What the function produces
$actualXmlEl =newSimpleXMLElement('<root/>');
arrayToXml($array, $actualXmlEl);
$this->assertEquals($expectedXmlEl->asXML(), $actualXmlEl->asXML());}publicfunction 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 =newSimpleXMLElement('<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 =newSimpleXMLElement('<root/>');
arrayToXml($testArray, $actualXmlEl);
$this->assertEquals($expectedXmlEl->asXML(), $actualXmlEl->asXML());}}
Это приводит к неожиданному эффекту создания XML в стиле RPC с такими вещами, как methodCall, methodName, скаляры и векторы и т. Д. На самом деле преобразование массива в XML не является простым.
Volomike
3
Если массив является ассоциативным и имеет правильный ключ, было бы легче сначала превратить его в xml. Что-то вроде:
а затем для каждой части вашего массива используйте нечто похожее на мой цикл создания текста и вместо этого используйте функции simplexml "addChild" для каждого узла массива.
Я попробую это позже и обновлю этот пост обеими версиями.
Этот бит, в котором я упомянул «<массив> </ массив>», заставил меня понять, что строковая версия нуждается в чем-то подобном. В основном массив должен иметь один узел снаружи. Позвольте мне поспать в целом, у меня будет что-то, что сразу же поймает эту первоначальную ошибку.
Энтони
2
Просто отредактируйте функцию выше, когда ключ числовой, добавьте префикс "key_"
// initializing or creating array
$student_info = array(your array data);// creating object of SimpleXMLElement
$xml_student_info =newSimpleXMLElement("<?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 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-странице.
Вы можете использовать xmlrpc_encode для создания XML из массива, если подробный XML не является проблемой.
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);?>
Эта функция не поддерживается и, по сути, не предусмотрена в моих сборках PHP 5.2.16 или PHP 5.3.5. (возвращает «PHP Fatal error: вызов неопределенной функции xmlrpc_encode ()»)
Данортон,
Вы должны раскомментировать следующую строку в php.ini: extension = php_xmlrpc.dll
w35l3y
@ w35l3y Я проверил свои ini. Он даже не содержит этого расширения, и я использую v 5.3.6.
Мой ответ, объединяя ответы других. Это должно исправить невозможность компенсации цифровых клавиш:
function array_to_xml($array, $root, $element){
$xml =newSimpleXMLElement("<{$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_flip()
помощью метода array_walk.array_walk_recursive
требует PHP 5. вы можете использоватьarray_walk
вместо этого, но вы не получите'stack' => 'overflow'
в XML тогда.источник
array_flip
будет работать, так как не может переворачивать массивы (какanother_array
внутри основного массива).array_flip
работает, только если массив не содержит одинаковых значений.Вот код php 5.2, который преобразует массив любой глубины в документ XML:
сгенерированный XML будет выглядеть так:
PHP-фрагмент
Документация по
SimpleXMLElement::asXML
использованию в этом фрагментеисточник
<itemN></itemN>
. Эта редакция: stackoverflow.com/revisions/5965940/2 была моим победителемОтветы, представленные здесь, только преобразовывают массив в XML с узлами, вы не можете установить атрибуты. Я написал функцию php, которая позволяет вам преобразовывать массив в php, а также устанавливать атрибуты для определенных узлов в xml. Недостатком здесь является то, что вы должны создать массив определенным образом с несколькими соглашениями (только если вы хотите использовать атрибуты)
Следующий пример позволит вам также установить атрибуты в XML.
Источник можно найти здесь: https://github.com/digitickets/lalit/blob/master/src/Array2XML.php
источник
if(!is_array($arr)) {
чтобыif(!is_array($arr) && $arr !== '') {
таким образом , что она не будет добавлять новый текстовый узел для пустых строк и , следовательно , сохраняет сокращенную пустой формат тегов т.е.'tag'=>''
это<tag/>
вместо<tag></tag>
Я нашел все ответы, чтобы использовать слишком много кода. Вот простой способ сделать это:
Тогда это просто вопрос отправки массива в функцию, которая использует рекурсию, поэтому он будет обрабатывать многомерный массив:
Теперь $ xml содержит красивый объект XML, основанный на вашем массиве, именно так, как вы его написали.
источник
if ( is_numeric( $key ) ) $key = "numeric_$key";
.$xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8" ?><rootTag/>');
для правильной кодировки UTF-8.$object->addChild($key, $value);
его,$object->addChild($key, htmlspecialchars($value));
чтобы предотвратить сбой, когда $ value содержит такие символы, как «&», для которых требуется XML-кодировка.источник
$k = (is_numeric($k)) ? 'item' : $k;
внутриforeach()
Из PHP 5.4
источник
Еще одно улучшение:
Использование:
источник
Вот моя запись, простая и чистая ..
источник
Так или иначе ... Я взял код onokazu (спасибо!) И добавил возможность повторять теги в XML, он также поддерживает атрибуты, надеюсь, кто-то найдет его полезным!
источник
if (is_numeric($k)) { $i = $k + 1; $child = $xml->addChild("_$i"); array_to_xml($v, $child); }
Я использую пару функций, которые я написал некоторое время назад, чтобы сгенерировать xml для передачи туда и обратно из PHP, jQuery и т. Д. Ни один из дополнительных каркасов не используется, просто генерируется строка, которую затем можно использовать с SimpleXML (или другим каркасом ) ...
Если это кому-нибудь пригодится, пожалуйста, используйте его :)
Всем любви :)
источник
Я хотел код, который будет принимать все элементы внутри массива и обрабатывать их как атрибуты, а все массивы как подэлементы.
Так что для чего-то вроде
Я бы получил что-то вроде этого
Чтобы добиться этого, код приведен ниже, но будьте очень осторожны, он рекурсивен и может фактически вызвать переполнение стека :)
Возможно, вы захотите добавить проверки длины массива, чтобы некоторый элемент был установлен внутри части данных, а не как атрибут.
источник
Основываясь на всем остальном, обрабатывает числовые индексы + атрибуты с помощью префикса
@
и может внедрить xml в существующие узлы:Код
использование
результат
Бонус: форматирование XML
источник
Вот функция, которая добилась цели для меня:
Просто позвоните с чем-то вроде
источник
Вы можете использовать XMLParser , над которым я работал.
В результате:
источник
Я нашел это решение похоже на исходную проблему
источник
Большинство из приведенных выше ответов являются правильными. Однако я пришел к этому ответу, который решает проблему совместимости array_walk_recursive, а также проблему числовых ключей. Это также прошло все испытания, которые я сделал:
Я также добавил тестовый класс для этого, который вы можете найти полезным:
источник
другое решение:
источник
Если массив является ассоциативным и имеет правильный ключ, было бы легче сначала превратить его в xml. Что-то вроде:
Другой путь - сначала создать базовый XML, например
а затем для каждой части вашего массива используйте нечто похожее на мой цикл создания текста и вместо этого используйте функции simplexml "addChild" для каждого узла массива.
Я попробую это позже и обновлю этот пост обеими версиями.
источник
Просто отредактируйте функцию выше, когда ключ числовой, добавьте префикс "key_"
источник
Вы можете использовать следующую функцию в своем коде напрямую,
Вызовите функцию с первым аргументом в качестве массива, а второй аргумент должен быть равен 1, это будет увеличено для идеального отступа, а третий должен быть истинным.
например, если переменная массива для преобразования равна $ array1, то при вызове вызывающая функция должна быть заключена в
<pre>
тег.Пожалуйста, посмотрите исходный код страницы после выполнения файла, потому что символы <и> не будут отображаться на HTML-странице.
источник
источник
Эта функция возвращает, например, список тегов <obj> ... </ obj> <obj> ... </ obj> XML для числовых индексов.
Входные данные:
Вывод:
Это должно удовлетворить все общие потребности. Возможно, вы можете изменить 3-ю строку на:
или если вы работаете с множественным числом, оканчивающимся на s:
источник
С FluidXML вы можете сгенерировать, начиная с массива PHP , XML для SimpleXML с ... всего двумя строками кода.
Пример массива может быть
https://github.com/servo-php/fluidxml
источник
Вы можете использовать xmlrpc_encode для создания XML из массива, если подробный XML не является проблемой. www.php.net/xmlrpc_encode
будьте осторожны, создаваемый xml отличается в случае использования ассоциативных и / или цифровых клавиш
источник
источник
Мой ответ, объединяя ответы других. Это должно исправить невозможность компенсации цифровых клавиш:
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 (надеюсь, она кому-нибудь поможет :)
источник
Вся структура XML определена в массиве $ data:
источник
Если вы работаете в magento и у вас есть этот тип ассоциативного массива
тогда лучше всего конвертировать ассоциативный массив в формат xml. Используйте этот код в файле контроллера.
Я надеюсь, что это помогает всем.
источник
источник