PHP 将 XML 转换为 JSON
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8830599/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PHP convert XML to JSON
提问by Bryan Hadlock
I am trying to convert xml to json in php. If I do a simple convert using simple xml and json_encode none of the attributes in the xml show.
我正在尝试将 xml 转换为 php 中的 json。如果我使用简单的 xml 和 json_encode 进行简单的转换,则 xml 中的任何属性都不会显示。
$xml = simplexml_load_file("states.xml");
echo json_encode($xml);
So I am trying to manually parse it like this.
所以我试图像这样手动解析它。
foreach($xml->children() as $state)
{
$states[]= array('state' => $state->name);
}
echo json_encode($states);
and the output for state is {"state":{"0":"Alabama"}}
rather than {"state":"Alabama"}
状态的输出是{"state":{"0":"Alabama"}}
而不是{"state":"Alabama"}
What am I doing wrong?
我究竟做错了什么?
XML:
XML:
<?xml version="1.0" ?>
<states>
<state id="AL">
<name>Alabama</name>
</state>
<state id="AK">
<name>Alaska</name>
</state>
</states>
Output:
输出:
[{"state":{"0":"Alabama"}},{"state":{"0":"Alaska"}
var dump:
无功转储:
object(SimpleXMLElement)#1 (1) {
["state"]=>
array(2) {
[0]=>
object(SimpleXMLElement)#3 (2) {
["@attributes"]=>
array(1) {
["id"]=>
string(2) "AL"
}
["name"]=>
string(7) "Alabama"
}
[1]=>
object(SimpleXMLElement)#2 (2) {
["@attributes"]=>
array(1) {
["id"]=>
string(2) "AK"
}
["name"]=>
string(6) "Alaska"
}
}
}
采纳答案by Bryan Hadlock
I figured it out. json_encode handles objects differently than strings. I cast the object to a string and it works now.
我想到了。json_encode 处理对象的方式与字符串不同。我将对象转换为字符串,现在可以使用了。
foreach($xml->children() as $state)
{
$states[]= array('state' => (string)$state->name);
}
echo json_encode($states);
回答by Antonio Max
Json & Array from XML in 3 lines:
来自 XML 的 Json & Array 分 3 行:
$xml = simplexml_load_string($xml_string);
$json = json_encode($xml);
$array = json_decode($json,TRUE);
回答by Coreus
Sorry for answering an old post, but this article outlines an approach that is relatively short, concise and easy to maintain. I tested it myself and works pretty well.
抱歉回答了一个旧帖子,但本文概述了一种相对简短、简洁且易于维护的方法。我自己测试过,效果很好。
http://lostechies.com/seanbiefeld/2011/10/21/simple-xml-to-json-with-php/
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;
}
}
?>
回答by FTav
I guess I'm a bit late to the party but I have written a small function to accomplish this task. It also takes care of attributes, text content and even if multiple nodes with the same node-name are siblings.
我想我参加聚会有点晚了,但我已经编写了一个小函数来完成这项任务。它还处理属性、文本内容,即使具有相同节点名称的多个节点是兄弟节点。
Dislaimer:I'm not a PHP native, so please bear with simple mistakes.
免责声明:我不是 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);
}
}
Usage example:
用法示例:
$xml = simplexml_load_file("myfile.xml");
echo xml2js($xml);
Example Input (myfile.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>
Example output:
示例输出:
{"family":[{"$":{"name":"Johnson"},"child":[{"$":{"name":"John","age":"5"},"toy":[{"$":{"status":"old"},"_":"Trooper"},{"$":{"status":"old"},"_":"Ultrablock"},{"$":{"status":"new"},"_":"Bike"}]}]}]}
Pretty printed:
印刷精美:
{
"family" : [{
"$" : {
"name" : "Johnson"
},
"child" : [{
"$" : {
"name" : "John",
"age" : "5"
},
"toy" : [{
"$" : {
"status" : "old"
},
"_" : "Trooper"
}, {
"$" : {
"status" : "old"
},
"_" : "Ultrablock"
}, {
"$" : {
"status" : "new"
},
"_" : "Bike"
}
]
}
]
}
]
}
Quirks to keep in mind:Several tags with the same tagname can be siblings. Other solutions will most likely drop all but the last sibling. To avoid this each and every single node, even if it only has one child, is an array which hold an object for each instance of the tagname. (See multiple "" elements in example)
要记住的怪癖:具有相同标记名的多个标记可以是同级的。其他解决方案很可能会删除除最后一个兄弟之外的所有解决方案。为了避免这种情况,每个节点,即使它只有一个子节点,也是一个数组,它为标记名的每个实例保存一个对象。(参见示例中的多个 "" 元素)
Even the root element, of which only one should exist in a valid XML document is stored as array with an object of the instance, just to have a consistent data structure.
甚至根元素,在一个有效的 XML 文档中应该只存在一个元素,它也被存储为带有实例对象的数组,只是为了具有一致的数据结构。
To be able to distinguish between XML node content and XML attributes each objects attributes are stored in the "$" and the content in the "_" child.
为了能够区分 XML 节点内容和 XML 属性,每个对象的属性都存储在“$”中,而内容存储在“_”子节点中。
Edit:I forgot to show the output for your example input data
编辑:我忘了显示示例输入数据的输出
{
"states" : [{
"state" : [{
"$" : {
"id" : "AL"
},
"name" : [{
"_" : "Alabama"
}
]
}, {
"$" : {
"id" : "AK"
},
"name" : [{
"_" : "Alaska"
}
]
}
]
}
]
}
回答by Coder Of Salvation
A common pitfall is to forget that json_encode()
does not respect elements with a textvalue andattribute(s). It will choose one of those, meaning dataloss.
The function below solves that problem. If one decides to go for the json_encode
/decode
way, the following function is advised.
一个常见的陷阱是忘记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 ) );
by doing so, <foo bar="3">Lorem</foo>
will not end up as {"foo":"Lorem"}
in your JSON.
这样做,<foo bar="3">Lorem</foo>
不会像{"foo":"Lorem"}
您的 JSON那样结束。
回答by Ajay Kumar
Try to use this
尝试使用这个
$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;
Or
或者
You can use this library : https://github.com/rentpost/xml2array
你可以使用这个库:https: //github.com/rentpost/xml2array
回答by Husky
I've used Miles Johnson's TypeConverterfor this purpose. It's installable using Composer.
为此,我使用了 Miles Johnson 的TypeConverter。它可以使用Composer安装。
You could write something like this using it:
你可以用它写这样的东西:
<?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);
回答by Marco Leuti
Optimizing Antonio Max answer:
优化 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);
回答by ChrisR
If you would like to only convert a specific part of the XML to JSON, you can use XPath to retrieve this and convert that to JSON.
如果您只想将 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);
?>
Please note that if you Xpath is incorrect, this will die with an error. So if you're debugging this through AJAX calls I recommend you log the response bodies as well.
请注意,如果您的 Xpath 不正确,则会出现错误。因此,如果您通过 AJAX 调用进行调试,我建议您也记录响应正文。
回答by Alpha
Best solution which works like a charm
像魅力一样的最佳解决方案
$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>';