I wrote a function for me to handle several insert modes (including insertAfter)
<?php
public function myInsertNode($newNode, $refNode, $insertMode=null) {
if(!$insertMode || $insertMode == "inside") {
$refNode->appendChild($newNode);
} else if($insertMode == "before") {
$refNode->parentNode->insertBefore($newNode, $refNode);
} else if($insertMode == "after") {
if($refNode->nextSibling) {
$refNode->parentNode->insertBefore($newNode, $refNode->nextSibling);
} else {
$refNode->parentNode->appendChild($newNode);
}
}
}
?>
DOMNode::insertBefore
(PHP 5)
DOMNode::insertBefore — 参照しているノードの前に新しい子を追加する
説明
この関数は、参照しているノードの直前に新しいノードを挿入します。 追加するノードに対して変更を加えたい場合は、この関数から返される ノードを使用します。
パラメータ
- newnode
-
新しいノード。
- refnode
-
参照ノード。指定されなかった場合は、newnode が子要素として追加されます。
返り値
挿入されたノードを返します。
エラー / 例外
- DOM_NO_MODIFICATION_ALLOWED_ERR
-
このノードが読み込み専用であったり、挿入されるノードの以前の親が 読み込み専用であった場合に発生します。
- DOM_HIERARCHY_REQUEST_ERR
-
newnode で指定した型の子ノードを 保持することが許可されていない場合、あるいは追加しようとしている ノードが自分自身やその祖先であった場合に発生します。
- DOM_WRONG_DOCUMENT_ERR
-
newnode が、このノードとは別の ドキュメントで作成されたものである場合に発生します。
- DOM_NOT_FOUND
-
refnode がこのノードの子ではない場合に 発生します。
felixsigl at gmail dot com
12-May-2009 12:17
naholyr at yahoo dot fr
08-Feb-2009 12:52
A very usual needed function is "appendSibling" to insert a node just before another one :
<?php
/**
* @param DOMNode $newnode Node to insert next to $ref
* @param DOMNode $ref Reference node
* @requires $ref has a parent node
* @return DOMNode the real node inserted
*/
function appendSibling(DOMNode $newnode, DOMNode $ref)
{
if ($ref->nextSibling) {
// $ref has an immediate brother : insert newnode before this one
return $ref->parentNode->insertBefore($newnode, $ref->nextSibling);
} else {
// $ref has no brother next to him : insert newnode as last child of his parent
return $ref->parentNode->appendChild($newnode);
}
}
?>
odonnell dot NOSPAM at ideaengineinc dot com
06-May-2008 10:57
Here's a usage example.
If you try this, you'll get an error message.
$refNode->insertBefore($newNode, $refNode);
Try this instead...
$refNode->parentNode->insertBefore($newNode, $refNode);
DrTebi at Yahoo
03-Oct-2007 02:54
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>
justin at redwiredesign dot com
07-Feb-2007 05:20
The previous example is incorrect, and causes a DOM_NOT_FOUND error, as the child nodes are not direct descendants of the root node.
Therefore, the line:
$parent_path = "/root";
needs to change to:
$parent_path = "/root/parent";
or
$parent_path = "//parent";
for this example to work
25-Aug-2005 08:34
moving an existing node within the DomDocument:
<root>
<parent>
<child><name>Bob</name></child>
<child><name>Sue</name></child>
</parent>
</root>
$dom = new DomDocument();
$dom->load("sample.xml");
$parent_path = "/root";
$query = "//child[position() = 2]";
$query2 = "//child[position() = 1]";
$xpath = new DomXPath($dom);
$parent = $xpath->query($parent_path);
$under = $xpath->query($query);
$above = $xpath->query($query2);
$parent->item(0)->insertBefore($under->item(0), $above->item(0));
$dom->save("sample.xml");
Should produce:
<root>
<parent>
<child><name>Sue</name></child>
<child><name>Bob</name></child>
</parent>
</root>
jg at handcode dot de
18-Aug-2005 09:18
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();
?>
Jerry Ellis
03-Jun-2005 09:45
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);
