PHP에서 XML을 JSON으로 변환


158

PHP에서 XML을 json으로 변환하려고합니다. 간단한 xml 및 json_encode를 사용하여 간단한 변환을 수행하면 xml의 속성이 표시되지 않습니다.

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

그래서 나는 이것을 수동으로 파싱하려고합니다.

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

상태 출력은 {"state":{"0":"Alabama"}}오히려{"state":"Alabama"}

내가 뭘 잘못하고 있죠?

XML :

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

산출:

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

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

XML 스 니펫과 구문 분석 한 최종 배열 구조를 포함 시키십시오. (A var_dump는 잘 작동합니다.)
nikc.org

추가 된 입력, 출력 및 var_dump
Bryan Hadlock

일부 애플리케이션에는 "Perfec XML-to-JSON 맵"필요 합니다 . , jsonML 입니다. 여기의 솔루션을 참조 하십시오 .
Peter Krauss

답변:


472

3 줄로 된 XML의 JSON 및 배열 :

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

58
이 솔루션은 완벽하지 않습니다. XML 속성을 완전히 버립니다. 따라서 <person my-attribute='name'>John</person>로 해석됩니다 <person>John</person>.
Jake Wilson

13
$ xml = simplexml_load_string ($ xml_string, 'SimpleXMLElement', LIBXML_NOCDATA); cdata 요소를 평평하게합니다.
txyoji

28
@JakeWilson 어쩌면 2 년이 지났고 다양한 버전 수정이 있었지만 PHP 5.6.30 에서이 방법은 모든 데이터를 생성합니다. 속성은 @attributes키 아래 배열에 저장 되므로 완벽하고 완벽하게 작동합니다. 3 줄의 짧은 코드는 내 문제를 아름답게 해결합니다.
AlexanderMP

1
네임 스페이스가 여러 개인 경우에는 작동하지 않습니다. 하나만 선택할 수 있으며 $ json_string에 전달됩니다. '(
jirislav

1
이 솔루션을 사용하면 이름이 같은 노드가 여러 개있을 때 하나의 노드에서 키가 요소를 가리 키지 만 여러 노드에서 키 가 요소 배열 을 가리 킵니다 <list><item><a>123</a><a>456</a></item><item><a>123</a></item></list>.-> {"item":[{"a":["123","456"]},{"a":"123"}]}. ratfactor에 의한 php.net의 솔루션은 항상 배열에 요소를 저장하여 해당 문제를 해결합니다.
Klesun

37

이전 게시물에 답변 해 주셔서 죄송하지만이 기사에서는 비교적 짧고 간결하며 유지 관리가 쉬운 접근 방식에 대해 간략하게 설명합니다. 나는 그것을 직접 테스트하고 잘 작동합니다.

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에 동일한 태그의 여러 인스턴스가있는 경우에는 작동하지 않습니다. json_encode는 마지막 태그 인스턴스 만 직렬화합니다.
ethree

35

나는 그것을 알아. json_encode는 문자열과 다르게 객체를 처리합니다. 객체를 문자열로 캐스팅하면 이제 작동합니다.

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

19

나는 파티에 조금 늦었다 고 생각하지만이 작업을 수행하기 위해 작은 기능을 작성했습니다. 또한 속성, 텍스트 내용 및 동일한 node-name을 가진 여러 노드가 형제 인 경우에도 처리합니다.

면책 조항 : 저는 PHP 네이티브가 아니므로 간단한 실수를 감수하십시오.

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

사용 예 :

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

