【问题标题】:How can I append new xml nodes to an existing .xml file with php class DOMDocument?如何使用 php 类 DOMDocument 将新的 xml 节点附加到现有的 .xml 文件?
【发布时间】:2021-12-31 04:14:39
【问题描述】:

假设我有以下 .xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <item>
    <name>Foo</name>
  </item>
  <item>
    <name>Bar</name>
  </item>
 </root>

在此示例文件中,我尝试在最后一个节点 &lt;item&gt; 之后将新节点 &lt;item&gt; 附加到节点 &lt;root&gt;

我正在尝试在 .xml 文件的 &lt;root&gt; 节点中的最后一个 &lt;item&gt; 节点之后追加新创建的 &lt;item&gt; 节点。

<?php
  $file = new DOMDocument;
  $file->load("xml.xml");
  $file->loadXML($file->saveXML());

  $root = $file->getElementsByTagName('root')->item(0);

  foreach (["Foo_1", "Bar_2", "Foo_3", "Bar_4"] as $val) {
    $item = new DOMElement('item');
    $item->appendChild(new DOMElement('name', $val));
    $root->appendChild(item);
  }

?>

但我收到一个错误:

致命错误:未捕获的错误:调用 C:\Users\pfort\Desktop\p.php:12 中为 null 的成员函数 appendChild() 堆栈跟踪: #0 {主要} 在第 12 行的 C:\Users\user_acer\Desktop\p.php 中抛出

我做错了什么?

【问题讨论】:

    标签: php xml domdocument


    【解决方案1】:

    您的示例代码存在多个问题。我将首先解决您收到的错误:

    您的示例 XML 中没有元素 &lt;terminy&gt;,所以

    $root = $file->getElementsByTagName('terminy')->item(0);
    

    将返回null。这就是为什么你会收到

    在 null 上调用成员函数 appendChild()

    错误

    $root->appendChild(item);
    

    另外,item 是一个错字,因为它不是一个有效的变量名(而是一个不存在的常量的名称);你的意思是$item

    我假设“terminy”在您的母语中意味着类似于“root”的意思,并且您实际上打算写

    $root = $file->getElementsByTagName('root')->item(0);
    

    顺便说一句:如果你想引用一个XML文档的根节点,你也可以使用$file-&gt;docomentElement

    但是,您的示例代码还有其他问题:

    $file->load("xml.xml");
    $file->loadXML($file->saveXML()); // why are you reloading it in this way?
    

    最后一行是不必要的。您正在重新加载相同的 XML。是为了格式化吗?如果是这样,还有更好的选择:

    $file->preserveWhiteSpace = false;
    $file->formatOutput = true;
    $file->load("xml.xml");
    

    最后:您不能将子节点附加到尚未与文档关联的节点。因此,要创建一个新项目并将其与文档相关联,您可以这样做(推荐):

    // automatically associate new nodes with document
    $item = $file->createElement('item');
    $item->appendChild($file->createElement('name', $val));
    

    或者(更麻烦):

    // import nodes to associate them with document
    $item = $file->importNode(new DOMElement('item'));
    $item->appendChild($file->importNode(new DOMElement('name', $val)));
    

    所以,把它们放在一起就变成了:

    <?php
    
    $xml = <<<'XML'
    <?xml version="1.0" encoding="UTF-8"?>
    <root>
      <item>
        <name>Foo</name>
      </item>
      <item>
        <name>Bar</name>
      </item>
     </root>
    XML;
    
    $file = new DOMDocument;
    $file->preserveWhiteSpace = false;
    $file->formatOutput = true;
    $file->loadXML($xml); // (for demo purpose loading above XML) replace this with $file->load("xml.xml"); in your actual code
    
    $root = $file->documentElement;
    
    foreach (["Foo_1", "Bar_2", "Foo_3", "Bar_4"] as $val) {
      $item = $file->createElement('item');
      $item->appendChild($file->createElement('name', $val));
      $root->appendChild($item);
    }
    
    echo $file->saveXML();
    

    【讨论】:

    • 非常感谢您的帮助和实事求是的评论。昨晚我太累了,找不到解决办法。您的解决方案帮助我优化了现有的工作 php 代码。 @Decent Dabbler
    【解决方案2】:

    **问题已解决**

    我在这个问题上浪费了太多时间。好消息是,我已经知道如何获得我需要的东西。在这里,我为需要解决相同问题的每个人提供了一个解决方案。 也许这个解决方案对任何需要它的人都有用。

    <?php
    // snippet of xml temple
    $xml = <<<XML
    <item date="%s" status="%s">
      <name>%s</name>
    </item>
    XML;
    
    // prepare snippet
    $xmlSnippet = sprintf($xml, "2022-11-21", 0, "Foo Bar");
    
    // new DOMDocument
    $dom = new DOMDocument;
    $dom->preserveWhiteSpace = 0;
    $dom->formatOutput = 1;
    
    // load of .xml file content and load to DOMDocument object
    $file = simplexml_load_file("xml.xml");
    $dom->loadXML($file->asXML());
    
    // creating of fragment from snippet
    $fragment = $dom->createDocumentFragment();
    $fragment->appendXML($xmlSnippet);
    
    //append the snippet to the DOMDocument
    // and save it to the xml.xml file
    $dom->documentElement->appendChild($fragment);
    $dom->save("xml.xml");
    ?>
    

    结果:

    【讨论】:

    • 为什么要先加载到 SimpleXML 中而不是直接加载到 DOMDocument 中?
    • 你是对的。我不知道为什么我没有考虑过。 @ThW
    猜你喜欢
    • 2015-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-19
    • 1970-01-01
    • 2018-06-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多