PHP XML'i JSON'a dönüştürür


158

Ben php json xml dönüştürmek çalışıyorum. Basit xml ve json_encode kullanarak basit bir dönüştürme yaparsanız xml gösterisi öznitelikleri hiçbiri.

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

Bu yüzden elle böyle ayrıştırmaya çalışıyorum.

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

ve durum için çıkış {"state":{"0":"Alabama"}}yerine{"state":"Alabama"}

Neyi yanlış yapıyorum?

XML:

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

Çıktı:

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

var dökümü:

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"
}
}
}

Lütfen ayrıştırdıktan sonra XML parçacığını ve sahip olduğunuz son dizi yapısını ekleyin. (A var_dump
am

giriş, çıkış ve var_dump eklendi
Bryan Hadlock

Bazı uygulamalar için "perfec XML-JSON haritası" gerekir , yani jsonML , buradaki çözüme bakın .
Peter Krauss

Yanıtlar:


473

XML'den 3 satırlı Json & Array:

$xml = simplexml_load_string($xml_string);
$json = json_encode($xml);
$array = json_decode($json,TRUE);

59
Bu çözüm kusursuz değildir. XML niteliklerini tamamen atar. Bu <person my-attribute='name'>John</person>şekilde yorumlanır <person>John</person>.
Jake Wilson

13
$ xml = simplexml_load_string ($ xml_string, 'SimpleXMLElement', LIBXML_NOCDATA); cdata elemanlarını düzleştirmek için.
txyoji

28
@JakeWilson belki 2 yıl geçti ve çeşitli sürüm düzeltmeleri, ancak PHP 5.6.30'da bu yöntem TÜM verileri üretir. Öznitelikler @attributesanahtarın altındaki dizide saklanır , bu yüzden kesinlikle kusursuz ve güzel çalışır. 3 kısa kod satırı sorunumu güzelce çözüyor.
AlexanderMP

1
Birden fazla ad alanınız varsa bu çalışmaz, yalnızca bir tane seçebilirsiniz, bu da $ json_string'e geçecektir: '(
jirislav

1
Bu çözümle, aynı ada sahip birden fazla düğüm olabileceği zaman, bir düğümün sadece bir öğeye işaret eden bir anahtarla sonuçlanacağını, ancak birden fazla düğümün öğe dizisine işaret eden anahtarla sonuçlanacağını unutmayın : <list><item><a>123</a><a>456</a></item><item><a>123</a></item></list>-> {"item":[{"a":["123","456"]},{"a":"123"}]}. Php.net de çözeltisi ratfactor göre çözer bir dizi her zaman depolama elemanları ile sorun olduğu.
Klesun

37

Eski bir gönderiyi cevapladığım için üzgünüm, ancak bu makale nispeten kısa, özlü ve bakımı kolay bir yaklaşımı özetliyor. Kendim test ettim ve oldukça iyi çalışıyor.

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;
    }
}
?>

4
XML'nizde aynı etiketin birden fazla örneğine sahipseniz bu çalışmaz, json_encode yalnızca etiketin son örneğini serileştirir.
Ethree

35

Bunu anladım. json_encode nesneleri dizelerden farklı işler. Nesneyi bir dizeye atıyorum ve şimdi çalışıyor.

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

20

Sanırım partiye biraz geç kaldım ama bu görevi yerine getirmek için küçük bir işlev yazdım. Ayrıca öznitelikler, metin içeriği ve aynı düğüm adına sahip birden fazla düğüm kardeş olsa bile ilgilenir.

Yasal Uyarı: Ben bir PHP yerli değilim, bu yüzden lütfen basit hatalar ile ayı.

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

Kullanım örneği:

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