입력 예 (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>

출력 예 :

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

꽤 인쇄 :

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

유의 사항 : 동일한 태그 이름을 가진 여러 태그가 형제 일 수 있습니다. 다른 솔루션은 마지막 형제를 제외한 모든 솔루션을 삭제합니다. 이를 방지하기 위해 하나의 자식 만있는 경우에도 각각의 모든 단일 노드는 tagname의 각 인스턴스에 대한 객체를 보유하는 배열입니다. (예에서 여러 개의 ""요소 참조)

유효한 XML 문서에 하나만 있어야하는 루트 요소조차도 일관된 데이터 구조를 갖기 위해 인스턴스의 객체와 함께 배열로 저장됩니다.

XML 노드 컨텐츠와 XML 속성을 구별 할 수 있도록 각 오브젝트 속성은 "$"에 저장되고 "_"하위의 컨텐츠에 저장됩니다.

편집 : 예제 입력 데이터의 출력을 표시하는 것을 잊었습니다 .

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

큰 XML 데이터를 구문 분석 할 수 있습니까?
Volatil3

2
이 솔루션 XML 속성을 버리지 않기 때문에 더 좋습니다 . @txyoji가 CDATA 요소를 평평하게 제안한 것처럼 xml.com/lpt/a/1658 에서이 복잡한 구조가 단순화 된 구조보다 나은 이유 ( " 반구 조형 XML"참조)를 참조하십시오 $xml = simplexml_load_file("myfile.xml",'SimpleXMLElement',LIBXML_‌​NOCDATA);.
Peter Krauss

사용자 정의 기능에 대한 많은 감사합니다! 튜닝이 매우 쉽습니다. Btw는 JS 방식으로 XML을 구문 분석하는 함수의 편집 버전을 추가했습니다. 모든 항목에는 고유 한 객체가 있으며 (항목이 동일한 태그 이름을 가진 경우 단일 배열에 저장되지 않음) 순서가 유지됩니다.
lucifer63

1
오류 Fatal error: Uncaught Error: Call to a member function getName() on bool.. 버전 PHP는 실패라고 생각합니다 :-( .. 도와주세요!
KingRider

10

일반적인 함정은 json_encode()텍스트 값 속성을 가진 요소를 존중하지 않는 것입니다 . 데이터 손실을 의미하는 것 중 하나를 선택합니다. 아래 기능은 그 문제를 해결합니다. json_encode/ decode길 을 가기로 결정 하면 다음 기능이 권장됩니다.

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

그렇게하면 JSON <foo bar="3">Lorem</foo>처럼 끝나지 않습니다 {"foo":"Lorem"}.


구문 오류가 정정되면 컴파일되지 않고 설명 된 출력을 생성하지 않습니다.
Richard Kiefer

무엇입니까 $dom? 어디에서 왔습니까?
Jake Wilson

$ dom = 새로운 DOMDocument ();
Scott의

1
코드의 마지막 줄 : $ json = json_decode (json_encode ($ sxml))); $ json = json_decode (json_encode ($ sxml))이어야합니다.
Charlie Smith

6

이것을 사용해보십시오

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

또는

이 라이브러리를 사용할 수 있습니다 : https://github.com/rentpost/xml2array


3

이 목적으로 Miles Johnson의 TypeConverter 를 사용했습니다. Composer를 사용하여 설치할 수 있습니다.

이것을 사용하여 다음과 같이 작성할 수 있습니다.

<?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 답변 최적화 :

$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
이 방법을 사용했지만 JSON이 비어 있습니다. XML이 유효합니다.
ryabenko-pro 2018

2

XML의 특정 부분 만 JSON으로 변환하려는 경우 XPath를 사용하여이를 검색하여 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);
?>

Xpath가 올바르지 않으면 오류와 함께 죽습니다. 따라서 AJAX 호출을 통해 이것을 디버깅하는 경우 응답 본문도 기록하는 것이 좋습니다.


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

매력처럼 작동하는 최고의 솔루션

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

출처


1

이것은 Antonio Max가 가장 많이 지원하는 솔루션을 개선 한 것으로, 네임 스페이스가있는 XML 과도 작동합니다 (콜론을 밑줄로 바꿈). 또한 추가 옵션이 있으며 <person my-attribute='name'>John</person>올바르게 구문 분석 합니다.

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
사소한 구조와 매우 예측 가능한 데이터가있는 간단한 XML이 아닌 한 Regex를 사용하여 XML을 구문 분석하지 않습니다. 이 솔루션이 얼마나 나쁜지 충분히 강조 할 수 없습니다. 데이터가 손상됩니다. 말할 것도없이 속도가 느리고 (정규식으로 구문 분석 한 다음 다시 구문 분석합니까?) 자동 종료 태그를 처리하지 않습니다.
AlexanderMP

나는 당신이 그 기능을 실제로 보았다고 생각하지 않습니다. 정규 구문을 사용하여 실제 구문 분석을 수행하지 않고 모든 XML 사례에서 작동하는 네임 스페이스를 처리하는 간단한 수정으로 만 사용되며 "정치적으로 올바른"것보다는 작동하는 것이 가장 중요합니다. 그래도 원하는 경우 개선 할 수 있습니다.
TheStoryCoder

2
그것이 당신을 위해 일했다는 것이 옳다는 것을 의미하지는 않습니다. 진단하기 매우 어려운 버그를 생성하고 악용을 생성하는 것은 이와 같은 코드입니다. 이 w3schools.com/xml/xml_elements.asp 와 같은 사이트의 XML 사양을 피상적으로 보면 이 솔루션이 작동하지 않는 많은 이유가 표시됩니다. 내가 말했듯이, 같은 자체 닫는 태그를 감지 <element/>하지 못하거나 XML로 허용되는 밑줄로 시작하거나 밑줄을 포함하는 요소를 처리하지 못합니다. CDATA를 감지하지 못했습니다. 그리고 내가 말했듯이, 그것은 느립니다. 내부 파싱으로 인해 O (n ^ 2) 복잡성입니다.
AlexanderMP

