Organizational Research By

Surprising Reserch Topic

php simplexml insert node at certain position


php simplexml insert node at certain position  using -'php,xml,simplexml'

say I have XML:

<root>
  <nodeA />
  <nodeA />
  <nodeA />
  <nodeC />
  <nodeC />
  <nodeC />
</root>


How do I insert "nodeB" between As and Cs? In PHP, preferably via SimpleXML? Like:

<root>
  <nodeA />
  <nodeA />
  <nodeA />
  <nodeB />
  <nodeC />
  <nodeC />
  <nodeC />
</root>

    

asked Oct 11, 2015 by amit_cmps
0 votes
5 views



Related Hot Questions

2 Answers

0 votes

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('');
// New element to be inserted
$insert = new SimpleXMLElement("");
// 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.

answered Oct 11, 2015 by suyesh.lokhande
0 votes

Salathe's answer did help me, but since I used the addChild method of SimpleXMLElement, I sought a solution to make inserting children as a first child more transparent. The solution is to take that DOM based functionality and hide it in a subclass of SimpleXMLElement:

class SimpleXMLElementEx extends SimpleXMLElement
{
    public function insertChildFirst($name, $value, $namespace)
    {
        // Convert ourselves to DOM.
        $targetDom = dom_import_simplexml($this);
        // Check for children
        $hasChildren = $targetDom->hasChildNodes();

        // Create the new childnode.
        $newNode = $this->addChild($name, $value, $namespace);

        // Put in the first position.
        if ($hasChildren)
        {
            $newNodeDom = $targetDom->ownerDocument->importNode(dom_import_simplexml($newNode), true);
            $targetDom->insertBefore($newNodeDom, $targetDom->firstChild);
        }

        // Return the new node.
        return $newNode;
    }
}

After all, SimpleXML allows to specify which element class to use:

$xml = simplexml_load_file($inputFile, 'SimpleXMLElementEx');

Now you can call insertChildFirst on any element to insert the new child as a first child. The method returns the new element as an SimpleXML element, so it's use is similar to addChild. Of course it would be easily possible to create an insertChild method that allows to specify an exact element to insert the item before, but since I don't need that right now, I decided not to.

answered Oct 11, 2015 by vimaldas2005

...