Örnek Giriş (dosyam.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>

Örnek çıktı:

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

Oldukça basılmış:

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

Akılda tutulması gereken tuhaflıklar : Aynı tagname'e sahip birkaç etiket kardeş olabilir. Diğer çözümler büyük olasılıkla son kardeş dışında hepsini bırakacaktır. Bundan kaçınmak için, her bir düğüm, yalnızca bir alt öğesi olsa bile, tagname'in her örneği için bir nesne tutan bir dizidir. (Örnekte birden çok "" öğesine bakın)

Geçerli bir XML belgesinde yalnızca birinin bulunması gereken kök öğe bile, yalnızca tutarlı bir veri yapısına sahip olmak için örneğin bir nesnesiyle dizi olarak saklanır.

XML düğümü içeriği ile XML özniteliklerini ayırt edebilmek için, her nesne özniteliği "$" ve "_" alt öğesindeki içerik olarak depolanır.

Düzenleme: Örnek giriş verileriniz için çıktıyı göstermeyi unuttum

{
    "states" : [{
            "state" : [{
                    "$" : {
                        "id" : "AL"
                    },
                    "name" : [{
                            "_" : "Alabama"
                        }
                    ]
                }, {
                    "$" : {
                        "id" : "AK"
                    },
                    "name" : [{
                            "_" : "Alaska"
                        }
                    ]
                }
            ]
        }
    ]
}

Büyük XML verilerini ayrıştırabilir mi?
Volatil3

2
XML özniteliklerini atmadığından bu çözüm daha iyidir . Ayrıca xml.com/lpt/a/1658 adresinde bu karmaşık yapının neden basitleştirilmiş olanlardan daha iyi olduğuna bakın (bkz. "Yarı Yapısal XML") .... @txyoji'nin CDATA öğelerini düzleştirmeyi önerdiği gibi, CDATA için ops $xml = simplexml_load_file("myfile.xml",'SimpleXMLElement',LIBXML_‌​NOCDATA);.
Peter Krauss

Özel bir işlev için çok teşekkürler! Ayarlamayı oldukça kolaylaştırır. Btw, XML'inizi JS biçiminde ayrıştıran işlevinizin düzenlenmiş bir sürümünü ekledi: her girdinin kendi nesnesi vardır (eşit tagnamesleri varsa girdiler tek bir dizide saklanmaz), böylece sipariş korunur.
lucifer63

1
Hata Fatal error: Uncaught Error: Call to a member function getName() on bool.. Ben bir php sürümü başarısız olduğunu düşünüyorum :-( .. lütfen yardım!
KingRider

10

Yaygın bir tuzak, json_encode()bir metin değeri ve özniteliği olan öğelere saygı göstermediğini unutmaktır . Veri kaybı anlamına gelen bunlardan birini seçecektir. Aşağıdaki işlev bu sorunu çözer. json_encode/ Yoluna gitmeye karar verilirse decode, aşağıdaki fonksiyon önerilir.

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

bunu yaparsanız, JSON'unuzdaki <foo bar="3">Lorem</foo>gibi sonuçlanmaz {"foo":"Lorem"}.


Sözdizimi hataları düzeltilmişse derlenmez ve açıklanan çıktıyı üretmez.
Richard Kiefer

Nedir $dom? Bu nereden geldi?
Jake Wilson

$ dom = yeni DOMDocument (); geldiği yer
Scott

1
Son kod satırı: $ json = json_decode (json_encode ($ sxml))); şöyle olmalıdır: $ json = json_decode (json_encode ($ sxml));
Charlie Smith

6

Bunu kullanmaya çalışın

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

Veya

Bu kütüphaneyi kullanabilirsiniz: https://github.com/rentpost/xml2array


3

Miles Johnson'ın TypeConverter'ı bu amaçla kullandım. Composer kullanılarak yüklenebilir .

Bunu kullanarak böyle bir şey yazabilirsiniz:

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

3

Antonio Max yanıtını optimize etme:

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

4
Bu yaklaşımı kullandım ama JSON boş. XML geçerlidir.
ryabenko-pro

2

XML'nin yalnızca belirli bir bölümünü JSON'a dönüştürmek istiyorsanız, bunu almak ve bunu JSON'a dönüştürmek için XPath'i kullanabilirsiniz.

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

Xpath yanlışsa, bunun bir hata ile öleceğini lütfen unutmayın. Eğer AJAX çağrıları ile bu hata ayıklama Yani, ben de yanıt organları günlüğü öneririz.


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;

2

Cazibe gibi çalışan en iyi çözüm

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

Kaynak


1

Bu, isim alanlarına sahip XML ile de çalışan (kolonu bir alt çizgi ile değiştirerek) Antonio Max tarafından en çok beğenilen çözümün bir gelişmesidir. Ayrıca bazı ekstra seçenekler vardır (ve <person my-attribute='name'>John</person>doğru ayrıştırır ).

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

2
Önemsiz yapıya ve çok öngörülebilir verilere sahip basit bir XML olmadığı sürece XML'i ayrıştırmak için Regex kullanılmaz. Bu çözümün ne kadar kötü olduğunu yeterince vurgulayamıyorum. Bu VERİLERİ ARIYOR. İnanılmaz derecede yavaş olduğunu (regex ile ayrıştırırsınız ve sonra tekrar ayrıştırır mısınız?) Ve kendiliğinden kapanan etiketleri işlemez.
AlexanderMP

Bu işleve gerçekten baktığınızı sanmıyorum. Regex'i gerçek ayrıştırmayı yapmak için kullanmaz, yalnızca tüm xml vakalarım için çalışan ad alanlarıyla başa çıkmak için basit bir düzeltme olarak kullanır ve çalışmasının "politik olarak doğru" olmak yerine en önemlisidir. Yine de, bunu geliştirmek için bekliyoruz!
TheStoryCoder

2
Sizin için işe yaradığı gerçeği, doğru olduğu anlamına gelmez. Bu, teşhis edilmesi son derece zor olan hatalar üreten ve istismarlar üreten böyle bir koddur. Yani w3schools.com/xml/xml_elements.asp gibi sitelerde XML spesifikasyonlarına yüzeysel olarak bakmak bile, bu çözümün neden işe yaramadığını gösteren birçok nedeni gösteriyor. Dediğim gibi <element/>, kendi kendine kapanan etiketleri algılayamıyor , XML ile izin verilen alt çizgi ile başlayan veya alt çizgi içeren öğeleri ele almıyor. CDATA algılanamıyor. Dediğim gibi, YAVAŞ. İç ayrıştırma nedeniyle bir O (n ^ 2) karmaşıklığıdır.
AlexanderMP

1
Mesele şu ki, ad alanlarıyla uğraşmak burada bile sorulmadı ve ad alanlarıyla başa çıkmak için PROPER yolları var. Ad alanları yararlı bir yapı olarak mevcuttur, böyle ayrıştırılmamalı ve makul bir ayrıştırıcı tarafından işlenmeyecek bir iğrençliğe dönüşmemelidir. Ve bunun için tek yapmanız gereken "2016'nın en yavaş algoritması" ödülü için yarışmacı yaratmak değil, biraz arama yapmak, bunun gibi sayısız gerçek çözüm bulmaktır. Stackoverflow.com/ sorular / 16412047 /… Ve buna bir gelişme mi demek istiyorsun ? Vay.
AlexanderMP

0

Buradaki tüm çözümlerin sorunları var!

... Temsili mükemmel XML yorumlaması gerektiğinde (özniteliklerle ilgili sorun olmadan) ve tüm text-tag-text-tag-text -... ve etiketlerin sırasını çoğaltmak için. Ayrıca burada JSON nesnesinin "sırasız bir küme" olduğunu unutmayın (anahtarları tekrarlamayın ve anahtarlar önceden tanımlanmış bir sıraya sahip olamaz) ... ZF'nin xml2json'u bile yanlış (!) Çünkü tam olarak XML yapısını korumak değil.

Buradaki tüm çözümlerin bu basit XML ile sorunları var,

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

... @FTav çözümü 3 satırlı çözümden daha iyi görünüyor, ancak bu XML ile test edildiğinde de çok az hata var.

Eski çözüm en iyisidir (kayıpsız sunum için)

Bugün jsonML olarak bilinen çözüm, Zorba projesi ve diğerleri tarafından kullanılmaktadır ve ilk olarak ~ 2006 veya ~ 2007'de (ayrı ayrı) Stephen McKamey ve John Snelson tarafından sunulmuştur .

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

Üretmek

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

Bkz http://jsonML.org veya github.com/mckamey/jsonml . Bu JSON'un üretim kuralları aşağıdakilere dayanmaktadır: elemanı JSON analog,

resim açıklamasını buraya girin

Bu sözdizimi bir öğe tanımı ve yineleme ile birlikte
element-list ::= element ',' element-list | element.


2
Şüphe duyduğum çok sıradışı xml yapısı gerçek yaşam kullanım örnekleri olurdu.
TheStoryCoder

0

Tüm cevapları biraz araştırdıktan sonra, tarayıcılardaki JavaScript işlevlerimle iyi çalışan bir çözüm buldum (Konsollar / Geliştirme Araçları dahil):

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

?>

Temel olarak içine yeni bir DOMDocument, yükler ve XML dosyası oluşturur ve can sıkıcı "@" işaretleri olmadan veri / parametreleri almak ve JSON içine ihracat düğümlerin her biri ve üzerinden geçer.

Link to XML dosyası.


0

Bu çözüm, ad alanlarını, nitelikleri işler ve yinelenen öğelerle tutarlı bir sonuç üretir (yalnızca tek bir olay olsa bile her zaman dizide bulunur). Esinlenerek ratfactor en sxiToArray () .

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

Misal:

php > print(json_encode(xmlToArr('<root a="5"><b>6</b></root>')));
{"root":[{"a":"5","b":["6"]}]}

Bu aslında çok çözümlü vakalar için çalışıyor, diğer çözümlerden daha iyi, neden aşağı oy var ...
aaron

0

FTav'ın cevabını çok özelleştirilebilir olduğu için en yararlı buldum , ancak xml2js işlevinin bazı kusurları var. Örneğin, alt öğelerin eşit tagnamesleri varsa, bunların tümü tek bir nesnede saklanır, bu da öğelerin sırasının korunmayacağı anlamına gelir. Bazı durumlarda düzeni gerçekten korumak istiyoruz, bu nedenle her öğenin verilerini ayrı bir nesnede daha iyi saklıyoruz:

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

İşte böyle çalışır. İlk xml yapısı:

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

Sonuç JSON:

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

-1

$state->nameDeğişken bir dizi tutuyor gibi görünüyor . Kullanabilirsiniz

var_dump($state)

içinde foreachtest etmek.

Eğer durum buysa, içinde çizgiyi değiştirebilir foreachTo

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

düzeltmek için.


öznitelikler diziler gibi görünüyor ama $ 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);
        }
    }
}

Bir dizi veriye dayalı küçük ve evrensel bir çözüm JSON dönüştürülmüş json_decode olabilir ... şanslı
Octavio Perez Gallegos

2
Bu asıl soruyu ne şekilde cevaplıyor? Cevabınız orijinal sorudan daha karmaşık görünüyor ve ayrıca hiçbir yerde JSON'dan bile bahsetmiyor gibi görünüyor.
Dan R

-1

Ubuntu kullanıcısı xml okuyucuysanız (php 5.6 var. Başka bir paketiniz varsa lütfen paketi bulun ve kurun)

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);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.