PHP convierte XML a JSON

158

Estoy tratando de convertir xml a json en php. Si hago una conversión simple usando xml simple y json_encode ninguno de los atributos en el show xml.

$xml = simplexml_load_file("states.xml");
echo json_encode($xml);

Así que estoy tratando de analizarlo manualmente de esta manera.

foreach($xml->children() as $state)
{
    $states[]= array('state' => $state->name); 
}       
echo json_encode($states);

y la salida para el estado es {"state":{"0":"Alabama"}}más que{"state":"Alabama"}

¿Qué estoy haciendo mal?

XML:

<?xml version="1.0" ?>
<states>
    <state id="AL">     
    <name>Alabama</name>
    </state>
    <state id="AK">
        <name>Alaska</name>
    </state>
</states>

Salida:

[{"state":{"0":"Alabama"}},{"state":{"0":"Alaska"}

volcado var:

object(SimpleXMLElement)#1 (1) {
["state"]=>
array(2) {
[0]=>
object(SimpleXMLElement)#3 (2) {
  ["@attributes"]=>
  array(1) {
    ["id"]=>
    string(2) "AL"
  }
  ["name"]=>
  string(7) "Alabama"
}
[1]=>
object(SimpleXMLElement)#2 (2) {
  ["@attributes"]=>
  array(1) {
    ["id"]=>
    string(2) "AK"
  }
  ["name"]=>
  string(6) "Alaska"
}
}
}
Bryan Hadlock
fuente
Incluya un fragmento del XML y la estructura de matriz final que tiene después de analizarlo. (A var_dumpfunciona bien.)
nikc.org
entrada, salida y var_dump añadidos
Bryan Hadlock
Algunas aplicaciones necesitan un "mapa de XML a JSON perfecto " , es decir , jsonML . Consulte la solución aquí .
Peter Krauss

Respuestas:

473

Json & Array de XML en 3 líneas:

$xml = simplexml_load_string($xml_string);
$json = json_encode($xml);
$array = json_decode($json,TRUE);
Antonio Max
fuente
59
Esta solución no es perfecta. Descarta completamente los atributos XML. Entonces <person my-attribute='name'>John</person>se interpreta como <person>John</person>.
Jake Wilson el
13
$ xml = simplexml_load_string ($ xml_string, 'SimpleXMLElement', LIBXML_NOCDATA); para aplanar elementos cdata.
txyoji
28
@JakeWilson tal vez hayan pasado 2 años y se hayan corregido varias versiones, pero en PHP 5.6.30, este método produce TODOS los datos. Los atributos se almacenan en la matriz bajo la @attributesclave, por lo que funciona de manera absolutamente perfecta y hermosa. 3 líneas cortas de código resuelven mi problema maravillosamente.
AlexanderMP
1
Esto no funciona si tiene varios espacios de nombres, puede elegir solo uno, que pasará a $ json_string: '(
jirislav
1
Tenga en cuenta que con esta solución, cuando puede haber múltiples nodos con el mismo nombre, un nodo dará como resultado que una clave solo apunte a un elemento, pero múltiples nodos resultarán en una clave que apunta a una matriz de elementos: <list><item><a>123</a><a>456</a></item><item><a>123</a></item></list>-> {"item":[{"a":["123","456"]},{"a":"123"}]}. Una solución en php.net por ratfactor resuelve ese problema almacenando siempre elementos en una matriz.
Klesun
37

Perdón por responder una publicación anterior, pero este artículo describe un enfoque relativamente breve, conciso y fácil de mantener. Lo probé yo mismo y funciona bastante bien.

http://lostechies.com/seanbiefeld/2011/10/21/simple-xml-to-json-with-php/

<?php   
class XmlToJson {
    public function Parse ($url) {
        $fileContents= file_get_contents($url);
        $fileContents = str_replace(array("\n", "\r", "\t"), '', $fileContents);
        $fileContents = trim(str_replace('"', "'", $fileContents));
        $simpleXml = simplexml_load_string($fileContents);
        $json = json_encode($simpleXml);

        return $json;
    }
}
?>
Coreus
fuente
44
Esto no funcionará si tiene varias instancias de la misma etiqueta en su XML, json_encode terminará solo serializando la última instancia de la etiqueta.
ethree
35

