Json 编码或序列化 XML
Posted
技术标签:
【中文标题】Json 编码或序列化 XML【英文标题】:Json Encode or Serialize an XML 【发布时间】:2013-09-04 03:44:47 【问题描述】:我有一些xml,这是一个简单的版本。
<xml>
<items>
<item abc="123">item one</item>
<item abc="456">item two</item>
</items>
</xml>
在内容上使用 SimpleXML,
$obj = simplexml_load_string( $xml );
我可以使用$obj->xpath( '//items/item' );
并访问@attributes。
我需要一个数组结果,所以我尝试了 json_decode(json_encode($obj),true)
技巧,但这似乎是删除对 @attributes 的访问(即 abc="123")。
是否有另一种方法可以提供对属性的访问并为我留下一个数组?
【问题讨论】:
“我需要一个数组结果” - 为什么?您需要它采用什么格式?如果您不介意它的格式,那么只需存储$item->asXML();
并下次重新解析即可。
我正在处理数据以期望标准数组格式的其他方法
那么任何内置的 php 函数如何知道“标准数组格式”需要是什么样的呢?您的代码需要将 you 期望的输入解析为 you 需要的输出。
IMSoP,我会通读你所有的 SimpleXML 主题,希望能得到一些指点。
【参考方案1】:
你需要调用 attributes() 函数。
示例代码:
$xmlString = '<xml>
<items>
<item abc="123">item one</item>
<item abc="456">item two</item>
</items>
</xml>';
$xml = new SimpleXMLElement($xmlString);
foreach( $xml->items->item as $value)
$my_array[] = strval($value->attributes());
print_r($my_array);
Eval
【讨论】:
我需要一个数组结果,所以我猜我需要自己构建一个数组?因为 json_encode() 剥离了属性? 正如我所怀疑的那样。我希望也许有一些 json_encode() 技巧或相关函数可以在将对象转换为数组时保留属性。谢谢! 这个方法看起来不错,但是这段代码很奇怪。为什么你使用$xml->items->item[$i++]
而不是$value
?为什么分配$xmlitems
只是为了循环它而foreach ( $xml->items->item as $value )
也可以工作?
哦,另外,strval($foo->attributes())
将始终返回字符串 'array'
。我猜您的意图是将strval
应用于每个属性 而不是整个列表?【参考方案2】:
您可以使用json_encode
和json_decode
进行路由,并且可以添加缺少的内容,因为json_encode
-ing 遵循SimpleXMLElement
的一些特定规则。
如果您对规则及其详细信息感兴趣,我已经写了两篇关于它的博文:
SimpleXML and JSON Encode in PHP – Part I SimpleXML and JSON Encode in PHP – Part II对你来说可能更有趣的是第三部分,它展示了如何修改 json 序列化并提供你自己的格式(例如,保留属性):
SimpleXML and JSON Encode in PHP – Part III and End它附带了一个完整的示例,这里是代码的摘录:
$xml = '<xml>
<items>
<item abc="123">item one</item>
<item abc="456">item two</item>
</items>
</xml>';
$obj = simplexml_load_string($xml, 'JsonXMLElement');
echo $json = json_encode($obj, JSON_PRETTY_PRINT), "\n";
print_r(json_decode($json, TRUE));
JSON和数组的输出如下,注意属性是其中的一部分:
"items":
"item": [
"@attributes":
"abc": "123"
,
"@text": "item one"
,
"@attributes":
"abc": "456"
,
"@text": "item two"
]
Array
(
[items] => Array
(
[item] => Array
(
[0] => Array
(
[@attributes] => Array
(
[abc] => 123
)
[@text] => item one
)
[1] => Array
(
[@attributes] => Array
(
[abc] => 456
)
[@text] => item two
)
)
)
)
【讨论】:
值得注意的是,第三部分中的递归函数与独立函数一样工作,无需任何 JSON 参考。使用 DOM 或 XMLReader API 看起来也差不多。我仍然不相信像这样的通用转换比使用可用的 API 以特定情况的方式遍历 XML 的价值。 好吧。第三部分顶部说该函数替换了数组强制转换,因此确保它在没有 JSON 序列化的情况下也能正常工作。如果您选择底部的装饰器(Cutting The Gordian Knot),并确保$decorator
上的工作实际上也返回了数组(而不是仅仅对其进行分配),这就是这样做的。然后,您可以将其命名为 ArraySimpleXMLElementSerializer
或其他名称:)
@hakre 是的;我认为将其呈现为 SimpleXML+json_encode 的 替代 会更强大,而不是暗示它以某种方式“修复”它。顺便说一句,我在这些帖子下方以我的真实姓名发布了几个 cmets(略显批评,但希望不会冒犯),但我认为它们已被垃圾邮件过滤器吃掉了。
@IMSoP:我在我的博客上找不到您的评论,无论是在垃圾邮件中还是在标准阵容中。对不起。还检查了我收到副本的邮件,但什么也没有。也许是错误的网站?
@hakre 哦,好吧,也许 wordpress.com 默默地吃了它们;我听说它有时会这样做。感谢收看;也许我会在某个时候再试一次。【参考方案3】:
$xml = new SimpleXMLElement($xmlString);
$xml 现在是一个对象。获取属性值:
$xml->something['id'];
其中 'id' 是属性的名称。
【讨论】:
我需要一个数组结果。我将存储它并想在某个时候检索它。我希望属性在我 json_decode 或反序列化之后存在于数组中。【参考方案4】:虽然理论上可以编写从 XML 到 PHP 或 JSON 结构的通用转换,但很难捕捉到所有可能存在的细微差别 - 子元素和属性之间的区别、文本内容与属性(如您所见)这里)甚至在子元素旁边,多个具有相同名称的子节点,子元素和文本节点的顺序是否重要(例如在 Xhtml 或 DocBook 中)等等。
如果您需要生成特定格式,通常使用 API(如 SimpleXML)来循环 XML 并生成您需要的结构会容易得多。
您没有指定要实现的结构,但给出输入的一般方法是遍历每个项目,并访问已知属性或遍历每个属性:
$sxml = simplexml_load_string( $xml );
$final_array = array();
foreach ( $sxml->items->item as $xml_item )
$formatted_item = array();
// Text content of item
$formatted_item['content'] = (string)$xml_item;
// Specifically get 'abc' attribute
$formatted_item['abc'] = (string)$xml_item['abc'];
// Maybe one of the attributes is an integer
$formatted_item['foo_id'] = (int)$xml_item['foo_id'];
// Or maybe you want to loop over lots of possible attributes
foreach ( $xml_item->attributes() as $attr_name => $attr_value )
$formatted_item['attrib:' . $attr_name] = (string)$attr_value;
// Add it to a final list
$final_array[] = $formatted_item;
// Or maybe you want that array to be keyed on one of the attributes
$final_array[ (string)$xml_item['key'] ] = $formatted_item;
【讨论】:
【参考方案5】:这是我发现的一个类,它能够很好地将 XML 处理成数组:http://outlandish.com/blog/xml-to-json/ (backup)。转换为 json 是一个 json_encode()
调用的问题。
【讨论】:
以上是关于Json 编码或序列化 XML的主要内容,如果未能解决你的问题,请参考以下文章
.net JSON 或 XML 对象序列化和包含字段类型的创建
Json或XML快速反序列化类(Visual Studio 2012以上)
是否有一个 XML 或 JSON 序列化器知道使用哪个构造函数来填充不可变对象并序列化 IEnumerable<> 属性? [关闭]