PHP SimpleXML: insertar nodo en cierta posición

decir que tengo XML:

        

¿Cómo inserto “nodeB” entre As y Cs? En PHP, preferiblemente a través de SimpleXML? Me gusta:

          

Solutions Collecting From Web of "PHP SimpleXML: insertar nodo en cierta posición"

La siguiente es una función para insertar un nuevo SimpleXMLElement después de otro SimpleXMLElement. Dado que esto no es posible directamente con SimpleXML, utiliza algunas clases / métodos DOM detrás del escenario para realizar el trabajo.

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

Y un ejemplo de cómo podría usarse (específico para su pregunta):

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

Si quiere / necesita una explicación de cómo funciona esto (el código es bastante simple pero puede incluir conceptos extraños), solo pregunte.

La respuesta de Salathe me ayudó, pero desde que usé el método addChild de SimpleXMLElement, busqué una solución para hacer que la inserción de niños como primer hijo sea más transparente. La solución es tomar esa funcionalidad basada en DOM y ocultarla en una subclase de 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; } } 

Después de todo, SimpleXML permite especificar qué clase de elemento usar:

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

Ahora puede llamar a insertChildFirst en cualquier elemento para insertar el nuevo hijo como primer hijo. El método devuelve el nuevo elemento como un elemento SimpleXML, por lo que su uso es similar a addChild. Por supuesto, sería fácilmente posible crear un método insertChild que permita especificar un elemento exacto para insertar el elemento antes, pero como no lo necesito ahora, decidí no hacerlo.