Me lo imaginé. json_encode maneja los objetos de manera diferente a las cadenas. Lanzo el objeto a una cadena y funciona ahora.

foreach($xml->children() as $state)
{
    $states[]= array('state' => (string)$state->name); 
}       
echo json_encode($states);
Bryan Hadlock
fuente
19

Supongo que llego un poco tarde a la fiesta, pero he escrito una pequeña función para realizar esta tarea. También se ocupa de los atributos, el contenido del texto e incluso si varios nodos con el mismo nombre de nodo son hermanos.

Descargo de responsabilidad: no soy un nativo de PHP, así que por favor tenga en cuenta los errores simples.

function xml2js($xmlnode) {
    $root = (func_num_args() > 1 ? false : true);
    $jsnode = array();

    if (!$root) {
        if (count($xmlnode->attributes()) > 0){
            $jsnode["$"] = array();
            foreach($xmlnode->attributes() as $key => $value)
                $jsnode["$"][$key] = (string)$value;
        }

        $textcontent = trim((string)$xmlnode);
        if (count($textcontent) > 0)
            $jsnode["_"] = $textcontent;

        foreach ($xmlnode->children() as $childxmlnode) {
            $childname = $childxmlnode->getName();
            if (!array_key_exists($childname, $jsnode))
                $jsnode[$childname] = array();
            array_push($jsnode[$childname], xml2js($childxmlnode, true));
        }
        return $jsnode;
    } else {
        $nodename = $xmlnode->getName();
        $jsnode[$nodename] = array();
        array_push($jsnode[$nodename], xml2js($xmlnode, true));
        return json_encode($jsnode);
    }
}   

Ejemplo de uso:

$xml = simplexml_load_file("myfile.xml");
echo xml2js($xml);

Entrada de ejemplo (myfile.xml):

<family name="Johnson">
    <child name="John" age="5">
        <toy status="old">Trooper</toy>
        <toy status="old">Ultrablock</toy>
        <toy status="new">Bike</toy>
    </child>
</family>

Salida de ejemplo:

{"family":[{"$":{"name":"Johnson"},"child":[{"$":{"name":"John","age":"5"},"toy":[{"$":{"status":"old"},"_":"Trooper"},{"$":{"status":"old"},"_":"Ultrablock"},{"$":{"status":"new"},"_":"Bike"}]}]}]}

Bastante impreso:

{
    "family" : [{
            "$" : {
                "name" : "Johnson"
            },
            "child" : [{
                    "$" : {
                        "name" : "John",
                        "age" : "5"
                    },
                    "toy" : [{
                            "$" : {
                                "status" : "old"
                            },
                            "_" : "Trooper"
                        }, {
                            "$" : {
                                "status" : "old"
                            },
                            "_" : "Ultrablock"
                        }, {
                            "$" : {
                                "status" : "new"
                            },
                            "_" : "Bike"
                        }
                    ]
                }
            ]
        }
    ]
}

Quirks a tener en cuenta: varias etiquetas con el mismo nombre de etiqueta pueden ser hermanos. Es probable que otras soluciones eliminen todas menos la última hermana. Para evitar esto, todos y cada uno de los nodos, incluso si solo tiene un hijo, es una matriz que contiene un objeto para cada instancia del nombre de etiqueta. (Ver múltiples "" elementos en el ejemplo)

Incluso el elemento raíz, del cual solo debe existir uno en un documento XML válido, se almacena como una matriz con un objeto de la instancia, solo para tener una estructura de datos coherente.

Para poder distinguir entre el contenido del nodo XML y los atributos XML, los atributos de cada objeto se almacenan en "$" y el contenido en el elemento secundario "_".

Editar: olvidé mostrar la salida para sus datos de entrada de ejemplo

