如何使用 php class DOMDocument 将新的 xml 节点附加到现有的 .xml 文件?
How can I append new xml nodes to an existing .xml file with php class DOMDocument?
假设我有以下 .xml 文件:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<item>
<name>Foo</name>
</item>
<item>
<name>Bar</name>
</item>
</root>
在此示例文件中,我尝试将新节点 <item>
添加到最后一个节点 <item>
之后的节点 <root>
。
我正在尝试在 .xml 文件的 <root>
节点中的最后一个 <item>
节点之后附加新创建的 <item>
节点。
<?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);
}
?>
但我收到一个错误:
Fatal error: Uncaught Error: Call to a member function appendChild() on null in C:\Users\pfort\Desktop\p.php:12
Stack trace:
#0 {main}
thrown in C:\Users\user_acer\Desktop\p.php on line 12
我做错了什么?
**问题已解决**
我在这个问题上浪费了太多时间。好消息是,我已经知道如何获得我需要的东西。在这里,我提供了一个解决方案 - 适用于需要解决相同问题的每个人。
也许这个解决方案对任何需要它的人都有用。
<?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");
?>
Result:
您的示例代码存在多个问题。我将首先解决您收到的错误:
您的示例 XML 中没有元素 <terminy>
,因此
$root = $file->getElementsByTagName('terminy')->item(0);
将 return null
。这就是您收到
的原因
Call to a member function appendChild() on null
错误
$root->appendChild(item);
此外,item
是一个拼写错误,因为它不是一个有效的变量名(而是一个不存在的常量的名称);你是说 $item
.
我假设“terminy”在您的母语中的意思类似于“root”,并且您实际上是想写
$root = $file->getElementsByTagName('root')->item(0);
顺便说一句:如果你想引用XML文档的根节点,你也可以使用$file->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();
假设我有以下 .xml 文件:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<item>
<name>Foo</name>
</item>
<item>
<name>Bar</name>
</item>
</root>
在此示例文件中,我尝试将新节点 <item>
添加到最后一个节点 <item>
之后的节点 <root>
。
我正在尝试在 .xml 文件的 <root>
节点中的最后一个 <item>
节点之后附加新创建的 <item>
节点。
<?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);
}
?>
但我收到一个错误:
Fatal error: Uncaught Error: Call to a member function appendChild() on null in C:\Users\pfort\Desktop\p.php:12 Stack trace: #0 {main} thrown in C:\Users\user_acer\Desktop\p.php on line 12
我做错了什么?
**问题已解决**
我在这个问题上浪费了太多时间。好消息是,我已经知道如何获得我需要的东西。在这里,我提供了一个解决方案 - 适用于需要解决相同问题的每个人。 也许这个解决方案对任何需要它的人都有用。
<?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");
?>
Result:
您的示例代码存在多个问题。我将首先解决您收到的错误:
您的示例 XML 中没有元素 <terminy>
,因此
$root = $file->getElementsByTagName('terminy')->item(0);
将 return null
。这就是您收到
Call to a member function appendChild() on null
错误
$root->appendChild(item);
此外,item
是一个拼写错误,因为它不是一个有效的变量名(而是一个不存在的常量的名称);你是说 $item
.
我假设“terminy”在您的母语中的意思类似于“root”,并且您实际上是想写
$root = $file->getElementsByTagName('root')->item(0);
顺便说一句:如果你想引用XML文档的根节点,你也可以使用$file->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();