PHP converte XML em JSON

157

Estou tentando converter xml para json em php. Se eu fizer uma conversão simples usando xml simples e json_encode, nenhum dos atributos no show xml.

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

Então, eu estou tentando analisá-lo manualmente assim.

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

e a saída para estado é, em {"state":{"0":"Alabama"}}vez de{"state":"Alabama"}

O que estou fazendo de errado?

XML:

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

Resultado:

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

var dump:

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
fonte
Inclua um trecho do XML e a estrutura final da matriz que você possui após analisá-lo. (A var_dumpfunciona bem.)
nikc.org 12/01
entrada, saída e var_dump adicionadas
Bryan Hadlock
Alguns aplicativos precisam "perfec XML-to-JSON map" , que é jsonML , consulte a solução aqui .
22416 Peter Krauss

Respostas:

472

Json & Array do XML em 3 linhas:

$xml = simplexml_load_string($xml_string);
$json = json_encode($xml);
$array = json_decode($json,TRUE);
Antonio Max
fonte
58
Esta solução não é perfeita. Ele descarta completamente os atributos XML. Então <person my-attribute='name'>John</person>é interpretado como <person>John</person>.
Jake Wilson
13
$ xml = simplexml_load_string ($ xml_string, 'SimpleXMLElement', LIBXML_NOCDATA); aplainar elementos cdata.
Txtoji
28
@JakeWilson talvez sejam os 2 anos que se passaram e várias correções de versão, mas no PHP 5.6.30, esse método produz TODOS os dados. Os atributos são armazenados na matriz sob a @attributeschave, para que funcione de maneira absolutamente perfeita e bonita. Três pequenas linhas de código resolvem meu problema lindamente.
AlexanderMP
1
Isso não funciona se você tiver vários espaços para nome, você pode escolher apenas um, que passará para o $ json_string: '(
jirislav
1
Lembre-se de que, com esta solução, quando houver vários nós com o mesmo nome, um nó resultará em uma chave apontando apenas para um elemento, mas vários nós resultarão em uma chave apontando para a matriz de elementos: <list><item><a>123</a><a>456</a></item><item><a>123</a></item></list>-> {"item":[{"a":["123","456"]},{"a":"123"}]}. Uma solução no php.net pelo ratfactor resolve esse problema, sempre armazenando elementos em uma matriz.
Klesun
37

Desculpe por responder uma postagem antiga, mas este artigo descreve uma abordagem relativamente curta, concisa e fácil de manter. Eu mesmo testei e funciona muito bem.

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
fonte
4
Isso não funcionará se você tiver várias instâncias da mesma tag em seu XML, json_encode acabará apenas serializando a última instância da tag.
Eth11
34

Eu descobri. O json_encode manipula objetos de maneira diferente das strings. Lancei o objeto a uma string e ele funciona agora.

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

Acho que estou um pouco atrasado para a festa, mas escrevi uma pequena função para realizar essa tarefa. Ele também cuida de atributos, conteúdo de texto e mesmo que vários nós com o mesmo nome de nó sejam irmãos.

Dislaimer: Eu não sou nativo do PHP, então, por favor, aceite erros 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);
    }
}   

Exemplo de uso:

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

