Home > Enterprise >  How can I append new xml nodes to an existing .xml file with php class DOMDocument?
How can I append new xml nodes to an existing .xml file with php class DOMDocument?

Time:11-22

Let's say I have the following .xml file:

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

In this sample file, I'm trying to append new nodes <item> to node <root> after the last node <item>.

I'm trying to append newly created <item> nodes after the last <item> node in the <root> node in the .xml file.

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

?>

But I'm getting an error:

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

What am I doing wrong?

CodePudding user response:

There's multiple issues with your example code. I will address the error you received first:

There is no element <terminy> in your example XML, so

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

will return null. That's why you are receiving the

Call to a member function appendChild() on null

error at

$root->appendChild(item);

Also, item is a typo, because it's not a valid variable name (but a name for a non-existent constant); you meant $item.

I'm assuming "terminy" means something similar to "root" in your native language and that you actually meant to write

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

By the way: if you want a reference to the root node of an XML document, you can also use $file->docomentElement.

However, there are other issues with your example code:

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

The last line is unnecessary. You are reloading the same XML again. Is it for formatting purposes? If so, there's a better option available:

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

Lastly: you cannot append children to a node that has not been associated with a document yet. So, to create a new item and associate it with the document, you either do (recommended):

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

or (more cumbersome):

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

So, putting it all together it becomes:

<?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();

CodePudding user response:

**PROBLEM SOLVED**

I lost too much time on this problem. The good news is, I already know how to get what I need. Here I offer a solution - for everyone who will need to solve the same problem. Perhaps this solution will be useful for anyone who needs it.

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

  • Related