chaves e valores são trocados - você pode corrigir isso array_flip()antes do array_walk. array_walk_recursiverequer PHP 5. você poderia usar array_walk, mas não entrará 'stack' => 'overflow'no xml.
Isso não funcionará se $ test_array tiver 'more_another_array' como 'another_array', porque a chave 'another_array' não será convertida. Portanto, você terá várias '<overflow> stack </overflow>'.
understack
11
O array_flipnão funcionará, pois não pode inverter matrizes (como o another_arrayinterior da matriz principal).
Lode
14
Onde está o elemento xml "another_array"? Tudo está achatado :(
FMaz008
2
Funcionou muito bem quando adicionei array_flip antes de array_walk_recursive. obrigado.
8118 Mike Purcell
12
Voto negativo, porque array_flipsó funciona se a matriz não contém valores idênticos.
287 Martijn
385
Aqui está o código php 5.2 que converterá array de qualquer profundidade em documento xml:
A IMO é uma solução muito melhor do que a resposta aceita. No entanto, isso tem a limitação de que, com matrizes numeradas com chave, ele gera XML malformado. <0> <1> <2> não são nomes de nó válidos.
KOGI 5/10
2
Porém, se sua matriz numerada com chave contiver apenas outra matriz que não seja numerada, ela não será.
Bryan Petty
15
@KOGI Modifiquei a resposta Hanmant. Agora, seu suporte matrizes multinível. pastebin.com/pYuXQWee
Mifas
1
Este exemplo escapa explicitamente caracteres especiais nos dados de texto do elemento usando htmlspecialchars, mas SimpleXMLElement :: addChild converte caracteres especiais xml em suas entidades char automaticamente para que htmlspecialchars possa ser deixado de fora. Curiosamente, isso parece não resultar em dados duplamente escapados.
mbaynton
3
@ Alex, sua edição nº 5 faz com que o exemplo falhe. Ele insere <item $ x> antes de cada registro <estudent>, fazendo com que a saída XML não seja o que o autor pretendia. Talvez forneça um exemplo do problema que você está tentando corrigir e podemos encontrar outra solução para os dois casos. Demorei um pouco antes de eu perceber que o código dos autores foi modificado.
Nicholas Blasgen
124
As respostas fornecidas aqui convertem apenas a matriz para XML com nós; você não pode definir atributos. Eu escrevi uma função php que permite converter uma matriz para php e também definir atributos para nós específicos no xml. A desvantagem aqui é que você precisa construir uma matriz de uma maneira específica com poucas convenções (somente se você quiser usar atributos)
O exemplo a seguir também permitirá que você defina atributos em XML.
Estou surpreso que ninguém tenha reagido a isso. Essa classe é realmente útil, pois está fazendo o oposto do que o simpleXMLElement gerará. Portanto, oferece a possibilidade de usar o SimpleXMLElement nos dois sentidos.
FMaz008
4
Eu marcaria isso como resposta em vez de atual. Resposta atual não criando matrizes recursivas
Oleksandr IY
2
Boa aula. Mudei linha 128 if(!is_array($arr)) {para if(!is_array($arr) && $arr !== '') {de modo que não irá acrescentar um novo nó de texto para cadeias vazias e, portanto, mantém o formato tag vazio taquigrafia isto 'tag'=>''é <tag/>, em vez de<tag></tag>
user1433150
Esta é a melhor resposta até agora. Além disso, possui a estrutura correta de vários itens com a mesma chave: 1º é a chave do nome do nó e, em seguida, contém a matriz com chaves numéricas. (o oposto da resposta Hanmant)
Encontrei todas as respostas para usar muito código. Aqui está uma maneira fácil de fazer isso:
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);}}}
Então é uma simples questão de enviar a matriz para a função, que usa recursão, para lidar com uma matriz multidimensional:
Eu amo essa solução mais. Embora, seria bom para adicionar um teste em teclas numéricas, como: if ( is_numeric( $key ) ) $key = "numeric_$key"; .
Wout 1/11
Boa captura. Adicionado. Fiz uma verificação int cast em vez de is_numeric, porque is_numeric pode fornecer alguns resultados, embora tecnicamente esperados, que realmente o afastariam.
Francis Lewis
Eu uso essa função, mas mudei $xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8" ?><rootTag/>');para codificação UTF-8 válida.
Daantje 30/03
Eu gosto desta solução o mais bem, simples faz :-) Uma observação: Você pode querer mudar $object->addChild($key, $value);para $object->addChild($key, htmlspecialchars($value));para evitar que ele falha quando $ value contém caracteres como "&" essa necessidade XML-codificação.
Se uma das chaves da matriz for denominada "corpo", ela não funcionará - mais precisamente, a chave será ignorada e atravessada. Tentando descobrir o porquê.
Bambax
@Bambax A única razão pela qual consigo pensar é se o XML está sendo analisado como HTML em algum momento posterior.
Enfim, peguei o código de onokazu (obrigado!) E acrescentei a capacidade de repetir tags em XML, ele também suporta atributos, espero que alguém ache útil!
Pode ser útil comentar suas alterações para tornar o código mais claro; ainda, boa adição
StormeHawke
Isso funcionou para mim com o WP All Export. Eu tive que mudar um pouco a parte is_numeric: if (is_numeric($k)) { $i = $k + 1; $child = $xml->addChild("_$i"); array_to_xml($v, $child); }
achiever
4
Eu uso algumas funções que escrevi há algum tempo para gerar o xml para ir e voltar do PHP e do jQuery, etc. ) ...
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
A maioria das respostas acima está correta. No entanto, eu vim com esta resposta que resolve o problema de compatibilidade array_walk_recursive e também o problema de chaves numéricas. Também passou em todos os testes que fiz:
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);}}
Também adicionei uma classe de teste para isso, que você pode achar ú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());}}
Isso tem um efeito inesperado de criar XML no estilo RPC com coisas como methodCall, methodName, escalares e vetores, etc. Não é realmente converter uma matriz em XML no sentido direto.
Volomike 4/16
3
Se a matriz for associativa e digitada corretamente, provavelmente seria mais fácil transformá-la em xml primeiro. Algo como:
e, em seguida, para cada parte da sua matriz, use algo semelhante ao meu loop de criação de texto e, em vez disso, use as funções simplexml "addChild" para cada nó da matriz.
Vou tentar isso mais tarde e atualizar este post com as duas versões.
A parte em que mencionei "<array> </array>" me fez perceber que a versão em string precisa de algo semelhante. Basicamente, a matriz precisa ter um nó do lado de fora. Deixe-me dormir a coisa toda, vou ter algo que pega esse erro inicial imediatamente.
Anthony
2
Apenas uma edição em uma função acima, quando uma tecla for numérica, adicione um prefixo "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");}}}}
Você pode usar a seguinte função no código diretamente,
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";}}}
Chame a função com o primeiro argumento como sua matriz e o segundo argumento deve ser 1, isso aumentará para um recuo perfeito e o terceiro deve ser verdadeiro.
por exemplo, se a variável da matriz a ser convertida for $ array1, a chamada seria, a função de chamada deve ser encapsulada com <pre>tag.
artoxml ($ array1,1, true);
Consulte a fonte da página após executar o arquivo, porque os símbolos <e> não serão exibidos em uma página html.
Você pode usar xmlrpc_encode para criar um xml a partir da matriz se um xml detalhado não for um problema.
www.php.net/xmlrpc_encode
tenha cuidado para o xml criado diferir caso você use chaves associativas e / ou 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 função não é suportada e, de fato, não é fornecida em minhas compilações do PHP 5.2.16 ou PHP 5.3.5. (retorna “PHP Erro fatal: Chamada para xmlrpc_encode função indefinida ()”)
danorton
você tem que remover o comentário da seguinte linha no php.ini: extension = php_xmlrpc.dll
w35l3y
@ w35l3y eu verifiquei meu ini. Ele nem contém essa extensão e estou usando a versão 5.3.6.
Minha resposta, juntando as respostas dos outros. Isso deve corrigir a falha em compensar as 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);}}}
A array_to_xml()função presume que a matriz seja composta primeiro por teclas numéricas. Se sua matriz tivesse um elemento inicial, você soltaria as instruções foreach()e $elemda array_to_xml()função e passaria $xml.
Eu teria comentado a segunda resposta mais votada, porque ela não preserva a estrutura e gera xml incorreto se houver matrizes internas indexadas numericamente.
Desenvolvi minha própria versão com base nela, porque precisava de um conversor simples entre json e xml, independentemente da estrutura dos dados. Minha versão preserva as informações de chave numérica e a estrutura da matriz original. Ele cria elementos para os valores indexados numericamente, agrupando valores em elementos nomeados como valor com atributo-chave que contém chave numérica.
Respostas:
uma curta:
resulta em
chaves e valores são trocados - você pode corrigir isso
array_flip()
antes do array_walk.array_walk_recursive
requer PHP 5. você poderia usararray_walk
, mas não entrará'stack' => 'overflow'
no xml.fonte
array_flip
não funcionará, pois não pode inverter matrizes (como oanother_array
interior da matriz principal).array_flip
só funciona se a matriz não contém valores idênticos.Aqui está o código php 5.2 que converterá array de qualquer profundidade em documento xml:
XML gerado seria como:
Fragmento de PHP
Documentação
SimpleXMLElement::asXML
usada neste snippetfonte
As respostas fornecidas aqui convertem apenas a matriz para XML com nós; você não pode definir atributos. Eu escrevi uma função php que permite converter uma matriz para php e também definir atributos para nós específicos no xml. A desvantagem aqui é que você precisa construir uma matriz de uma maneira específica com poucas convenções (somente se você quiser usar atributos)
O exemplo a seguir também permitirá que você defina atributos em XML.
A fonte pode ser encontrada aqui: https://github.com/digitickets/lalit/blob/master/src/Array2XML.php
fonte
if(!is_array($arr)) {
paraif(!is_array($arr) && $arr !== '') {
de modo que não irá acrescentar um novo nó de texto para cadeias vazias e, portanto, mantém o formato tag vazio taquigrafia isto'tag'=>''
é<tag/>
, em vez de<tag></tag>
Encontrei todas as respostas para usar muito código. Aqui está uma maneira fácil de fazer isso:
Então é uma simples questão de enviar a matriz para a função, que usa recursão, para lidar com uma matriz multidimensional:
Agora $ xml contém um belo objeto XML baseado em sua matriz exatamente como você o escreveu.
fonte
if ( is_numeric( $key ) ) $key = "numeric_$key";
.$xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8" ?><rootTag/>');
para codificação UTF-8 válida.$object->addChild($key, $value);
para$object->addChild($key, htmlspecialchars($value));
para evitar que ele falha quando $ value contém caracteres como "&" essa necessidade XML-codificação.fonte
$k = (is_numeric($k)) ? 'item' : $k;
dentro doforeach()
Do PHP 5.4
fonte
Outra melhoria:
Uso:
fonte
Aqui está a minha entrada, simples e limpa ..
fonte
Enfim, peguei o código de onokazu (obrigado!) E acrescentei a capacidade de repetir tags em XML, ele também suporta atributos, espero que alguém ache útil!
fonte
if (is_numeric($k)) { $i = $k + 1; $child = $xml->addChild("_$i"); array_to_xml($v, $child); }
Eu uso algumas funções que escrevi há algum tempo para gerar o xml para ir e voltar do PHP e do jQuery, etc. ) ...
Se for útil para alguém, use-o :)
Amor a todos :)
fonte
Eu queria um código que pegasse todos os elementos dentro de uma matriz e os tratasse como atributos, e todas as matrizes como subelementos.
Então, para algo como
Eu teria algo assim
Para conseguir isso, o código está abaixo, mas tenha muito cuidado, é recursivo e pode realmente causar um stackoverflow :)
Você pode adicionar verificações para o comprimento da matriz, para que algum elemento seja definido dentro da parte dos dados e não como um atributo.
fonte
Com base em tudo o resto, lida com índices numéricos + atributos via prefixação com
@
e pode injetar xml nos nós existentes:Código
Uso
Resultado
Bônus: Formatação XML
fonte
Aqui está uma função que fez o truque para mim:
Basta chamá-lo com algo como
fonte
Você pode usar o XMLParser em que estou trabalhando.
Resultaria em:
fonte
Encontrei esta solução semelhante ao problema original
fonte
A maioria das respostas acima está correta. No entanto, eu vim com esta resposta que resolve o problema de compatibilidade array_walk_recursive e também o problema de chaves numéricas. Também passou em todos os testes que fiz:
Também adicionei uma classe de teste para isso, que você pode achar útil:
fonte
outra solução:
fonte
Se a matriz for associativa e digitada corretamente, provavelmente seria mais fácil transformá-la em xml primeiro. Algo como:
A outra rota seria criar primeiro o seu XML básico, como
e, em seguida, para cada parte da sua matriz, use algo semelhante ao meu loop de criação de texto e, em vez disso, use as funções simplexml "addChild" para cada nó da matriz.
Vou tentar isso mais tarde e atualizar este post com as duas versões.
fonte
Apenas uma edição em uma função acima, quando uma tecla for numérica, adicione um prefixo "key_"
fonte
Você pode usar a seguinte função no código diretamente,
Chame a função com o primeiro argumento como sua matriz e o segundo argumento deve ser 1, isso aumentará para um recuo perfeito e o terceiro deve ser verdadeiro.
por exemplo, se a variável da matriz a ser convertida for $ array1, a chamada seria, a função de chamada deve ser encapsulada com
<pre>
tag.Consulte a fonte da página após executar o arquivo, porque os símbolos <e> não serão exibidos em uma página html.
fonte
fonte
Esta função retorna, por exemplo, uma lista de tags XML <obj>...</obj> <obj> ... </obj> para índices numéricos.
Entrada:
Resultado:
Isso deve satisfazer todas as necessidades comuns. Talvez você possa alterar a terceira linha para:
ou se você estiver trabalhando com plurais terminando com s:
fonte
Com o FluidXML, você pode gerar, a partir de uma matriz PHP , um XML para SimpleXML com ... apenas duas linhas de código.
Uma matriz de exemplo pode ser
https://github.com/servo-php/fluidxml
fonte
Você pode usar xmlrpc_encode para criar um xml a partir da matriz se um xml detalhado não for um problema. www.php.net/xmlrpc_encode
tenha cuidado para o xml criado diferir caso você use chaves associativas e / ou numéricas
fonte
fonte
Minha resposta, juntando as respostas dos outros. Isso deve corrigir a falha em compensar as teclas numéricas:
A
array_to_xml()
função presume que a matriz seja composta primeiro por teclas numéricas. Se sua matriz tivesse um elemento inicial, você soltaria as instruçõesforeach()
e$elem
daarray_to_xml()
função e passaria$xml
.fonte
Eu teria comentado a segunda resposta mais votada, porque ela não preserva a estrutura e gera xml incorreto se houver matrizes internas indexadas numericamente.
Desenvolvi minha própria versão com base nela, porque precisava de um conversor simples entre json e xml, independentemente da estrutura dos dados. Minha versão preserva as informações de chave numérica e a estrutura da matriz original. Ele cria elementos para os valores indexados numericamente, agrupando valores em elementos nomeados como valor com atributo-chave que contém chave numérica.
Por exemplo
array('test' => array(0 => 'some value', 1 => 'other'))
converte para
<test><value key="0">some value</value><value key="1">other</value></test>
Minha versão do array_to_xml -function (espero que ajude alguém :)
fonte
Toda a estrutura XML é definida em $ data Array:
fonte
Se você trabalha no magento e tem esse tipo de array associativo
é melhor converter a matriz associativa para o formato xml.Use este código no arquivo do controlador.
Espero que ajude a todos.
fonte
fonte