1

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');
2
  • What doesn't work? If any errors are shown, add them to your question. If the script runs but the result is not what you expect it to be, show what the result is and what you expect it to be. Commented Sep 14, 2016 at 18:02
  • @lucash it just don't load the php page. So it doesn't do anything. Commented Sep 14, 2016 at 18:19

1 Answer 1

1

$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();
Sign up to request clarification or add additional context in comments.

3 Comments

This works exactly as you wrote. But, when I try to change it to create the new "track" element before the 659th it cames not to work. Maybe I changed it badly.
The XML document has 915 <track> tags.
Are they all in the same hour parent element? Position does not sound like the most stable condition, is here another?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.