1
문제는 네임 스페이스를 다루지 않아도 여기에서 요청되지 않았으며 네임 스페이스를 처리하는 올바른 방법이 있다는 것입니다. 네임 스페이스는 유용한 구문으로 존재하며, 그런 식으로 구문 분석되어서는 안되며 합리적인 파서로 처리되지 않는 가증으로 변합니다. 그리고 당신이해야 할 일은 "2016 년 가장 느린 알고리즘"의 상을 받기 위해 경쟁자를 만드는 것이 아니라 약간의 검색을 수행하는 것입니다.이 같은 stackoverflow.com/ 질문 / 16412047 /… 그리고 이것을 개선이라고 부릅니까? 와.
AlexanderMP

0

여기에있는 모든 솔루션에는 문제가 있습니다!

... 표현에 완전한 XML 해석이 필요한 경우 (속성에 문제 없음) 모든 text-tag-text-tag-text -... 및 태그 순서를 재현해야합니다. JSON 객체 라는 것도 기억하십시오. "순서가없는 세트"(반복 키가 아니며 키가 사전 정의 된 순서를 가질 수 없음)라는 ZF의 xml2json 도 XML 구조를 정확하게 유지하지 않기 때문에 잘못되었습니다!

여기의 모든 솔루션에는이 간단한 XML에 문제가 있습니다.

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

... @FTav 솔루션은 3 줄 솔루션보다 낫지 만이 XML로 테스트 할 때 버그가 거의 없습니다.

오래된 솔루션이 최고입니다 (무손실 표현)

오늘날 jsonML 로 잘 알려진이 솔루션 은 Zorba 프로젝트 및 기타 업체에서 사용되며 ~ 2006 년 또는 ~ 2007 년에 (별도의) Stephen McKameyJohn 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);

생산액

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

http://jsonML.org 또는 github.com/mckamey/jsonml을 참조하십시오 . 이 JSON의 프로덕션 규칙은 JSON- 아날로그 요소를 기반으로합니다 .

여기에 이미지 설명을 입력하십시오

이 구문은을 사용하여 요소 정의 및 반복입니다
element-list ::= element ',' element-list | element.


2
실제 사용 사례가 의심되는 매우 특이한 XML 구조.
TheStoryCoder 2013

0

약간의 모든 답변을 조사한 후 브라우저 (콘솔 / 개발자 도구 포함)에서 JavaScript 기능으로 잘 작동하는 솔루션을 생각해 냈습니다.

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

?>

기본적으로 새 DOMDocument,로드 및 XML 파일을 작성하고 각 노드 및 하위 노드를 통해 데이터 / 매개 변수를 가져와 성가신 "@"부호없이 JSON으로 내 보냅니다.

XML 파일에 연결 하십시오.


0

이 솔루션은 네임 스페이스, 속성을 처리하고 반복되는 요소 (항상 배열이 하나만있는 경우에도 항상 배열)를 사용하여 일관된 결과를 생성합니다. ratfactor의 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);
}

예:

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

이 사실은 ... 아래로 투표를 가지고 왜 다른 솔루션보다 더, 멀티 네임 스페이스의 경우에 작동합니다
아론

0

FTav의 답변은 매우 사용자 정의가 가능하기 때문에 가장 유용하지만 그의 xml2js 기능에는 몇 가지 결함이 있습니다. 예를 들어, 하위 요소의 태그 이름이 동일하면 모두 단일 객체에 저장되므로 요소의 순서가 유지되지 않습니다. 어떤 경우에는 순서를 유지하기 위해 모든 요소의 데이터를 별도의 객체에 저장하는 것이 좋습니다.

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

작동 방식은 다음과 같습니다. 초기 XML 구조 :

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

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

-1

$state->name변수가 배열을 보유하고있는 것 같습니다 . 당신이 사용할 수있는

var_dump($state)

foreach그것을 테스트 하기 위해 내부 .

그런 경우에는, 당신은 내부의 라인 변경 foreach에를

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

수정하십시오.


속성은 배열이지만 $ 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);
        }
    }
}

JSON가 json_decode ... 운 변환 될 수있는 데이터의 배열에 기초하여 작은 범용 솔루션
옥타 페레즈 갈레

2
이것은 원래의 질문에 어떤 식으로 대답합니까? 귀하의 답변은 원래 질문보다 복잡해 보이며 어디서나 JSON을 언급하지 않는 것 같습니다.
Dan R

-1

우분투 사용자 인 경우 XML 리더를 설치하십시오 (PHP 5.6이 있습니다. 다른 패키지가 있으면 설치하여 설치하십시오)

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);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.