首页 > 解决方案 > PHP 遍历具有无效结构的 XML 文件

问题描述

如何遍历如下所示的 XML 文件?它的输出没有任何根节点或父节点。有些元素会重复,但有些则不会。而且,它是来自遗留应用程序的大文件输出。

<name>Chair</name>
<price>$53</price>
<quantity>20</quantity>
<units>Piece</units>
<name>Lamp</name>
<price>$20</price>
<quantity>90</quantity>
<units>Piece</units>
<name>Table</name>
<price>$35</price>
<quantity>10</quantity>
<units>Piece</units>
<material>Wood</material>
<name>Pen Holder</name>
<price>$5</price>
<quantity>20</quantity>
<units>Piece</units>
<color>Black</color>

否则我就是这样做的,但它不适用于此。

$data=simplexml_load_file("inventory.xml");

foreach($data->item as $item) {
        echo "Name: " . $item->name . "<br>";
        echo "Price: " . $item->price . "<br>";
        echo "Quantity: " . $item->quantity . "<br>";
        echo "Units: " . $item->units . "<br>";
        echo "Color: " . $item->color . "<br>";
}

标签: phpxml

解决方案


添加根元素很容易。您只需将 XML 加载到字符串中,然后根据需要附加和前置。但是,对项目中的各种元素进行分组有点棘手,并且很大程度上取决于 XML。以下代码将适用于您显示的 XML:

<?php

$xml = 'your xml from the question';

$dom = new DOMDocument;
$dom->loadXml("<root>$xml</root>");

$fixed = new DOMDocument();
$fixed->loadXML("<inventory><items/></inventory>");
$fixed->formatOutput = true;

$items = $fixed->getElementsByTagName('items')->item(0);
foreach ($dom->documentElement->childNodes as $node) {
    if ($node->nodeName === 'name') {
        $item = $fixed->createElement('item');
        $item->appendChild($fixed->createElement($node->nodeName, $node->nodeValue));
        $next = $node->nextSibling;
        while ($next !== null) {
            if ($next instanceof DOMElement) {
                if ($next->nodeName !== 'name') {
                    $item->appendChild($fixed->createElement($next->nodeName, $next->nodeValue));
                } else {
                    $items->appendChild($item);
                    break;
                }
            }
            $next = $next->nextSibling;
        }
    }
}
echo $fixed->saveXML();

这将创建两个文档:

  1. 您的旧 XML 带有一个虚拟<root>元素,因此我们可以对其进行处理
  2. 具有根元素<inventory>和空元素的文档<items>

然后我们将迭代遗留 XML 中的所有元素。当我们找到一个<name>元素时,我们创建一个新<item>元素并将该<name>元素添加为子元素。然后我们检查<name>元素的每个后续兄弟。如果它不是一个<name>元素,我们也会将它添加到<item>。当它是另一个<name>时,我们将其添加<item><items>集合中并重新开始。

这将产生:

<?xml version="1.0"?>
<inventory>
  <items>
    <item>
      <name>Chair</name>
      <price>$53</price>
      <quantity>20</quantity>
      <units>Piece</units>
    </item>
    <item>
      <name>Lamp</name>
      <price>$20</price>
      <quantity>90</quantity>
      <units>Piece</units>
    </item>
    <item>
      <name>Table</name>
      <price>$35</price>
      <quantity>10</quantity>
      <units>Piece</units>
      <material>Wood</material>
    </item>
  </items>
</inventory>

您可能可以在一个文档中完成所有这些操作。我觉得用两个文件更容易理解。


推荐阅读