Simplexml How to Prepend a Child in a Node

SimpleXML how to prepend a child in a node?

As it's been mentionned, SimpleXML doesn't support that so you'd have to use DOM. Here's what I recommend: extend SimpleXMLElement with whatever you need to use in your programs. This way, you can keep all the DOM manipulation and other XML magic outside of your actual program. By keeping the two matters separate, you improve readability and maintainability.

Here's how to extend SimpleXMLElement with a new method prependChild():

class my_node extends SimpleXMLElement
{
public function prependChild($name, $value)
{
$dom = dom_import_simplexml($this);

$new = $dom->insertBefore(
$dom->ownerDocument->createElement($name, $value),
$dom->firstChild
);

return simplexml_import_dom($new, get_class($this));
}
}

$actors = simplexml_load_string(
'<actors>
<actor>Al Pacino</actor>
<actor>Zsa Zsa Gabor</actor>
</actors>',
'my_node'
);

$actors->addChild('actor', 'John Doe - last');
$actors->prependChild('actor', 'John Doe - first');

die($actors->asXML());

How to add SimpleXMLElement node as a child element?

SimpleXML is good for basic things, but lacks the control (and complications) of DOMDocument.

When copying content from one document to another, you have to do three things (for SimpleXML), first is convert it to a DOMElement, then import it into the target document using importNode() with true as the second argument to say do a deep copy. This just makes it available to the target document and doesn't actually place the content. This is done using appendChild() with the newly imported node...

// Convert target SimpleXMLElement to DOMElement
$targetImport = dom_import_simplexml($target_body);

foreach ($source_body as $source_child) {
foreach ($source_child as $p) {
// Convert SimpleXMLElement to DOMElement
$sourceImport = dom_import_simplexml($p);
// Import the new node into the target document
$import = $targetImport->ownerDocument->importNode($sourceImport, true);
// Add the new node to the correct part of the target
$targetImport->appendChild($import);
}
}

SimpleXml PHP addchild before any child

It looks like you want to prepend to your container. Unfortunately simplexml doesn't have this function natively, but this previous answer will assist you in getting it working

SimpleXML how to prepend a child in a node?

Add new child node with php simplexml on top of file

Be aware that SimpleXML is a very simple implementation of a XML API in PHP.

So, there's no SimpleXML function that directly achieves what you want. But: You can use a different approach of building your XML structure:

<?php

$newXml = simplexml_load_string('<?xml version="1.0" encoding="utf-8"?><News></News>');

$entry = $newXml->addChild('NewsModel');
$entry->addChild('ID', $_POST['inputIDNumber']);
$entry->addChild('Headline', $_POST['inputHeadline']);
$entry->addChild('ShortDescription', $_POST['inputShorDesc']);
$entry->addChild('Description', $_POST['inputDesc']);
$entry->addChild('LinkText', $_POST['inputLinkText']);
$entry->addChild('Link', $_POST['inputLink']);

$xml = simplexml_load_file($xmlurl) or die("Kann keine Verbindung zu $xmlurl aufbauen");

foreach ($xml as $child) {
$entry = $newXml->addChild('NewsModel');
$entry->addChild('ID', $child->ID);
$entry->addChild('Headline', $child->Headline);
$entry->addChild('ShortDescription', $child->ShortDescription);
$entry->addChild('Description', $child->Description);
$entry->addChild('LinkText', $child->LinkText);
$entry->addChild('Link', $child->Link);
}
file_put_contents($xmlurl, $newXml->asXML(), 0, stream_context_create(['ftp' => ['overwrite' => true]]));

You start by creating a new XML structure and adding the new NewsModel entry to it. After that you import the existing NewsModels.

In SimpleXML, how can I add an existing SimpleXMLElement as a child element?

I know this isn't the most helpful answer, but especially since you're creating/modifying XML, I'd switch over to using the DOM functions. SimpleXML's good for accessing simple documents, but pretty poor at changing them.

If SimpleXML is treating you kindly in all other places and you want to stick with it, you still have the option of jumping over to the DOM functions temporarily to perform what you need to and then jump back again, using dom_import_simplexml() and simplexml_import_dom(). I'm not sure how efficient this is, but it might help you out.

Insert XML structure as a child of another XML Element using PHP