Exemplo de entrada (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>

Exemplo de saída:

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

Bastante impresso:

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

Peculiaridades a serem lembradas: várias tags com o mesmo nome de tag podem ser irmãos. É provável que outras soluções descartem todos, menos o último irmão. Para evitar isso, todo nó único, mesmo que tenha apenas um filho, é uma matriz que armazena um objeto para cada instância do tagname. (Veja vários "" elementos no exemplo)

Mesmo o elemento raiz, do qual apenas um deveria existir em um documento XML válido, é armazenado como matriz com um objeto da instância, apenas para ter uma estrutura de dados consistente.

Para poder distinguir entre o conteúdo do nó XML e os atributos XML, os atributos de cada objeto são armazenados no "$" e o conteúdo no filho "_".

Editar: esqueci de mostrar a saída para os dados de entrada de exemplo

{
    "states" : [{
            "state" : [{
                    "$" : {
                        "id" : "AL"
                    },
                    "name" : [{
                            "_" : "Alabama"
                        }
                    ]
                }, {
                    "$" : {
                        "id" : "AK"
                    },
                    "name" : [{
                            "_" : "Alaska"
                        }
                    ]
                }
            ]
        }
    ]
}
FTav
fonte
Ele pode analisar grandes dados XML?
Volatil3
2
Esta solução é melhor porque não descarta atributos XML. Veja também por que essa estrutura complexa é melhor do que a simplificada, em xml.com/lpt/a/1658 (consulte "XML semiestruturado ") .... Ops, para CDATA, como @txyoji sugeriu aplainar elementos CDATA $xml = simplexml_load_file("myfile.xml",'SimpleXMLElement',LIBXML_‌​NOCDATA);.
Peter Krauss
Muito obrigado por uma função personalizada! Torna o ajuste muito fácil. Por outro lado, adicionou uma versão editada da sua função que analisa XML de uma maneira JS: cada entrada possui seu próprio objeto (as entradas não são armazenadas em uma única matriz se tiverem nomes de tag iguais), portanto, a ordem é preservada.
Lucifer63 #
1
Erro Fatal error: Uncaught Error: Call to a member function getName() on bool.. eu acho que uma versão php é deixar :-( .. por favor me ajude!
KingRider
10

Uma armadilha comum é esquecer que json_encode()não respeita elementos com um valor de texto e atributo (s). Ele escolherá um deles, significando dataloss. A função abaixo resolve esse problema. Se alguém optar pelo caminho json_encode/ decode, é recomendável a seguinte função.

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 ) );

ao fazer isso, <foo bar="3">Lorem</foo>não terminará como {"foo":"Lorem"}no seu JSON.

Coder Of Salvation
fonte
Não compila e não produz a saída descrita se erros de sintaxe forem corrigidos.
Richard Kiefer
O que é $dom? De onde isso veio?
Jake Wilson
$ dom = novo DOMDocument (); é de onde vem
Scott
1
Última linha de código: $ json = json_decode (json_encode ($ sxml))); deve ser: $ json = json_decode (json_encode ($ sxml));
Charlie Smith
6

Tente usar isso

$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;

Ou

Você pode usar esta biblioteca: https://github.com/rentpost/xml2array

Ajay Kumar
fonte
3

Eu usei o TypeConverter de Miles Johnson para esse fim. É instalável usando o Composer .

Você pode escrever algo assim usando:

<?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);
Husky
fonte
3

Otimizando a resposta 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
fonte
4
Eu usei essa abordagem, mas o JSON está vazio. XML é válido.
Ryabenko-pro
2

Se você deseja converter apenas uma parte específica do XML em JSON, pode usar o XPath para recuperá-lo e convertê-lo em 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);
?>

Observe que, se o Xpath estiver incorreto, isso ocorrerá com um erro. Portanto, se você estiver depurando isso por meio de chamadas AJAX, recomendo que você também registre os corpos de resposta.

ChrisR
fonte
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
fonte
2

Melhor solução que funciona como um 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>';

Fonte

Alfa
fonte
1

Essa é uma melhoria da solução mais votada por Antonio Max, que também trabalha com XML que possui namespaces (substituindo os dois pontos por um sublinhado). Ele também possui algumas opções extras (e analisa <person my-attribute='name'>John</person>corretamente).

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
fonte
2
Não se usa o Regex para analisar XML, a menos que seja um XML simples com estrutura trivial e dados muito previsíveis. Não posso enfatizar o suficiente o quão ruim é essa solução. Isso quebra dados. Sem mencionar que é incrivelmente lento (você analisa com regex e analisa novamente?) E não lida com tags de fechamento automático.
AlexanderMP
Eu não acho que você realmente olhou para a função. Ele não usa regex para fazer a análise real, apenas como uma correção simples para lidar com namespaces - que tem funcionado em todos os meus casos de xml - e que está funcionando é o mais importante, em vez de ser "politicamente correto". Você pode melhorá-lo, se quiser!
TheStoryCoder
2
O fato de ter funcionado para você não significa que está certo. É um código como esse que gera bugs imensamente difíceis de diagnosticar e gera explorações. Quero dizer, mesmo olhando superficialmente as especificações XML em sites como este, w3schools.com/xml/xml_elements.asp mostra muitas razões pelas quais essa solução não funcionaria. Como eu disse, ele falha em detectar tags de fechamento automático <element/>, falha em endereçar elementos que começam com ou contêm sublinhados, o que é permitido em XML. Falha na detecção do CDATA. E como eu disse, é LENTO. É uma complexidade O (n ^ 2) por causa da análise interna.
AlexanderMP às
1
O fato é que nem sequer foi solicitado lidar com espaços para nome aqui, e existem maneiras ADEQUADAS de lidar com espaços para nome. Os espaços para nome existem como uma construção útil, NÃO para ser analisada dessa maneira e transformada em uma abominação que não será processada por nenhum analisador razoável. E tudo o que você precisa fazer para isso não é criar o candidato ao prêmio de "algoritmo mais lento de 2016", mas fazer um pouco de pesquisa, encontrar uma infinidade de soluções reais, como esta stackoverflow.com/ questions / 16412047 /… E chamar isso de melhoria? Uau.
AlexanderMP
0

