PHP chuyển đổi XML thành JSON


157

Tôi đang cố gắng chuyển đổi xml sang json trong php. Nếu tôi thực hiện chuyển đổi đơn giản bằng cách sử dụng xml và json_encode đơn giản, không có thuộc tính nào trong chương trình xml.

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

Vì vậy, tôi đang cố gắng tự phân tích nó như thế này.

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

và đầu ra cho trạng thái {"state":{"0":"Alabama"}}chứ không phải là{"state":"Alabama"}

Tôi đang làm gì sai?

XML:

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

Đầu ra:

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

bãi chứa 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"
}
}
}

Vui lòng bao gồm một đoạn mã XML và cấu trúc mảng cuối cùng mà bạn có sau khi phân tích cú pháp. (Một var_dumphoạt động tốt.)
nikc.org

đã thêm đầu vào, đầu ra và var_dump
Bryan Hadlock

Một số ứng dụng cần "bản đồ XML-to-JSON perfec " , đó là jsonML , xem giải pháp tại đây .
Peter Krauss

Câu trả lời:


472

Json & Array từ XML trong 3 dòng:

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

58
Giải pháp này không hoàn mỹ. Nó loại bỏ hoàn toàn các thuộc tính XML. Vì vậy, <person my-attribute='name'>John</person>được giải thích là <person>John</person>.
Jake Wilson

13
$ xml = simplexml_load_opes ($ xml_opes, 'SimpleXMLEuity', LIBXML_NOCDATA); để làm phẳng các yếu tố cdata.
txyoji

28
@JakeWilson có thể đã 2 năm trôi qua và nhiều phiên bản sửa lỗi khác nhau, nhưng trên PHP 5.6.30, phương pháp này tạo ra TẤT CẢ dữ liệu. Các thuộc tính được lưu trữ trong mảng dưới @attributeskhóa, vì vậy nó hoạt động hoàn hảo và đẹp mắt. 3 dòng mã ngắn giải quyết vấn đề của tôi rất đẹp.
AlexanderMP

1
Điều này không hoạt động nếu bạn có nhiều không gian tên, bạn chỉ có thể chọn một không gian, sẽ chuyển vào $ json_opes: '(
jirislav

1
Hãy nhớ rằng với giải pháp này, khi có thể có nhiều nút có cùng tên, một nút sẽ dẫn đến một khóa chỉ trỏ đến một phần tử, nhưng nhiều nút sẽ dẫn đến khóa chỉ vào mảng các phần tử: <list><item><a>123</a><a>456</a></item><item><a>123</a></item></list>-> {"item":[{"a":["123","456"]},{"a":"123"}]}. Một giải pháp tại php.net của ratfactor giải quyết vấn đề đó bằng cách luôn lưu trữ các phần tử trong một mảng.
Klesun

37

Xin lỗi vì đã trả lời một bài viết cũ, nhưng bài viết này phác thảo một cách tiếp cận tương đối ngắn, súc tích và dễ duy trì. Tôi đã thử nghiệm nó và làm việc khá tốt.

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
Điều này sẽ không hoạt động nếu bạn có nhiều phiên bản của cùng một thẻ trong XML của mình, json_encode sẽ chỉ kết thúc tuần tự hóa phiên bản cuối cùng của thẻ.
ethree

34

Tôi đã hiểu rồi. json_encode xử lý các đối tượng khác với chuỗi. Tôi chuyển đối tượng thành một chuỗi và nó hoạt động ngay bây giờ.

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

19

Tôi đoán tôi đến bữa tiệc hơi muộn nhưng tôi đã viết một chức năng nhỏ để hoàn thành nhiệm vụ này. Nó cũng quan tâm đến các thuộc tính, nội dung văn bản và ngay cả khi nhiều nút có cùng tên nút là anh em ruột.

Từ chối trách nhiệm: Tôi không phải là người bản địa PHP, vì vậy xin vui lòng chịu những lỗi đơn giản.

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

Ví dụ sử dụng:

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