{
    "states" : [{
            "state" : [{
                    "$" : {
                        "id" : "AL"
                    },
                    "name" : [{
                            "_" : "Alabama"
                        }
                    ]
                }, {
                    "$" : {
                        "id" : "AK"
                    },
                    "name" : [{
                            "_" : "Alaska"
                        }
                    ]
                }
            ]
        }
    ]
}
FTav
fuente
¿Puede analizar datos XML grandes?
Volatil3
2
Esta solución es mejor porque no descarta los atributos XML. Vea también por qué esta estructura compleja es mejor que las simplificadas, en xml.com/lpt/a/1658 (consulte "XML semiestructurado ") ... Ops, para CDATA, como @txyoji sugirió aplanar elementos CDATA $xml = simplexml_load_file("myfile.xml",'SimpleXMLElement',LIBXML_‌​NOCDATA);.
Peter Krauss
¡Muchas gracias por una función personalizada! Hace que la sintonización sea bastante fácil. Por cierto, agregó una versión editada de su función que analiza XML de una manera JS: cada entrada tiene su propio objeto (las entradas no se almacenan en una sola matriz si tienen nombres de etiqueta iguales), por lo que se conserva el orden.
lucifer63
1
Error Fatal error: Uncaught Error: Call to a member function getName() on bool... creo que una versión php falla :-( .. por favor ayuda!
KingRider
10

Un error común es olvidar que json_encode()no respeta elementos con un valor de texto y atributo (s). Escogerá uno de esos, lo que significa dataloss. La siguiente función resuelve ese problema. Si uno decide ir por json_encode/ decodeway, se recomienda la siguiente función.

function json_prepare_xml($domNode) {
  foreach($domNode->childNodes as $node) {
    if($node->hasChildNodes()) {
      json_prepare_xml($node);
    } else {
      if($domNode->hasAttributes() && strlen($domNode->nodeValue)){
         $domNode->setAttribute("nodeValue", $node->textContent);
         $node->nodeValue = "";
      }
    }
  }
}

$dom = new DOMDocument();
$dom->loadXML( file_get_contents($xmlfile) );
json_prepare_xml($dom);
$sxml = simplexml_load_string( $dom->saveXML() );
$json = json_decode( json_encode( $sxml ) );

al hacerlo, <foo bar="3">Lorem</foo>no terminará como {"foo":"Lorem"}en su JSON.

Codificador de Salvación
fuente
No se compila y no produce el resultado descrito si se corrigen los errores de sintaxis.
Richard Kiefer
¿Qué es $dom? De donde vino eso?
Jake Wilson el
$ dom = nuevo DOMDocument (); es de donde viene
Scott
1
Última línea de código: $ json = json_decode (json_encode ($ sxml))); debe ser: $ json = json_decode (json_encode ($ sxml));
Charlie Smith
6

Intenta usar esto

$xml = ... // Xml file data

// first approach
$Json = json_encode(simplexml_load_string($xml));

---------------- OR -----------------------

// second approach
$Json = json_encode(simplexml_load_string($xml, "SimpleXMLElement", LIBXML_NOCDATA));

echo $Json;

O

Puede usar esta biblioteca: https://github.com/rentpost/xml2array

Ajay Kumar
fuente
3

He utilizado TypeConverter de Miles Johnson para este propósito. Es instalable usando Composer .

Podrías escribir algo como esto usándolo:

<?php
require 'vendor/autoload.php';
use mjohnson\utility\TypeConverter;

$xml = file_get_contents("file.xml");
$arr = TypeConverter::xmlToArray($xml, TypeConverter::XML_GROUP);
echo json_encode($arr);
Fornido
fuente
3

Optimizando la respuesta de Antonio Max:

$xmlfile = 'yourfile.xml';
$xmlparser = xml_parser_create();

// open a file and read data
$fp = fopen($xmlfile, 'r');
//9999999 is the length which fread stops to read.
$xmldata = fread($fp, 9999999);

// converting to XML
$xml = simplexml_load_string($xmldata, "SimpleXMLElement", LIBXML_NOCDATA);

// converting to JSON
$json = json_encode($xml);
$array = json_decode($json,TRUE);
Marco Leuti
fuente
44
Usé este enfoque, pero JSON está vacío. XML es válido
ryabenko-pro
2

Si desea convertir solo una parte específica del XML a JSON, puede usar XPath para recuperar esto y convertirlo a JSON.

<?php
$file = @file_get_contents($xml_File, FILE_TEXT);
$xml = new SimpleXMLElement($file);
$xml_Excerpt = @$xml->xpath('/states/state[@id="AL"]')[0]; // [0] gets the node
echo json_encode($xml_Excerpt);
?>