Todas as soluções aqui têm problemas!

... Quando a representação precisar de perfeita interpretação XML (sem problemas com atributos) e reproduzir todo o texto-tag-text-tag-text -... e a ordem das tags. Também é bom lembrar aqui que o objeto JSON "é um conjunto não ordenado" (sem repetir chaves e as chaves não podem ter ordem predefinida) ... Até o xml2json da ZF está errado (!) Porque não preserva exatamente a estrutura XML.

Todas as soluções aqui têm problemas com este XML simples,

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

... A solução @FTav parece melhor que a solução de 3 linhas, mas também possui pouco bug quando testada com este XML.

A solução antiga é a melhor (para uma representação sem perdas)

A solução, hoje conhecida como jsonML , é usada pelo projeto Zorba e outros e foi apresentada pela primeira vez em ~ 2006 ou ~ 2007, por (separadamente) Stephen McKamey e 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);

Produzir

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

Consulte http://jsonML.org ou github.com/mckamey/jsonml . As regras de produção deste JSON são baseadas no elemento JSON-analog,

insira a descrição da imagem aqui

Essa sintaxe é uma definição de elemento e recorrência, com
element-list ::= element ',' element-list | element.

Peter Krauss
fonte
2
Estrutura xml muito incomum que duvido que teria casos de uso da vida real.
TheStoryCoder
0

Depois de pesquisar um pouco de todas as respostas, eu vim com uma solução que funcionava bem com minhas funções JavaScript nos navegadores (incluindo consoles / Ferramentas de desenvolvimento):

<?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' ) );
 */

?>

Ele basicamente cria um novo DOMDocument, carrega e arquivo XML nele e percorre cada um dos nós e filhos, obtendo os dados / parâmetros e exportando-os para JSON sem os sinais "@" irritantes.

Link para o arquivo XML .

Xedret
fonte
0

Esta solução lida com namespaces, atributos e produz resultados consistentes com a repetição de elementos (sempre na matriz, mesmo se houver apenas uma ocorrência). Inspirado pelo sxiToArray () do 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);
}

Exemplo:

php > print(json_encode(xmlToArr('<root a="5"><b>6</b></root>')));
{"root":[{"a":"5","b":["6"]}]}
Klesun
fonte
isso realmente funciona para casos com vários namespaces, melhor do que outras soluções, por que uma votação
negativa
0

A resposta do FTav foi a mais útil, pois é muito personalizável, mas sua função xml2js tem algumas falhas. Por exemplo, se os elementos filhos tiverem nomes de tag iguais, todos eles serão armazenados em um único objeto, isso significa que a ordem dos elementos não será preservada. Em alguns casos, realmente queremos preservar a ordem, para armazenar melhor os dados de cada elemento em um 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;
}

Aqui está como isso funciona. Estrutura 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>

JSON do resultado:

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

Parece que a $state->namevariável está mantendo uma matriz. Você pode usar

var_dump($state)

dentro do foreachpara testar isso.

Se for esse o caso, você pode alterar a linha dentro de foreachpara

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

para corrigi-lo.

Michael Fenwick
fonte
Parece que o atributos são matrizes, mas não $ State-> nome
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
fonte
É uma solução pequena e universal com base em uma matriz de dados pode ser um JSON transformado json_decode ... sorte
Octavio Perez Gallegos
2
De que maneira isso responde à pergunta original? Sua resposta parece mais complicada do que a pergunta original e também nem sequer menciona o JSON em lugar algum.
Dan R
-1

Se você é um usuário do Ubuntu, instale o xml reader (eu tenho o php 5.6. Se você tiver outro, por favor encontre o pacote e instale)

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
fonte