Ví dụ đầu vào (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>

Ví dụ đầu ra:

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

In đẹp:

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

Những điều cần lưu ý: Một số thẻ có cùng tên thẻ có thể là anh em ruột. Các giải pháp khác rất có thể sẽ bỏ tất cả trừ anh chị em cuối cùng. Để tránh điều này, mỗi nút đơn lẻ, ngay cả khi nó chỉ có một con, là một mảng chứa một đối tượng cho mỗi phiên bản của tên thẻ. (Xem nhiều yếu tố "" trong ví dụ)

Ngay cả phần tử gốc, trong đó chỉ có một phần tử tồn tại trong tài liệu XML hợp lệ được lưu trữ dưới dạng mảng với một đối tượng của thể hiện, chỉ để có cấu trúc dữ liệu nhất quán.

Để có thể phân biệt giữa nội dung nút XML và các thuộc tính XML, mỗi thuộc tính đối tượng được lưu trữ trong "$" và nội dung trong phần tử con "_".

Chỉnh sửa: Tôi quên hiển thị đầu ra cho dữ liệu đầu vào mẫu của bạn

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

Nó có thể phân tích dữ liệu XML lớn không?
Volatil3

2
Giải pháp này tốt hơn vì không loại bỏ các thuộc tính XML. Xem thêm tại sao cấu trúc phức tạp này tốt hơn cấu trúc đơn giản hóa, tại xml.com/lpt/a/1658 (xem "XML bán cấu trúc") .... Ops, đối với CDATA, như @txyoji đề xuất để làm phẳng các phần tử CDATA $xml = simplexml_load_file("myfile.xml",'SimpleXMLElement',LIBXML_‌​NOCDATA);.
Peter Krauss

Rất cám ơn cho một chức năng tùy chỉnh! Nó làm cho điều chỉnh khá dễ dàng. Btw, đã thêm một phiên bản chỉnh sửa của hàm để phân tích cú pháp XML theo cách JS: mọi mục nhập đều có đối tượng riêng (các mục nhập không được lưu trữ trong một mảng nếu chúng có tên thẻ bằng nhau), do đó thứ tự được giữ nguyên.
lucifer63

1
Lỗi Fatal error: Uncaught Error: Call to a member function getName() on bool.. tôi nghĩ rằng một phiên bản php bị lỗi :-( .. vui lòng giúp đỡ!
KingRider

10

Một cạm bẫy phổ biến là quên rằng json_encode()không tôn trọng các yếu tố với giá trị văn bản (các) thuộc tính. Nó sẽ chọn một trong số đó, có nghĩa là dataloss. Hàm dưới đây giải quyết vấn đề đó. Nếu một người quyết định đi theo json_encode/ decodecách, chức năng sau được khuyên dùng.

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

bằng cách làm như vậy, <foo bar="3">Lorem</foo>sẽ không kết thúc như {"foo":"Lorem"}trong JSON của bạn.


Không biên dịch và không tạo ra đầu ra được mô tả nếu lỗi cú pháp được sửa chữa.
Richard Kiefer

$domgì Thứ đó đã đến từ đâu?
Jake Wilson

$ dom = DOMDocument mới (); là nơi nó đến từ
Scott

1
Dòng mã cuối cùng: $ json = json_decode (json_encode ($ sxml))); nên là: $ json = json_decode (json_encode ($ sxml));
Charlie Smith

6

Cố gắng sử dụng cái này

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

Hoặc là

Bạn có thể sử dụng thư viện này: https://github.com/rentpost/xml2array


3

Tôi đã sử dụng TypeConverter của Miles Johnson cho mục đích này. Nó có thể cài đặt bằng Composer .

Bạn có thể viết một cái gì đó như thế này bằng cách sử dụng nó:

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

Tối ưu hóa câu trả lời của 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
Tôi đã sử dụng phương pháp này, nhưng JSON trống. XML là hợp lệ.
ryabenko-pro

2

Nếu bạn muốn chỉ chuyển đổi một phần cụ thể của XML thành JSON, bạn có thể sử dụng XPath để truy xuất phần này và chuyển đổi phần đó thành 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);
?>

