du13520157325 2018-09-03 15:48
浏览 28
已采纳

加载XML文件 - >添加项目 - >重新排序 - >写入XML文件[PHP和SimpleXML]

SUMMARY

  1. Load existing XML-File
  2. Add 2 items to every child
  3. Change order of children
  4. Write new XML-File

DETAILED EXPLANATION

This is a shortened sample of the 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. Load existing XML-File

Load the XML-File into a variable.

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

2. Add 2 items to every child

Add 2 children to the first inventory with name and value.

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

3. Change order of children

This is the part that doesn't work for me, no matter what I tried.

My idea was the following:

$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);
}

The basic idea is that I take a child (<inventory>) out of <warehouse> and store in in a variable or maybe an array (which would be way better and easier) containing everything that <inventory> contains (including attributes and child nodes and so on). After I have stored all <inventory> somewhere else I take a new XML and put the stored <inventory> in a new order into the new XML.

However it seems impossible to save a whole child into a variable (or an array) and add it to another XML later.

Since the order is not necessarily in order a simple sort wouldn't help me out here and since I wasn't able to get sorting to work I am at a loss here.

4. Write new XML-File

Save the new XML content to a new XML-File.

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

This is a shortened sample of the destination-XML-File

<?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>

Can someone help me to figure out how to make this work?

Right now I'm resorting to parse the whole XML-File and rewrite it line by line with string since SimpleXML doesn't seem to work.

  • 写回答

1条回答 默认 最新

  • duanbogan5878 2018-09-04 13:37
    关注

    There are a few things which I'm not sure about, but hopefully this code will show the principle of copying the nodes from one document to another (and adding content) using DOMDocument. I've added comments to the code to help, if there is anything you are unsure about, then let me know.

    $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);
    

    The output is almost just a copy of the input document with the extra data. You could in the second foreach() loop add some logic to order the output elements in some other format, which I'm not sure what that is.

    Also note there is a minor XML flaw in your document...

    </marker>green</marker>
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 从Freecad中宏下载的DesignSPHysics,出现如下问题是什么原因导致的(语言-python)
  • ¥30 notepad++ 自定义代码补全提示
  • ¥15 MATLAB有限差分法解一维边值问题
  • ¥200 内网渗透测试 横向渗透 Windows漏洞 Windows权限维持
  • ¥15 数据结构图的相关代码实现
  • ¥15 python中aiohttp.client_exceptions.ContentTypeError
  • ¥30 DeepLung肺结节检测生成最大froc值对应的epoch报错
  • ¥15 信号发生器如何将频率调大,步尽值改成10
  • ¥15 keil 5 编程智能家具,风扇台灯开关,人体感应等
  • ¥100 找一名渗透方面的专家