las claves y los valores se intercambian; podría solucionarlo array_flip()antes de array_walk. array_walk_recursiverequiere PHP 5. que podría usar array_walken su lugar, pero no entrará 'stack' => 'overflow'en el xml entonces.
Esto no funcionará si $ test_array tiene 'more_another_array' como 'another_array', porque la clave 'another_array' no se convierte. Por lo tanto, tendrá múltiples '<overflow> stack </overflow>'.
comprensión
11
El array_flipno va a funcionar, ya que puede no matrices flip (al igual que el another_arrayinterior de la matriz principal).
Lode
14
¿Dónde está el elemento xml "another_array"? Todo se
aplana
2
Funcionó muy bien cuando agregué array_flip antes de array_walk_recursive. Gracias.
Mike Purcell
12
Downvoting porque array_flipsolo funciona si la matriz no contiene valores idénticos.
Martijn
385
Aquí está el código php 5.2 que convertirá una matriz de cualquier profundidad en un documento xml:
Esto, IMO, es una solución mucho mejor que la respuesta aceptada. Sin embargo, esto tiene la limitación de que con las matrices con clave numérica, genera XML con formato incorrecto. <0> <1> <2> no son nombres de nodo válidos.
KOGI
2
Sin embargo, si su matriz con clave numérica solo contiene otra matriz que no tiene clave numérica, no lo hará.
Bryan Petty
15
@KOGI He modificado la respuesta de Hanmant. Ahora es compatible con matrices multinivel. pastebin.com/pYuXQWee
Mifas
1
Este ejemplo escapa explícitamente a los caracteres especiales en los datos de texto del elemento usando htmlspecialchars, pero SimpleXMLElement :: addChild traduce los caracteres especiales xml a sus entidades char automáticamente para que htmlspecialchars puedan omitirse. Curiosamente, esto parece no dar lugar a datos con doble escape.
mbaynton
3
@Alex, tu Edit # 5 hace que el ejemplo falle. Inserta <item $ x> antes de cada registro <student> haciendo que la salida XML no sea lo que el autor pretendía. Tal vez proporcione un ejemplo del problema que está tratando de solucionar y podemos encontrar otra solución para ambos casos. Me tomó un tiempo antes de darme cuenta de que el código del autor fue modificado.
Nicholas Blasgen
124
Las respuestas proporcionadas aquí solo convierten la matriz a XML con nodos, no puede establecer atributos. He escrito una función php que le permite convertir una matriz a php y también establecer atributos para nodos particulares en el xml. La desventaja aquí es que tiene que construir una matriz de una manera particular con pocas convenciones (solo si desea usar atributos)
El siguiente ejemplo también le permitirá establecer atributos en XML.
Me sorprende que nadie haya reaccionado ante esto. Esta clase es realmente útil ya que está haciendo lo contrario de lo que generará XMLElement. Por lo tanto, le brinda la posibilidad de usar SimpleXMLElement en ambos sentidos.
FMaz008
44
Lo marcaría como respuesta en lugar de actual. Respuesta actual que no construye matrices recursivas
Oleksandr IY
2
Buena clase Cambié la línea 128 if(!is_array($arr)) {para if(!is_array($arr) && $arr !== '') {que no agregue un nuevo nodo de texto para cadenas vacías y, por lo tanto, mantenga el formato de etiqueta vacía, 'tag'=>''es decir, en <tag/>lugar de<tag></tag>
user1433150
Esta es la mejor respuesta hasta ahora. Además, tiene la estructura correcta de varios elementos con la misma clave: primero es la clave de nombre de nodo, luego contiene la matriz con claves numéricas. (lo contrario de la respuesta de Hanmant)
Encontré todas las respuestas para usar demasiado código. Aquí hay una manera fácil de hacerlo:
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);}}}
Entonces es una simple cuestión de enviar la matriz a la función, que utiliza la recursividad, por lo que manejará una matriz multidimensional:
Me encanta esta solución más. Si bien, sería bueno añadir una prueba de teclas numéricas, como: if ( is_numeric( $key ) ) $key = "numeric_$key"; .
Wout 01 de
@wout Buena captura. Adicional. Hice una comprobación int cast en lugar de is_numeric porque is_numeric puede dar algunos resultados, aunque técnicamente esperados, que realmente te desanimarán.
Francis Lewis
Utilizo esta función, pero cambié $xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8" ?><rootTag/>');por una codificación UTF-8 válida.
Daantje
Me gusta esta solución los más así, simple lo hace :-) Una observación: Es posible que desee cambiar $object->addChild($key, $value);a $object->addChild($key, htmlspecialchars($value));para evitar que falle cuando $ valor contiene caracteres como "&" esa necesidad XML-codificación.
De todos modos ... Tomé el código de onokazu (¡gracias!) Y agregué la capacidad de tener etiquetas repetidas en XML, también admite atributos, ¡espero que alguien lo encuentre útil!
Puede ser útil comentar sus cambios para aclarar el código; Aún así, buena adición
StormeHawke
Esto funcionó para mí con WP All Export. Tuve que cambiar la parte is_numeric ligeramente: if (is_numeric($k)) { $i = $k + 1; $child = $xml->addChild("_$i"); array_to_xml($v, $child); }
cumplidor
4
Utilizo un par de funciones que escribí hace un tiempo para generar el xml para pasar de PHP y jQuery, etc. No utilizo ningún marco adicional simplemente genera una cadena que luego puede usarse con SimpleXML (u otro marco ) ...
Para lograr esto, el código está debajo, pero tenga mucho cuidado, es recursivo y puede causar un desbordamiento de pila :)
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=newSimpleXMLElement('<?xml version=\'1.0\' encoding=\'utf-8\'?><'.key($array).'/>');
addElements($xml,$array[key($array)]);return $xml->asXML();}
Es posible que desee agregar comprobaciones para la longitud de la matriz para que algún elemento se establezca dentro de la parte de datos y no como un atributo.
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
La mayoría de las respuestas anteriores son correctas. Sin embargo, se me ocurrió esta respuesta que resuelve el problema de compatibilidad array_walk_recursive y también el problema de las teclas numéricas. También pasó todas las pruebas que hice:
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);}}
También he agregado una clase de prueba para esto que puede ser útil:
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'=>'[email protected]'),'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());}}
Esto tiene un efecto inesperado de crear XML de estilo RPC con cosas como methodCall, methodName, escalares y vectores, etc. Realmente no está convirtiendo una matriz en XML en el sentido directo.
Volomike
3
Si la matriz es asociativa y está codificada correctamente, probablemente sería más fácil convertirla primero en xml. Algo como:
y luego, para cada parte de su matriz, use algo similar a mi ciclo de creación de texto y en su lugar use las funciones simplexml "addChild" para cada nodo de la matriz.
Lo probaré más tarde y actualizaré esta publicación con ambas versiones.
Ese bit donde mencioné "<array> </array>" me hizo darme cuenta de que la versión de cadena necesita algo similar. Básicamente, la matriz debe tener un nodo en el exterior. Déjame dormir sobre todo, tendré algo que atrapa ese error inicial de inmediato.
Anthony
2
Solo una edición en una función anterior, cuando una tecla es numérica, agregue el prefijo "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");}}}}
Puede usar la siguiente función en su código directamente,
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";}}}
Llame a la función con el primer argumento como su matriz y el segundo argumento debe ser 1, esto se incrementará para una sangría perfecta, y el tercero debe ser verdadero.
por ejemplo, si la variable de matriz que se va a convertir es $ array1, la llamada debería encapsularse con la <pre>etiqueta.
artoxml ($ array1,1, verdadero);
Consulte la fuente de la página después de ejecutar el archivo, ya que los símbolos <y> no se mostrarán en una página html.
Puede usar xmlrpc_encode para crear un xml a partir de una matriz si un xml detallado no es un problema.
www.php.net/xmlrpc_encode
tenga cuidado de que el xml creado difiera en caso de que use claves asociativas y / o numéricas
<?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);?>
Esta función no es compatible y, de hecho, no se proporciona en mis compilaciones de PHP 5.2.16 o PHP 5.3.5. (devuelve "Error fatal de PHP: Llamada a la función indefinida xmlrpc_encode ()")
danorton
debe descomentar la siguiente línea en php.ini: extension = php_xmlrpc.dll
w35l3y
@ w35l3y Revisé mi ini. Ni siquiera contiene esa extensión y estoy usando v 5.3.6.
Mi respuesta, juntando las respuestas de los demás. Esto debería corregir la falla al compensar las teclas numéricas:
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);}}}
La array_to_xml()función supone que la matriz se compone primero de teclas numéricas. Si su matriz tuviera un elemento inicial, eliminaría las declaraciones foreach()y $elemde la array_to_xml()función y simplemente pasaría en su $xmllugar.
Hubiera comentado la segunda respuesta más votada, porque no conserva la estructura y genera un xml incorrecto si hay matrices internas indexadas numéricamente.
Desarrollé mi propia versión basada en él, porque necesitaba un convertidor simple entre json y xml, independientemente de la estructura de datos. Mi versión conserva la información clave numérica y la estructura de la matriz original. Crea elementos para los valores indexados numéricamente ajustando valores a elementos con nombre de valor con clave-atributo que contiene clave numérica.
Respuestas:
uno corto:
resultados en
las claves y los valores se intercambian; podría solucionarlo
array_flip()
antes de array_walk.array_walk_recursive
requiere PHP 5. que podría usararray_walk
en su lugar, pero no entrará'stack' => 'overflow'
en el xml entonces.fuente
array_flip
no va a funcionar, ya que puede no matrices flip (al igual que elanother_array
interior de la matriz principal).array_flip
solo funciona si la matriz no contiene valores idénticos.Aquí está el código php 5.2 que convertirá una matriz de cualquier profundidad en un documento xml:
XML generado sería como:
Fragmento de PHP
Documentación sobre el
SimpleXMLElement::asXML
uso en este fragmentofuente
Las respuestas proporcionadas aquí solo convierten la matriz a XML con nodos, no puede establecer atributos. He escrito una función php que le permite convertir una matriz a php y también establecer atributos para nodos particulares en el xml. La desventaja aquí es que tiene que construir una matriz de una manera particular con pocas convenciones (solo si desea usar atributos)
El siguiente ejemplo también le permitirá establecer atributos en XML.
La fuente se puede encontrar aquí: https://github.com/digitickets/lalit/blob/master/src/Array2XML.php
fuente
if(!is_array($arr)) {
paraif(!is_array($arr) && $arr !== '') {
que no agregue un nuevo nodo de texto para cadenas vacías y, por lo tanto, mantenga el formato de etiqueta vacía,'tag'=>''
es decir, en<tag/>
lugar de<tag></tag>
Encontré todas las respuestas para usar demasiado código. Aquí hay una manera fácil de hacerlo:
Entonces es una simple cuestión de enviar la matriz a la función, que utiliza la recursividad, por lo que manejará una matriz multidimensional:
Ahora $ xml contiene un hermoso objeto XML basado en su matriz exactamente como lo escribió.
fuente
if ( is_numeric( $key ) ) $key = "numeric_$key";
.$xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8" ?><rootTag/>');
por una codificación UTF-8 válida.$object->addChild($key, $value);
a$object->addChild($key, htmlspecialchars($value));
para evitar que falle cuando $ valor contiene caracteres como "&" esa necesidad XML-codificación.fuente
$k = (is_numeric($k)) ? 'item' : $k;
dentro de laforeach()
Desde PHP 5.4
fuente
Otra mejora:
Uso:
fuente
Aquí está mi entrada, simple y limpia.
fuente
De todos modos ... Tomé el código de onokazu (¡gracias!) Y agregué la capacidad de tener etiquetas repetidas en XML, también admite atributos, ¡espero que alguien lo encuentre útil!
fuente
if (is_numeric($k)) { $i = $k + 1; $child = $xml->addChild("_$i"); array_to_xml($v, $child); }
Utilizo un par de funciones que escribí hace un tiempo para generar el xml para pasar de PHP y jQuery, etc. No utilizo ningún marco adicional simplemente genera una cadena que luego puede usarse con SimpleXML (u otro marco ) ...
Si es útil para alguien, úselo :)
Amor a todos :)
fuente
Quería un código que tomara todos los elementos dentro de una matriz y los tratara como atributos, y todas las matrices como subelementos.
Entonces para algo como
Obtendría algo como esto
Para lograr esto, el código está debajo, pero tenga mucho cuidado, es recursivo y puede causar un desbordamiento de pila :)
Es posible que desee agregar comprobaciones para la longitud de la matriz para que algún elemento se establezca dentro de la parte de datos y no como un atributo.
fuente
Basado en todo lo demás aquí, maneja índices numéricos + atributos mediante prefijos con
@
, y podría inyectar xml a los nodos existentes:Código
Uso
Resultado
Bonificación: formato XML
fuente
Aquí hay una función que me funcionó:
Solo llámalo con algo como
fuente
Podrías usar el XMLParser en el que he estado trabajando.
Daría como resultado:
fuente
Encontré esta solución similar al problema original
fuente
La mayoría de las respuestas anteriores son correctas. Sin embargo, se me ocurrió esta respuesta que resuelve el problema de compatibilidad array_walk_recursive y también el problema de las teclas numéricas. También pasó todas las pruebas que hice:
También he agregado una clase de prueba para esto que puede ser útil:
fuente
otra solución:
fuente
Si la matriz es asociativa y está codificada correctamente, probablemente sería más fácil convertirla primero en xml. Algo como:
La otra ruta sería crear tu xml básico primero, como
y luego, para cada parte de su matriz, use algo similar a mi ciclo de creación de texto y en su lugar use las funciones simplexml "addChild" para cada nodo de la matriz.
Lo probaré más tarde y actualizaré esta publicación con ambas versiones.
fuente
Solo una edición en una función anterior, cuando una tecla es numérica, agregue el prefijo "key_"
fuente
Puede usar la siguiente función en su código directamente,
Llame a la función con el primer argumento como su matriz y el segundo argumento debe ser 1, esto se incrementará para una sangría perfecta, y el tercero debe ser verdadero.
por ejemplo, si la variable de matriz que se va a convertir es $ array1, la llamada debería encapsularse con la
<pre>
etiqueta.Consulte la fuente de la página después de ejecutar el archivo, ya que los símbolos <y> no se mostrarán en una página html.
fuente
fuente
Esta función devuelve, por ejemplo, una lista de <obj>...</obj> <obj> ... </obj> etiquetas XML para índices numéricos.
Entrada:
Salida:
Esto debería satisfacer todas las necesidades comunes. Tal vez pueda cambiar la tercera línea a:
o si está trabajando con plurales que terminan en s:
fuente
Con FluidXML puede generar, a partir de una matriz de PHP , un XML para SimpleXML con ... solo dos líneas de código.
Un conjunto de ejemplos podría ser
https://github.com/servo-php/fluidxml
fuente
Puede usar xmlrpc_encode para crear un xml a partir de una matriz si un xml detallado no es un problema. www.php.net/xmlrpc_encode
tenga cuidado de que el xml creado difiera en caso de que use claves asociativas y / o numéricas
fuente
fuente
Mi respuesta, juntando las respuestas de los demás. Esto debería corregir la falla al compensar las teclas numéricas:
La
array_to_xml()
función supone que la matriz se compone primero de teclas numéricas. Si su matriz tuviera un elemento inicial, eliminaría las declaracionesforeach()
y$elem
de laarray_to_xml()
función y simplemente pasaría en su$xml
lugar.fuente
Hubiera comentado la segunda respuesta más votada, porque no conserva la estructura y genera un xml incorrecto si hay matrices internas indexadas numéricamente.
Desarrollé mi propia versión basada en él, porque necesitaba un convertidor simple entre json y xml, independientemente de la estructura de datos. Mi versión conserva la información clave numérica y la estructura de la matriz original. Crea elementos para los valores indexados numéricamente ajustando valores a elementos con nombre de valor con clave-atributo que contiene clave numérica.
Por ejemplo
array('test' => array(0 => 'some value', 1 => 'other'))
se convierte a
<test><value key="0">some value</value><value key="1">other</value></test>
Mi versión de la función array_to_xml (espero que ayude a alguien :)
fuente
Toda la estructura XML se define en $ data Array:
fuente
Si trabajas en magento y tienes este tipo de matriz asociativa
entonces es mejor convertir la matriz asociativa al formato xml. Use este código en el archivo del controlador.
Espero que ayude a todos.
fuente
fuente