(PHP 5, PHP 7, PHP 8)
DOMNode::insertBefore — Добавляет новый дочерний узел перед указанным узлом
Данная функция вставляет новый узел перед указанным узлом. Чтобы вносить изменения в добавленный дочерний узел, необходимо использовать возвращаемый узел.
При использовании существующего узла он будет перемещён.
nodeНовый узел.
child
Контрольный узел. Если отсутствует, то node
добавляется в конец списка потомков.
Возвращает добавленный узел или false в случае возникновения ошибки.
Может выбросить исключение DOMException со следующими кодами ошибок:
DOM_NO_MODIFICATION_ALLOWED_ERR Возникает, если узел доступен только для чтения или предыдущий родитель вставляемого узла доступен только для чтения.
DOM_HIERARCHY_REQUEST_ERR
Возникает, если тип узла не поддерживает потомков типа,
который имеет узел node,
или же если добавляемый узел является предком целевого узла или им самим.
DOM_WRONG_DOCUMENT_ERR
Возникает, если node создан в другом документе,
отличном от того, в котором был создан этот узел.
DOM_NOT_FOUND_ERR
Возникает, если child не является дочерним узлом данного узла.
1st argument) a node to insert
2nd argument) a reference node - this is the node that the new node will be inserted before
The trick to using this method is that the OBJECT on which you actually CALL the insertBefore() method is actually the PARENT node of the reference node!
INCORRECT:
$DOMNode_refNode->insertBefore($DOMNode_newNode, $DOMNode_refNode);
CORRECT:
$DOMNode_refNode->parentNode->insertBefore($DOMNode_newNode, $DOMNode_refNode);Note that supplying the same node for $newnode and $refnode leads to an E_WARNING ("Couldn't add newnode as the previous sibling of refnode"). For example imagine one wanted to make $newnode the first child of its parent by doing:
<?php
$firstSibling = $newnode->parentNode->firstChild;
// Bad:
$newnode->parentNode->insertBefore( $newnode, $firstSibling );
?>
This would generate a warning if it already was the first child of its parent, since $newnode and $firstSibling are identical. Easy to work around though:
<?php
$firstSibling = $newnode->parentNode->firstChild;
// Better:
if( $newnode !== $firstSibling ) {
$newnode->parentNode->insertBefore( $newnode, $firstSibling );
}
?>example to insert <newnode/> between <chid1/> and <child2/>
<?xml version="1.0" encoding="ISO-8859-1" ?>
<root>
<parent>
<child nr="1"/>
<child nr="2"/>
</parent>
</root>
<?php
$xml_src = 'test.xml';
// XPath-Querys
$parent_path = "//parent";
$next_path = "//parent/child[@nr='2']";
// Create a new DOM document
$dom = new DomDocument();
$dom->load($xml_src);
// Find the parent node
$xpath = new DomXPath($dom);
// Find parent node
$parent = $xpath->query($parent_path);
// new node will be inserted before this node
$next = $xpath->query($next_path);
// Create the new element
$element = $dom->createElement('newnode');
// Insert the new element
$parent->item(0)->insertBefore($element, $next->item(0));
echo $dom->saveXML();
?>Sorry, my previous posting worked only for the top node. Here the corrected version, which will work for any node:
XML
----
<?xml version="1.0"?>
<contacts>
<person>Adam</person>
<person>Eva</person>
<person>Thomas</person>
</contacts>
PHP
---
<?php
// load XML, create XPath object
$xml = new DomDocument();
$xml->preserveWhitespace = false;
$xml->load('contacts.xml');
$xpath = new DOMXPath($xml);
// get node eva, which we will append to
$eva = $xpath->query('/contacts/person[.="Eva"]')->item(0);
// create node john
$john = $xml->createElement('person', 'John');
// insert john after eva
// "in eva's parent node (=contacts) insert
// john before eva's next node"
// this also works if eva would be the last node
$eva->parentNode->insertBefore($john, $eva->nextSibling);
// show result
header('Content-Type: text/plain');
print $xml->saveXML();
?>
Result
------
<?xml version="1.0"?>
<contacts>
<person>Adam</person>
<person>Eva</person><person>John</person>
<person>Thomas</person>
</contacts>