user3746625 user3746625 - 2 months ago 14
PHP Question

XML create node before another PHP

I have a XML file and I'm trying to insert a new node between two others with PHP script.

XML file:

<playlistLog>
<hour>
<track>
<type>take</type>
<url>URL</url>
<title>1473869236.wav</title>
<mix>0</mix>
</track>
(...)
</hour>
</playlistLog>


PHP file:

$xmldoc = new DOMDocument();

$xmldoc->load('../logs/log14-09-2016.xml');

$elem = $xmldoc->getElementsByTagName("track");

$track = $xmldoc->createElement('track');

$type = $xmldoc->createElement('type', 'take');
$track->appendChild($type);

$url = $xmldoc->createElement('url', 'url');
$track->appendChild($url);

$title = $xmldoc->createElement('title', 'title');
$track->appendChild($title);

$mix = $xmldoc->createElement('mix', 'mix');
$track->appendChild($mix);

$xmldoc->documentElement->insertBefore($track,$elem[660]);
$xmldoc->save('../logs/log14-09-2016.xml');


I'm trying to insert the new node before "track" tag number 660 but when I try to open the php file it doesn't work at all.

Can anybody tell me what I am doing wrong?

SOLUTION:

After @ThW response I change a bit what he wrotes and finally the code is doing right:

$document = new DOMDocument();
$document->preserveWhiteSpace = FALSE;
$document->load('../logs/log14-09-2016.xml');
$xpath = new DOMXpath($document);
$previousTrack = $xpath->evaluate('/playlistLog/hour/track')->item(659);
$newTrack = $previousTrack->parentNode->insertBefore($document->createElement('track'),$previousTrack);
$newTrack
->appendChild($document->createElement('type'))
->appendChild($document->createTextNode('take'));
$document->formatOutput = TRUE;
echo $document->save('../logs/log14-09-2016.xml');

ThW ThW
Answer

$elem[660] is the 661st element node with the tag name track. But its parent node is not the document element. Here is another hour ancestor between. The node you're providing to insertBefore() has a different parent then the node you're adding the new element to.

You can use the $parentNode property to make sure that you append to that node.

Additionally I suggest using Xpath to fetch the track node.

$xml = <<<'XML'
<playlistLog>
  <hour>
    <track>
      <type>take</type>
      <url>URL</url>
      <title>1473869236.wav</title>
      <mix>0</mix>
    </track>
  </hour>
</playlistLog>
XML;

$document = new DOMDocument();
$document->preserveWhiteSpace = FALSE;
$document->loadXml($xml);

$xpath = new DOMXpath($document);
$previousTrack = $xpath->evaluate('/playlistLog/hour/track[1]')->item(0);

$newTrack = $previousTrack
  ->parentNode
  ->insertBefore(
    $document->createElement('track'),
    $previousTrack
  );

$newTrack
  ->appendChild($document->createElement('type'))
  ->appendChild($document->createTextNode('take'));

$document->formatOutput = TRUE;
echo $document->saveXml();
Comments