我需要使用一些非常简单快速的解决方案将XML文件转换为数组。这个对我来说很好看:
json_decode(json_encode(simplexml_load_string($xmlContent, "SimpleXMLElement", LIBXML_NOCDATA)), true);
这个问题是它将多个子节点视为一个索引数组,每个子节点包含一个关联数组,但如果它只是父标记中的一个子节点,它就不会创建一个索引数组使用一个元素并将一个assoc数组直接放到父标记元素。我需要这些场景的输出是一致的。即索引数组首先不依赖于子项的数量。我的目标是解析后的一致模式。
多个孩子的一个例子:
输入:
<PICK_NOTE_LINES>
<LINE>
<PICK_LINE_NUM>1</PICK_LINE_NUM>
<PRODUCT_CODE>3342</PRODUCT_CODE>
<BATCH_CODE></BATCH_CODE>
<QUANTITY>1</QUANTITY>
</LINE>
<LINE>
<PICK_LINE_NUM>2</PICK_LINE_NUM>
<PRODUCT_CODE>5285</PRODUCT_CODE>
<BATCH_CODE></BATCH_CODE>
<QUANTITY>1</QUANTITY>
</LINE>
</PICK_NOTE_LINES>
输出(在LINE父元素中是索引数组):
['PICK_NOTE_LINES'=>['LINE'=>[['PICK_LINE_NUM'=>1, ...],['PICK_LINE_NUM'=>2, ...]]]
一个孩子的例子:
<PICK_NOTE_LINES>
<LINE>
<PICK_LINE_NUM>1</PICK_LINE_NUM>
<PRODUCT_CODE>3342</PRODUCT_CODE>
<BATCH_CODE></BATCH_CODE>
<QUANTITY>1</QUANTITY>
</LINE>
</PICK_NOTE_LINES>
输出(行父元素中的关联数组):
['PICK_NOTE_LINES'=> ['LINE'=>['PICK_LINE_NUM'=>1, ...]]]
即使它只有一个孩子,是否有可能让孩子一直把孩子放入索引数组?如果不可能,我可以用什么来获得一致的输出?
答案 0 :(得分:1)
我最终使用了saber / xml库。几行代码,它给了我我需要的结构:
$this->service->elementMap = [
'{}DOCUMENT' => $assocParser,
'{}DATA' => $assocParser,
'{}CONSIGNMENTS' => $indexParser,
'{}PICK_NOTE_LINES' => function ($reader) use ($makeArray) {
$lines = [];
$children = $reader->parseInnerTree();
foreach ($children as $child) {
$lines[] = $makeArray($child['value']);
}
return $lines;
},
];
其中$this->service
是Sabre\Xml\Service
,$ assocParser和$ indexParser使用$makeArray
闭包从lib的标准输出创建我需要的数组结构。
答案 1 :(得分:0)
实际上解析非常一致 - 但转换是有限的,因为JSON没有与XML相同的格式功能。
您的请求无法正常工作,因为通用转换器无法知道此处是否“可能”是多个子节点(具有相同名称)。如果它无论如何都会创建数组,它会对任何元素执行此操作(甚至像foo(int&)
这样的父节点)。像JsonML这样的一些基于JSON的格式实际上就是这样。
SimpleXML本身允许您将每个元素视为单个节点或列表。您知道如何访问数据以避免问题。
如果您想创建特定的JSON输出,则需要编写自己的转换逻辑,读取XML并创建对象/数组结构。
我强烈建议避免通用转换。如果您正在阅读XML,请保留SimpleXMLElement,转换意味着您将丢失数据和API功能。
如果您需要特定的JSON输出,请使用您自己的逻辑生成它。通过这种方式,您可以确保结构是您需要的结构。