首页 > 解决方案 > 加载 XML 文件 -> 添加项目 -> 重新排序 -> 写入 XML 文件 [PHP & SimpleXML]

问题描述

概括

  1. 加载现有的 XML 文件
  2. 为每个孩子添加 2 个项目
  3. 改变孩子的顺序
  4. 编写新的 XML 文件

详细说明

这是 Source-XML-File 的简化示例

<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
<warehouse>
  <inventory>
    <name>Name 1</name>
    <markers>
     <marker>red</marker>
     <marker>yellow</marker>
     <marker>green</marker>
   </markers>
   (...)
  </inventory>
  <inventory>
    <name>Name 2</name>
    <markers>
     <marker>blue</marker>
     <marker>pink</marker>
     <marker>brown</marker>
   </markers>
   (...)
  </inventory>
  <inventory>
    <name>Name 3</name>
    <markers>
     <marker>black</marker>
     <marker>white</marker>
     <marker>marron</marker>
   </markers>
   (...)
  </inventory>
</warehouse>

1.加载现有的XML-File

将 XML 文件加载到变量中。

$source_xmlfile = "source.xml";
$source_xml_file_contents = simplexml_load_file($source_xmlfile);

2.给每个孩子添加2个项目

将 2 个孩子添加到具有名称和值的第一个库存中。

$source_xml_file_contents->warehouse->inventory[0]->addChild("new1", "0.12345");
$source_xml_file_contents->warehouse->inventory[0]->addChild("new2", "17");

3. 改变孩子的顺序

无论我尝试什么,这对我都不起作用。

我的想法如下:

$destination_xml_file_contents = new SimpleXMLElement('<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?><warehouse></warehouse>');
foreach($source_xml_file_contents->warehouse->inventory as $inventory){
  $destination_xml_file_contents->warehouse->addChild("inventory", $inventory);
}

基本思想是我从 <warehouse> 中取出一个子项 (<inventory>) 并存储在一个变量或一个数组中(这会更好更容易),其中包含 <inventory> 包含的所有内容(包括属性和子项)节点等)。在我将所有 <inventory> 存储在其他地方之后,我获取一个新的 XML 并将存储的 <inventory> 以新的顺序放入新的 XML 中。

但是,将整个子项保存到变量(或数组)中并稍后将其添加到另一个 XML 似乎是不可能的。

由于顺序不一定按顺序排列,因此简单的排序在这里对我没有帮助,而且由于我无法进行排序,所以我在这里不知所措。

4. 编写新的 XML 文件

将新的 XML 内容保存到新的 XML 文件中。

$new_xml_file = "destination.xml";
$destination_xml_file_contents->asXML($new_xml_file);

这是目标 XML 文件的缩短示例

<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
<warehouse>
  <inventory>
    <name>Name 2</name>
    <markers>
     <marker>blue</marker>
     <marker>pink</marker>
     </marker>brown</marker>
   </markers>
   (...)
   <new1>0.6789</new1>
   <new2>115</new2>
  </inventory>
  <inventory>
    <name>Name 1</name>
    <markers>
     <marker>red</marker>
     <marker>yellow</marker>
     </marker>green</marker>
   </markers>
   (...)
   <new1>0.4567</new1>
   <new2>4</new2>
  </inventory>
  <inventory>
    <name>Name 3</name>
    <markers>
     <marker>black</marker>
     <marker>white</marker>
     </marker>marron</marker>
   </markers>
   (...)
   <new1>0.1234</new1>
   <new2>17</new2>
  </inventory>
</warehouse>

有人可以帮我弄清楚如何完成这项工作吗?

现在我正在解析整个 XML 文件并用字符串逐行重写它,因为 SimpleXML 似乎不起作用。

标签: phpsimplexml

解决方案


有几件事我不确定,但希望这段代码能够展示使用 DOMDocument 将节点从一个文档复制到另一个文档(并添加内容)的原理。我在代码中添加了注释以提供帮助,如果您有任何不确定的地方,请告诉我。

$inFile = "data.xml";
$input = new DOMDocument();
$input->load($inFile);

$all_inventory = $input->getElementsByTagName("inventory");
// Add new content to each item
foreach ( $all_inventory as $inventory )    {
    $inventory->appendChild ( $input->createElement("new1", "0.12345"));
    $inventory->appendChild ( $input->createElement("new2", "17"));
}

$outFile = "out.xml";
$output = new DOMDocument();
// Create base document for destination
$output->loadXML('<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?><warehouse />');
// Get the root element as we will be adding content to this
$outputRoot = $output->documentElement;
foreach ( $all_inventory as $inventory )    {
    // Copy the element from the input document to the output document
    // Note this does not add it anywhere, just makes it available
    // The true option says make a deep copy
    $import = $output->importNode($inventory, true);
    // Add the newly imported node to the output document root
    $outputRoot->appendChild($import);
}
$output->save($outFile);

输出几乎只是带有额外数据的输入文档的副本。您可以在第二个foreach()循环中添加一些逻辑来以其他格式对输出元素进行排序,我不确定那是什么。

另请注意,您的文档中有一个小的 XML 缺陷...

</marker>green</marker>

推荐阅读