Xin lưu ý rằng nếu Xpath của bạn không chính xác, điều này sẽ xảy ra lỗi. Vì vậy, nếu bạn gỡ lỗi điều này thông qua các cuộc gọi AJAX, tôi khuyên bạn cũng nên đăng nhập các nội dung phản hồi.


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

Giải pháp tốt nhất có tác dụng như bùa 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>';

Nguồn


1

Đây là một cải tiến của giải pháp nâng cao nhất của Antonio Max, cũng hoạt động với XML có không gian tên (bằng cách thay thế dấu hai chấm bằng dấu gạch dưới). Nó cũng có một số tùy chọn bổ sung (và phân tích <person my-attribute='name'>John</person>chính xác).

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
Người ta không sử dụng Regex để phân tích cú pháp XML, trừ khi đó là một XML đơn giản với cấu trúc tầm thường và dữ liệu rất dễ đoán. Tôi không thể nhấn mạnh đủ mức độ tồi tệ của giải pháp này. SỐ LIỆU BREAKS này. Chưa kể rằng nó cực kỳ chậm (bạn phân tích bằng regex, và sau đó bạn lại phân tích lại?) Và không xử lý các thẻ tự đóng.
AlexanderMP

Tôi không nghĩ rằng bạn thực sự nhìn vào chức năng. Nó không sử dụng regex để thực hiện phân tích cú pháp thực tế, chỉ là một sửa chữa đơn giản để xử lý các không gian tên - đã hoạt động cho tất cả các trường hợp xml của tôi - và nó đang hoạt động là quan trọng nhất, thay vì "chính xác". Bạn được chào đón để cải thiện nó nếu bạn muốn, mặc dù!
TheStoryCoder

2
Thực tế là nó đã làm việc cho bạn không có nghĩa là nó đúng. Mã như thế này tạo ra các lỗi cực kỳ khó chẩn đoán và tạo ra các khai thác. Tôi có nghĩa là thậm chí nhìn bề ngoài vào các thông số kỹ thuật XML trên các trang web như w3schools.com/xml/xml_elements.asp này cho thấy rất nhiều lý do tại sao giải pháp này không hoạt động. Giống như tôi đã nói, nó không phát hiện được các thẻ tự đóng như <element/>, không giải quyết được các phần tử bắt đầu bằng hoặc chứa dấu gạch dưới, được phép trong XML. Không thể phát hiện CDATA. Và như tôi đã nói, đó là CHẬM. Đó là một phức tạp O (n ^ 2) vì phân tích cú pháp bên trong.
AlexanderMP

1
Vấn đề là việc xử lý các không gian tên thậm chí còn không được hỏi ở đây và có nhiều cách PROPER để xử lý các không gian tên. Không gian tên tồn tại như một công trình hữu ích, KHÔNG được phân tích cú pháp như thế và biến thành một sự gớm ghiếc sẽ không được xử lý bởi bất kỳ trình phân tích cú pháp hợp lý nào. Và tất cả những gì bạn cần làm là không tạo ra ứng cử viên cho giải thưởng "thuật toán chậm nhất năm 2016", mà là tìm kiếm một chút, để đưa ra vô số giải pháp thực tế, như một stackoverflow.com/ câu hỏi / 16412047 / Có thể gọi đây là một cải tiến? Ồ
AlexanderMP

0

Tất cả các giải pháp ở đây có vấn đề!

... Khi biểu diễn cần diễn giải XML hoàn hảo (không có vấn đề với các thuộc tính) và để tái tạo tất cả các thẻ văn bản-thẻ-văn bản-thẻ-văn bản -... và thứ tự các thẻ. Cũng nên nhớ ở đây rằng đối tượng JSON "là một tập hợp không có thứ tự" (không phải các khóa lặp lại và các khóa không thể có thứ tự được xác định trước) ... Ngay cả xml2json của ZF cũng sai (!) Vì không bảo toàn chính xác cấu trúc XML.