You can't with SimpleXML, but if you really need manipulate your DOM or create it from scratch consider DOMDocument.

$xmlObject   = new \DOMDocument();
$xml = $xmlObject->createElement('root');
$xml_a = $xmlObject->createElement('parent');
$xml_b = $xmlObject->createElement('child');
$xml_b->setAttribute('attribute','value');
$xml_b->appendChild(new \DOMElement('item', 'itemValue'));
$xml_a->appendChild($xml_b);
$xml->appendChild($xml_a);
$xmlObject->appendChild($xml);
echo $xmlObject->saveXML();

PHP SimpleXML: insert node at certain position

The following is a function to insert a new SimpleXMLElement after some other SimpleXMLElement. Since this isn't directly possible with SimpleXML, it uses some DOM classes/methods behind-the-scenes to get the job done.

function simplexml_insert_after(SimpleXMLElement $insert, SimpleXMLElement $target)
{
$target_dom = dom_import_simplexml($target);
$insert_dom = $target_dom->ownerDocument->importNode(dom_import_simplexml($insert), true);
if ($target_dom->nextSibling) {
return $target_dom->parentNode->insertBefore($insert_dom, $target_dom->nextSibling);
} else {
return $target_dom->parentNode->appendChild($insert_dom);
}
}

And an example of how it might be used (specific to your question):

$sxe = new SimpleXMLElement('<root><nodeA/><nodeA/><nodeA/><nodeC/><nodeC/><nodeC/></root>');
// New element to be inserted
$insert = new SimpleXMLElement("<nodeB/>");
// Get the last nodeA element
$target = current($sxe->xpath('//nodeA[last()]'));
// Insert the new element after the last nodeA
simplexml_insert_after($insert, $target);
// Peek at the new XML
echo $sxe->asXML();

If you want/need an explanation of how this works (the code is fairly simple but might include foreign concepts), just ask.

SimpleXML: append one tree to another

You can't add a "tree" directly using SimpleXML, as you have seen. However, you can use some DOM methods to do the heavy lifting for you whilst still working on the same underlying XML.

$xmldict = new SimpleXMLElement('<dictionary><a/><b/><c/></dictionary>');
$kitty = new SimpleXMLElement('<cat><sound>meow</sound><texture>fuzzy</texture></cat>');

// Create new DOMElements from the two SimpleXMLElements
$domdict = dom_import_simplexml($xmldict->c);
$domcat = dom_import_simplexml($kitty);

// Import the <cat> into the dictionary document
$domcat = $domdict->ownerDocument->importNode($domcat, TRUE);

// Append the <cat> to <c> in the dictionary
$domdict->appendChild($domcat);

// We can still use SimpleXML! (meow)
echo $xmldict->c->cat->sound;

Prepending raw XML using PHP's SimpleXML

I'm really not sure if that will work. Try this or downvote this, but I hope it helps. Using DOMDocument (Reference)

<?php
$xml = new DOMDocument();
$xml->loadHTML($yourOriginalXML);
$newNode = DOMDocument::createElement($someXMLtoPrepend);
$nodeRoot = $xml->getElementsByTagName('root')->item(0);
$nodeOriginal = $xml->getElementsByTagName('people')->item(0);
$nodeRoot->insertBefore($newNode,$nodeOriginal);

$finalXmlAsString = $xml->saveXML();
?>

Sometimes UTF-8 can make problems, then try this:

<?php
$xml = new DOMDocument();
$xml->loadHTML(mb_convert_encoding($yourOriginalXML, 'HTML-ENTITIES', 'UTF-8'));
$newNode = DOMDocument::createElement(mb_convert_encoding($someXMLtoPrepend, 'HTML-ENTITIES', 'UTF-8'));
$nodeRoot = $xml->getElementsByTagName('root')->item(0);
$nodeOriginal = $xml->getElementsByTagName('people')->item(0);
$nodeRoot->insertBefore($newNode,$nodeOriginal);

$finalXmlAsString = $xml->saveXML();
?>

Add child to xml with PHP simpleXml

then, you should not create new items node:

$xml = simplexml_load_file("myxml.xml");
$sxe = new SimpleXMLElement($xml->asXML());
$itemsNode = $sxe->items[0];
$itemsNode->addChild("item", $newValue);
$sxe->asXML("myxml.xml");


Related Topics



Leave a reply



Submit