【问题标题】:merge xml childs with php将xml子项与php合并
【发布时间】:2014-02-02 21:30:17
【问题描述】:

尝试了许多不同的脚本,最终得到了这个我觉得必须接近解决方案的脚本,但不确定如何定义孩子。试过“@name”和“name”。 我尝试过的所有脚本都是从这里和那里复制并修改以供我使用。

每个 XML 有 1 个节点和 1 个子节点。那么这应该不会容易得多,但没有运气。 可以提一下,我还希望合并 xsl 样式表引用,但我想我只是偶然发现了一个解决方案,但忘记为页面添加书签。

xml 1:

<?xml version="1.0" encoding="utf-8"?>
<companyroutes>
  <route name="BBUPLOAD">ENGM OKSAT L996 SVD EKCH</route>

</companyroutes>

xml 2:

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xml" href="merge2.xsl"?> 
<companyroutes>
   <route name="XXXXCORE">RUTA TULLA L666 BARE LITT MNOP</route>

</companyroutes>

还有 PHP 代码(此文件与输出文件位于同一目录中:

  <?php
    $doc1 = new DOMDocument();
    $doc1->load('/uploads/companyroutes.xml');

    $doc2 = new DOMDocument();
    $doc2->load('/uploads/companyroutes_core.xml');

    // get 'res' element of document 1
    $res1 = $doc1->getElementsByTagName('res')->name(0);

    // iterate over '@name' elements of document 2
    $companyroutes2 = $doc2->getElementsByTagName('name');
    for ($i = 0; $i < $companyroutes2->length; $i ++) {
        $name2 = $companyroutes2->name($i);

        // import/copy @name from document 2 to document 1
        $name1 = $doc1->importNode($name2, true);

        // append imported @name to document 1 'res' element
        $res1->appendChild($name1);

    }
    $doc1->save('companyroutes.xml'); 
    ?>

任何指针表示赞赏。

【问题讨论】:

    标签: php xml domdocument


    【解决方案1】:

    以下是如何将文件与simplexml 合并:

    $xml = simplexml_load_string($x1); // assume XML in $x1 and $x2
    $xml2 = simplexml_load_string($x2);
    
    foreach ($xml2->route as $route) {  // merge $xml2 into $xml
        $newroute = $xml->addChild("route", $route);
        $newroute->addAttribute("name", $route['name']);
    }
    
    unset($xml2); // dispose $xml2
    
    echo $xml->asXML();
    

    看到它的工作:https://eval.in/97372

    【讨论】:

    • $x1 和 $x2 会是两个 xml 文件的 URL 吗?比如:$x1 = ('/uploads/companyroutes.xml');
    • @NAX 在我的示例中,它们是字符串。查看我的答案中的链接。您可以将 simplexml_load_file 与文件名一起使用。
    • 所以我只需将前两行更改为: $xml = simplexml_load_file('/uploads/companyroutes_core.xml'); ... 和 $xml2 = simplexml_load_file('/uploads/companyroutes.xml') ... 我可以在 echo 命令后添加一行,以便脚本复制结果 xml 并粘贴到 Companyroutes_core.xml?我需要这个函数来确保结果 xml 是下一次合并的核心。 /uploads/companyroutes.xml 由许多用户上传,将他们的新条目添加到合并文件中。如果核心没有更新,当下一个人上传和合并时,新条目将丢失。 file_put 可能吗?
    • @NAX $xml2 被合并到$xml,所以这应该是你的目标文件。我代码中的echo 仅用于演示目的,请阅读php.net 上的simplexml 手册,了解如何将XML 保存到文件。
    【解决方案2】:

    两步,准备目标DOM(添加文档元素)。加载每个源 XML,遍历文档元素内的子节点并将它们导入目标文档:

    $xmlFiles = [
      '/uploads/companyroutes.xml',
      '/uploads/companyroutes_core.xml'
    ];
    
    $targetDom = new DOMDocument();
    $targetDom->appendChild(
      $targetDom->createProcessingInstruction(
        'xml-stylesheet', 'type="text/xml" href="merge2.xsl"' 
      )
    );
    $rootNode = $targetDom->appendChild(
      $targetDom->createElement('companyroutes')
    );
    
    foreach ($xmlFiles as $xmlFile) {
      $importDom = new DOMDocument();
      $importDom->load($xmlFile);
      foreach ($importDom->documentElement->childNodes as $node) {
        $rootNode->appendChild($targetDom->importNode($node, TRUE));
      }
    }
    
    echo $targetDom->saveXml();
    

    以 XML 字符串作为源的示例:https://eval.in/97405

    当然,您可以为目标 DOM 创建一个模板 XML 并加载它:

    $template = <<<'XML'
    <?xml version="1.0" encoding="utf-8"?>
    <?xml-stylesheet type="text/xml" href="merge2.xsl"?> 
    <companyroutes/>
    XML;
    
    $targetDom = new DOMDocument();
    $targetDom->loadXml($template);
    $rootNode = $targetDom->documentElement;
    ...
    

    我不建议更改文档。如果您构建一个新文档,您可以重复该操作。

    【讨论】:

    • 我可以在这里涉及到第一个脚本,因为我有点理解所有行。我将在今天晚些时候测试这个。
    • 第二个例子只是展示了创建 $targetDom 并通过加载模板 xml 来分配 $rootNode 变量的替代方法。
    【解决方案3】:

    谢谢。我做了一点编辑并让它运行起来。

    $xml = simplexml_load_file('./uploads/companyroutes_core.xml');  // xml files URL insted of $x
    $xml2 = simplexml_load_file('./uploads/companyroutes.xml');
    
    foreach ($xml2->route as $route) {  // merge $xml2 into $xml
        $newroute = $xml->addChild("route", $route);
        $newroute->addAttribute("name", $route['name']);
    }
    
    unset($xml2); // dispose $xml2
    
    $xml->asXML('merged.xml'); //this line saves to directory and name of choice
    

    我现在唯一的问题是所有 Childs 都输出在一行上。一条 4Mb 长的线路。需要它更整洁(是的,我已经阅读了关于 tidy 命令的信息,但是如何在这里使用它......?idunno)并为每个孩子分解它。感谢您到目前为止的耐心。如果您看到我提出更多基本问题,请不要大吃一惊,但好在我每天都在努力学习更多知识。

    【讨论】:

    • @michi 是否可以插入仅用于合并唯一条目的命令?我发现了使用数组的例子,只合并了唯一的孩子,但不能直接将这些行插入到这个脚本中。这个脚本的功能可以用数组来完成吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-08
    • 2011-05-10
    相关资源
    最近更新 更多