Tất cả các giải pháp ở đây đều có vấn đề với XML đơn giản này,

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

... Giải pháp @FTav có vẻ tốt hơn giải pháp 3 dòng, nhưng cũng có một chút lỗi khi được thử nghiệm với XML này.

Giải pháp cũ là tốt nhất (cho đại diện không mất)

Giải pháp, ngày nay nổi tiếng là jsonML , được sử dụng bởi dự án Zorba và các dự án khác, và được trình bày lần đầu tiên vào năm 2006 hoặc ~ 2007, bởi (riêng) 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);

Sản xuất

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

Xem http://jsonML.org hoặc github.com/mckamey/jsonml . Các quy tắc sản xuất của JSON này dựa trên yếu tố JSON-analog,

nhập mô tả hình ảnh ở đây

Cú pháp này là một định nghĩa phần tử và tái phát, với
element-list ::= element ',' element-list | element.


2
Cấu trúc xml rất bất thường mà tôi nghi ngờ sẽ có trường hợp sử dụng thực tế.
TheStoryCoder

0

Sau khi nghiên cứu một chút tất cả các câu trả lời, tôi đã tìm ra một giải pháp hoạt động tốt với các chức năng JavaScript của mình trên các trình duyệt (Bao gồm bảng điều khiển / Công cụ phát triển):

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

?>

Về cơ bản, nó tạo ra một DOMDocument mới, tải và tệp XML vào đó và duyệt qua từng nút và con nhận dữ liệu / tham số và xuất nó thành JSON mà không có dấu "@" gây phiền nhiễu.

Liên kết đến tệp XML .


0

Giải pháp này xử lý các không gian tên, thuộc tính và tạo ra kết quả nhất quán với các phần tử lặp lại (luôn trong mảng, ngay cả khi chỉ có một lần xuất hiện). Lấy cảm hứng từ sxiToArray () của 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);
}

Thí dụ:

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

điều này thực sự hoạt động cho các trường hợp nhiều không gian tên, tốt hơn so với các giải pháp khác, tại sao lại bỏ phiếu ...
aaron

0

Tìm thấy câu trả lời của FTav hữu ích nhất vì nó rất tùy biến, nhưng chức năng xml2js của anh ta có một số sai sót. Chẳng hạn, nếu các phần tử con có tên thẻ bằng nhau thì tất cả chúng sẽ được lưu trữ trong một đối tượng, điều này có nghĩa là thứ tự các phần tử sẽ không được giữ nguyên. Trong một số trường hợp, chúng tôi thực sự muốn giữ gìn trật tự, vì vậy chúng tôi lưu trữ tốt hơn mọi dữ liệu của một thành phần trong một đối tượng riêng biệt:

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

Đây là cách nó làm việc. Cấu trúc xml ban đầu:

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

Kết quả JSON:

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

-1

Có vẻ như $state->namebiến đang giữ một mảng. Bạn có thể dùng

var_dump($state)

Bên trong foreachđể kiểm tra mà.

Nếu đó là trường hợp, bạn có thể thay đổi dòng bên trong foreachđể

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

để sửa nó


có vẻ như các thuộc tính là mảng nhưng không phải là $ 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);
        }
    }
}

Đó là một giải pháp nhỏ và phổ biến dựa trên một mảng dữ liệu có thể là json_decode được chuyển đổi JSON ... may mắn
Octavio Perez Gallegos

2
Bằng cách nào điều này trả lời câu hỏi ban đầu? Câu trả lời của bạn có vẻ phức tạp hơn câu hỏi ban đầu và dường như thậm chí không đề cập đến JSON ở bất cứ đâu.
Dan R

-1

Nếu bạn là người dùng Ubuntu cài đặt trình đọc xml (tôi có php 5.6. Nếu bạn có khác xin vui lòng tìm gói và cài đặt)

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);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.