Tenga en cuenta que si su Xpath es incorrecto, esto morirá con un error. Entonces, si está depurando esto a través de llamadas AJAX, le recomiendo que también registre los cuerpos de respuesta.

ChrisR
fuente
2
This is better solution

$fileContents= file_get_contents("https://www.feedforall.com/sample.xml");
$fileContents = str_replace(array("\n", "\r", "\t"), '', $fileContents);
$fileContents = trim(str_replace('"', "'", $fileContents));
$simpleXml = simplexml_load_string($fileContents);
$json = json_encode($simpleXml);
$array = json_decode($json,TRUE);
return $array;
Rashiqul Rony
fuente
2

La mejor solución que funciona como un encanto

$fileContents= file_get_contents($url);

$fileContents = str_replace(array("\n", "\r", "\t"), '', $fileContents);

$fileContents = trim(str_replace('"', "'", $fileContents));

$simpleXml = simplexml_load_string($fileContents);

//$json = json_encode($simpleXml); // Remove // if you want to store the result in $json variable

echo '<pre>'.json_encode($simpleXml,JSON_PRETTY_PRINT).'</pre>';

Fuente

Alfa
fuente
1

Esta es una mejora de la solución más votada por Antonio Max, que también funciona con XML que tiene espacios de nombres (reemplazando los dos puntos con un guión bajo). También tiene algunas opciones adicionales (y analiza <person my-attribute='name'>John</person>correctamente).

function parse_xml_into_array($xml_string, $options = array()) {
    /*
    DESCRIPTION:
    - parse an XML string into an array
    INPUT:
    - $xml_string
    - $options : associative array with any of these keys:
        - 'flatten_cdata' : set to true to flatten CDATA elements
        - 'use_objects' : set to true to parse into objects instead of associative arrays
        - 'convert_booleans' : set to true to cast string values 'true' and 'false' into booleans
    OUTPUT:
    - associative array
    */

    // Remove namespaces by replacing ":" with "_"
    if (preg_match_all("|</([\\w\\-]+):([\\w\\-]+)>|", $xml_string, $matches, PREG_SET_ORDER)) {
        foreach ($matches as $match) {
            $xml_string = str_replace('<'. $match[1] .':'. $match[2], '<'. $match[1] .'_'. $match[2], $xml_string);
            $xml_string = str_replace('</'. $match[1] .':'. $match[2], '</'. $match[1] .'_'. $match[2], $xml_string);
        }
    }

    $output = json_decode(json_encode(@simplexml_load_string($xml_string, 'SimpleXMLElement', ($options['flatten_cdata'] ? LIBXML_NOCDATA : 0))), ($options['use_objects'] ? false : true));

    // Cast string values "true" and "false" to booleans
    if ($options['convert_booleans']) {
        $bool = function(&$item, $key) {
            if (in_array($item, array('true', 'TRUE', 'True'), true)) {
                $item = true;
            } elseif (in_array($item, array('false', 'FALSE', 'False'), true)) {
                $item = false;
            }
        };
        array_walk_recursive($output, $bool);
    }

    return $output;
}
TheStoryCoder
fuente
2
Uno no usa Regex para analizar XML, a menos que sea un XML simple con estructura trivial y datos muy predecibles. No puedo enfatizar lo suficiente lo mala que es esta solución. Esto rompe los datos. Sin mencionar que es increíblemente lento (analiza con expresiones regulares y luego vuelve a analizar de nuevo?) Y no maneja las etiquetas de cierre automático.
AlexanderMP
No creo que hayas mirado realmente la función. No utiliza regex para realizar el análisis real, solo como una solución simple para manejar los espacios de nombres, que ha estado funcionando en todos mis casos xml, y que está funcionando es lo más importante, en lugar de ser "políticamente correcto". ¡Sin embargo, puedes mejorarlo si quieres!
TheStoryCoder
2
El hecho de que te haya funcionado no significa que sea correcto. Es un código como este que genera errores que son inmensamente difíciles de diagnosticar y genera vulnerabilidades. Me refiero incluso a mirar superficialmente las especificaciones XML en sitios como este w3schools.com/xml/xml_elements.asp muestran muchas razones por las que esta solución no funcionaría. Como dije, no puede detectar etiquetas de cierre automático como <element/>, no aborda los elementos que comienzan con, o contienen guiones bajos, lo cual está permitido en XML. No puede detectar CDATA. Y como he dicho, es LENTO. Es una complejidad O (n ^ 2) debido al análisis interno.
AlexanderMP
1
La cuestión es que tratar con espacios de nombres ni siquiera se preguntó aquí, y hay formas ADECUADAS de tratar con espacios de nombres. Los espacios de nombres existen como una construcción útil, NO deben analizarse así y convertirse en una abominación que no será procesada por ningún analizador razonable. Y todo lo que necesita hacer para eso no es crear el contendiente para el premio del "algoritmo más lento de 2016", sino hacer un poco de búsqueda, encontrar una miríada de soluciones reales, como esta stackoverflow.com/ preguntas / 16412047 / ... ¿ Y llamar a esto una mejora? Guau.
AlexanderMP
0

¡Todas las soluciones aquí tienen problemas!

... Cuando la representación necesita una interpretación XML perfecta (sin problemas con los atributos) y para reproducir todo el texto-etiqueta-texto-etiqueta-texto -... y el orden de las etiquetas. También recuerde aquí que el objeto JSON "es un conjunto desordenado" (no repite las teclas y las teclas no pueden tener un orden predefinido) ... Incluso el xml2json de ZF está equivocado (!) Porque no preserva exactamente la estructura XML.

Todas las soluciones aquí tienen problemas con este XML simple,

    <states x-x='1'>
        <state y="123">Alabama</state>
        My name is <b>John</b> Doe
        <state>Alaska</state>
    </states>

... La solución @FTav parece mejor que la solución de 3 líneas, pero también tiene un pequeño error cuando se prueba con este XML.

La solución anterior es la mejor (para una representación sin pérdidas)

La solución, hoy conocida como jsonML , es utilizada por el proyecto Zorba y otros, y fue presentada por primera vez en ~ 2006 o ~ 2007, por (por separado) Stephen McKamey y John Snelson .

// the core algorithm is the XSLT of the "jsonML conventions"
// see  https://github.com/mckamey/jsonml
$xslt = 'https://raw.githubusercontent.com/mckamey/jsonml/master/jsonml.xslt';
$dom = new DOMDocument;
$dom->loadXML('
    <states x-x=\'1\'>
        <state y="123">Alabama</state>
        My name is <b>John</b> Doe
        <state>Alaska</state>
    </states>
');
if (!$dom) die("\nERROR!");
$xslDoc = new DOMDocument();
$xslDoc->load($xslt);
$proc = new XSLTProcessor();
$proc->importStylesheet($xslDoc);
echo $proc->transformToXML($dom);

Produce

["states",{"x-x":"1"},
    "\n\t    ",
    ["state",{"y":"123"},"Alabama"],
    "\n\t\tMy name is ",
    ["b","John"],
    " Doe\n\t    ",
    ["state","Alaska"],
    "\n\t"
]

Ver http://jsonML.org o github.com/mckamey/jsonml . Las reglas de producción de este JSON se basan en el elemento JSON-analog,

ingrese la descripción de la imagen aquí

Esta sintaxis es una definición y recurrencia de elementos , con
element-list ::= element ',' element-list | element.

Peter Krauss
fuente
2
Estructura xml muy inusual que dudo que tenga casos de uso de la vida real.
TheStoryCoder
0

Después de investigar un poco todas las respuestas, se me ocurrió una solución que funcionaba bien con mis funciones de JavaScript en todos los navegadores (incluidas las consolas / herramientas de desarrollo):

<?php

 // PHP Version 7.2.1 (Windows 10 x86)

 function json2xml( $domNode ) {
  foreach( $domNode -> childNodes as $node) {
   if ( $node -> hasChildNodes() ) { json2xml( $node ); }
   else {
    if ( $domNode -> hasAttributes() && strlen( $domNode -> nodeValue ) ) {
     $domNode -> setAttribute( "nodeValue", $node -> textContent );
     $node -> nodeValue = "";
    }
   }
  }
 }

 function jsonOut( $file ) {
  $dom = new DOMDocument();
  $dom -> loadXML( file_get_contents( $file ) );
  json2xml( $dom );
  header( 'Content-Type: application/json' );
  return str_replace( "@", "", json_encode( simplexml_load_string( $dom -> saveXML() ), JSON_PRETTY_PRINT ) );
 }

 $output = jsonOut( 'https://boxelizer.com/assets/a1e10642e9294f39/b6f30987f0b66103.xml' );

 echo( $output );

 /*
  Or simply 
  echo( jsonOut( 'https://boxelizer.com/assets/a1e10642e9294f39/b6f30987f0b66103.xml' ) );
 */

?>

Básicamente, crea un nuevo DOMDocument, carga y un archivo XML en él y atraviesa cada uno de los nodos y los niños obteniendo los datos / parámetros y exportándolos a JSON sin los molestos signos "@".

Enlace al archivo XML .

Xedret
fuente
0

Esta solución maneja espacios de nombres, atributos y produce resultados consistentes con elementos repetitivos (siempre en matriz, incluso si solo hay una ocurrencia). Inspirado en el sxiToArray () de ratfactor .

/**
 * <root><a>5</a><b>6</b><b>8</b></root> -> {"root":[{"a":["5"],"b":["6","8"]}]}
 * <root a="5"><b>6</b><b>8</b></root> -> {"root":[{"a":"5","b":["6","8"]}]}
 * <root xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"><a>123</a><wsp:b>456</wsp:b></root> 
 *   -> {"root":[{"xmlns:wsp":"http://schemas.xmlsoap.org/ws/2004/09/policy","a":["123"],"wsp:b":["456"]}]}
 */
function domNodesToArray(array $tags, \DOMXPath $xpath)
{
    $tagNameToArr = [];
    foreach ($tags as $tag) {
        $tagData = [];
        $attrs = $tag->attributes ? iterator_to_array($tag->attributes) : [];
        $subTags = $tag->childNodes ? iterator_to_array($tag->childNodes) : [];
        foreach ($xpath->query('namespace::*', $tag) as $nsNode) {
            // the only way to get xmlns:*, see https://stackoverflow.com/a/2470433/2750743
            if ($tag->hasAttribute($nsNode->nodeName)) {
                $attrs[] = $nsNode;
            }
        }

        foreach ($attrs as $attr) {
            $tagData[$attr->nodeName] = $attr->nodeValue;
        }
        if (count($subTags) === 1 && $subTags[0] instanceof \DOMText) {
            $text = $subTags[0]->nodeValue;
        } elseif (count($subTags) === 0) {
            $text = '';
        } else {
            // ignore whitespace (and any other text if any) between nodes
            $isNotDomText = function($node){return !($node instanceof \DOMText);};
            $realNodes = array_filter($subTags, $isNotDomText);
            $subTagNameToArr = domNodesToArray($realNodes, $xpath);
            $tagData = array_merge($tagData, $subTagNameToArr);
            $text = null;
        }
        if (!is_null($text)) {
            if ($attrs) {
                if ($text) {
                    $tagData['_'] = $text;
                }
            } else {
                $tagData = $text;
            }
        }
        $keyName = $tag->nodeName;
        $tagNameToArr[$keyName][] = $tagData;
    }
    return $tagNameToArr;
}

function xmlToArr(string $xml)
{
    $doc = new \DOMDocument();
    $doc->loadXML($xml);
    $xpath = new \DOMXPath($doc);
    $tags = $doc->childNodes ? iterator_to_array($doc->childNodes) : [];
    return domNodesToArray($tags, $xpath);
}

Ejemplo:

php > print(json_encode(xmlToArr('<root a="5"><b>6</b></root>')));
{"root":[{"a":"5","b":["6"]}]}
Klesun
fuente
esto realmente funciona para casos de espacios de nombres múltiples, mejor que otras soluciones, ¿por qué obtuve un voto
negativo
0

La respuesta de FTav le pareció la más útil, ya que es muy personalizable, pero su función xml2js tiene algunos defectos. Por ejemplo, si los elementos secundarios tienen nombres de etiqueta iguales, todos se almacenarán en un solo objeto, esto significa que el orden de los elementos no se conservará. En algunos casos, realmente queremos preservar el orden, por lo que es mejor almacenar los datos de cada elemento en un objeto separado:

function xml2js($xmlnode) {
    $jsnode = array();
    $nodename = $xmlnode->getName();
    $current_object = array();

    if (count($xmlnode->attributes()) > 0) {
        foreach($xmlnode->attributes() as $key => $value) {
            $current_object[$key] = (string)$value;
        }
    }

    $textcontent = trim((string)$xmlnode);
    if (strlen($textcontent) > 0) {
        $current_object["content"] = $textcontent;
    }

    if (count($xmlnode->children()) > 0) {
        $current_object['children'] = array();
        foreach ($xmlnode->children() as $childxmlnode) {
            $childname = $childxmlnode->getName();
            array_push($current_object['children'], xml2js($childxmlnode, true));
        }
    }

    $jsnode[ $nodename ] = $current_object;
    return $jsnode;
}

Así es como funciona. Estructura xml inicial:

<some-tag some-attribute="value of some attribute">
  <another-tag>With text</another-tag>
  <surprise></surprise>
  <another-tag>The last one</another-tag>
</some-tag>

Resultado JSON:

{
    "some-tag": {
        "some-attribute": "value of some attribute",
        "children": [
            {
                "another-tag": {
                    "content": "With text"
                }
            },
            {
                "surprise": []
            },
            {
                "another-tag": {
                    "content": "The last one"
                }
            }
        ]
    }
}
lucifer63
fuente
-1

Parece que la $state->namevariable contiene una matriz. Puedes usar

var_dump($state)

dentro del foreachpara probar eso.

Si ese es el caso, puede cambiar la línea dentro foreachde

$states[]= array('state' => array_shift($state->name)); 

para corregirlo

Michael Fenwick
fuente
parece que los atributos son matrices pero no $ state-> name
Bryan Hadlock
-1
$templateData =  $_POST['data'];

// initializing or creating array
$template_info =  $templateData;

// creating object of SimpleXMLElement
$xml_template_info = new SimpleXMLElement("<?xml version=\"1.0\"?><template></template>");

// function call to convert array to xml
array_to_xml($template_info,$xml_template_info);

//saving generated xml file
 $xml_template_info->asXML(dirname(__FILE__)."/manifest.xml") ;

// function defination to convert array to xml
function array_to_xml($template_info, &$xml_template_info) {
    foreach($template_info as $key => $value) {
        if(is_array($value)) {
            if(!is_numeric($key)){
                $subnode = $xml_template_info->addChild($key);
                if(is_array($value)){
                    $cont = 0;
                    foreach(array_keys($value) as $k){
                        if(is_numeric($k)) $cont++;
                    }
                }

                if($cont>0){
                    for($i=0; $i < $cont; $i++){
                        $subnode = $xml_body_info->addChild($key);
                        array_to_xml($value[$i], $subnode);
                    }
                }else{
                    $subnode = $xml_body_info->addChild($key);
                    array_to_xml($value, $subnode);
                }
            }
            else{
                array_to_xml($value, $xml_template_info);
            }
        }
        else {
            $xml_template_info->addChild($key,$value);
        }
    }
}
Octavio Perez Gallegos
fuente
Es una solución pequeña y universal basada en una matriz de datos que puede ser un JSON_decode transformado ... afortunado
Octavio Perez Gallegos
2
¿De qué manera responde esto a la pregunta original? Su respuesta parece más complicada que la pregunta original, y tampoco parece mencionar a JSON en ninguna parte.
Dan R
-1

Si es usuario de ubuntu, instale el lector xml (tengo php 5.6. Si tiene otro, busque el paquete e instálelo)

sudo apt-get install php5.6-xml
service apache2 restart

$fileContents = file_get_contents('myDirPath/filename.xml');
$fileContents = str_replace(array("\n", "\r", "\t"), '', $fileContents);
$fileContents = trim(str_replace('"', "'", $fileContents));
$oldXml = $fileContents;
$simpleXml = simplexml_load_string($fileContents);
$json = json_encode($simpleXml);
Atul Baldaniya
fuente