如何只改变一个DOM节点的根标记的名称?
在DOM的文档模型中,我们无法更改的属性documentElement
一个的DOMElement
对象,所以,我们需要“重建”的节点......但如何“重建”用childNodes
属性?
注:我可以做到这一点转换为字符串saveXML和正则表达式cuting根 ...但它是一种解决方法,而不是一个DOM的解决方案。
试过,但没有作品,PHP实例
PHP例子(没有作品,但为什么呢?):
尝试-1
// DOMElement::documentElement can not be changed, so...
function DomElement_renameRoot1($ele,$ROOTAG='newRoot') {
if (gettype($ele)=='object' && $ele->nodeType==XML_ELEMENT_NODE) {
$doc = new DOMDocument();
$eaux = $doc->createElement($ROOTAG); // DOMElement
foreach ($ele->childNodes as $node)
if ($node->nodeType == 1) // DOMElement
$eaux->appendChild($node); // error!
elseif ($node->nodeType == 3) // DOMText
$eaux->appendChild($node); // error!
return $eaux;
} else
die("ERROR: invalid DOM object as input");
}
在appendChild($node)
导致错误:
Fatal error: Uncaught exception 'DOMException'
with message 'Wrong Document Error'
尝试-2
从@can建议(只指向链接),我可怜的解释DOM-DOM文档-renamenode手册 。
function DomElement_renameRoot2($ele,$ROOTAG='newRoot') {
$ele->ownerDocument->renameNode($ele,null,"h1");
return $ele;
}
所述renameNode()方法导致了错误,
Warning: DOMDocument::renameNode(): Not yet implemented
尝试-3
从PHP手册中,评论1 。
function renameNode(DOMElement $node, $newName)
{
$newNode = $node->ownerDocument->createElement($newName);
foreach ($node->attributes as $attribute)
$newNode->setAttribute($attribute->nodeName, $attribute->nodeValue);
while ($node->firstChild)
$newNode->appendChild($node->firstChild); // changes firstChild to next!?
$node->ownerDocument->replaceChild($newNode, $node); // changes $node?
// not need return $newNode;
}
所述的replaceChild()方法导致了错误,
Fatal error: Uncaught exception 'DOMException' with message 'Not Found Error'
Answer 1:
由于这还没有被真正回答的是,你得到一个关于没有找到错误信息是因为一个小错误的renameNode()
您复制功能。
在有关在DOM重命名不同的元素一个有点相关的问题我已经看到了这个问题,以及和使用的收养我的回答是功能不具有这样的错误:
/**
* Renames a node in a DOM Document.
*
* @param DOMElement $node
* @param string $name
*
* @return DOMNode
*/
function dom_rename_element(DOMElement $node, $name) {
$renamed = $node->ownerDocument->createElement($name);
foreach ($node->attributes as $attribute) {
$renamed->setAttribute($attribute->nodeName, $attribute->nodeValue);
}
while ($node->firstChild) {
$renamed->appendChild($node->firstChild);
}
return $node->parentNode->replaceChild($renamed, $node);
}
你可能会在函数体的最后一行都看上了它:这是使用->parentNode
代替->ownerDocument
。 作为$node
不是文档的一个孩子,是你得到的错误。 而且这也是一个错误的假设,它应该是。 而是使用父元素来搜索孩子在那里来取代它;)
这不是在PHP手册usernotes列出了到目前为止,但是,如果你没有按照链接到博客,帖子最初建议的renameNode()
你可以在下面找到它提供这种解决方案,以及评论功能。
无论如何,我的变种这里使用一个稍微不同的变量命名,更鲜明关于类型。 就像在PHP手册的例子也错过与命名空间节点交易的变种。 我没有预订什么是最好的,例如创建一个额外的功能和它打交道,接管命名空间从节点重命名或在不同的功能明确改变的命名空间。
Answer 2:
首先,你需要了解的是, DOMDocument
仅是文档树的层次根源。 它的名字总是#document
。 要重命名的根元素,它是$document->documentElement
。
如果要复制节点形成一个文档到另一个文档,你需要使用importNode()函数: $document->importNode($nodeInAnotherDocument)
编辑:
renameNode()
还没有实现,所以你应该让另一根,并简单地用旧替换它。 如果你使用DOMDocument->createElement()
你不需要使用importNode()
以后就可以了。
$oldRoot = $doc->documentElement;
$newRoot = $doc->createElement('new-root');
foreach ($oldRoot->attributes as $attr) {
$newRoot->setAttribute($attr->nodeName, $attr->nodeValue);
}
while ($oldRoot->firstChild) {
$newRoot->appendChild($oldRoot->firstChild);
}
$doc->replaceChild($newRoot, $oldRoot);
Answer 3:
这是我的“尝试-3”(见问题)的变化,并能正常工作 !
function xml_renameNode(DOMElement $node, $newName, $cpAttr=true) {
$newNode = $node->ownerDocument->createElement($newName);
if ($cpAttr && is_array($cpAttr)) {
foreach ($cpAttr as $k=>$v)
$newNode->setAttribute($k, $v);
} elseif ($cpAttr)
foreach ($node->attributes as $attribute)
$newNode->setAttribute($attribute->nodeName, $attribute->nodeValue);
while ($node->firstChild)
$newNode->appendChild($node->firstChild);
return $newNode;
}
当然,如果您展示如何使用DOM文档:: renameNode (没有错误!), 赏金去为您服务!
Answer 4:
ISTM在你的方法,你尝试从另一个 节点导入 DOMDocument
,所以你需要使用importNode()
方法:
$d = new DOMDocument();
/* Make a `foo` element the root element of $d */
$root = $d->createElement("foo");
$d->appendChild($root);
/* Append a `bar` element as the child element of the root of $d */
$child = $d->createElement("bar");
$root->appendChild($child);
/* New document */
$d2 = new DOMDocument();
/* Make a `baz` element the root element of $d2 */
$root2 = $d2->createElement("baz");
$d2->appendChild($root2);
/*
* Import a clone of $child (from $d) into $d2,
* with its child nodes imported recursively
*/
$child2 = $d2->importNode($child, true);
/* Add the clone as the child node of the root of $d2 */
$root2->appendChild($child2);
但是,它要容易得多子节点附加到新的父元素(从而使它们),并更换旧的根与父元素:
$d = new DOMDocument();
/* Make a `foo` element the root element of $d */
$root = $d->createElement("foo");
$d->appendChild($root);
/* Append a `bar` element as the child element of the root of $d */
$child = $d->createElement("bar");
$root->appendChild($child);
/* <?xml version="1.0"?>
<foo><bar/></foo> */
echo $d->saveXML();
$root2 = $d->createElement("baz");
/* Make the `bar` element the child element of `baz` */
$root2->appendChild($child);
/* Replace `foo` with `baz` */
$d->replaceChild($root2, $root);
/* <?xml version="1.0"?>
<baz><bar/></baz> */
echo $d->saveXML();
Answer 5:
我希望我不缺什么,但我碰巧有类似的问题,并能够通过使用来解决它DomDocument::replaceChild(...)
/* @var $doc DOMDocument */
$doc = DOMImplementation::createDocument(NULL, 'oldRoot');
/* @var $newRoot DomElement */
$newRoot = $doc->createElement('newRoot');
/* all the code to create the elements under $newRoot */
$doc->replaceChild($newRoot, $doc->documentElement);
$doc->documentElement->isSameNode($newRoot) === true;
什么扔我最初是$doc->documentElement
是只读的,但上面的工作,似乎是IF的更简单的解决$newRoot
用同样创建DomDocument
,否则你需要做的importNode
解决方案如上所述。 从你的问题是似乎是$newRoot
可以从同一创建$doc
。
让我们知道,如果这个摸索出适合你。 干杯。
编辑:在20031129版本注意到DomDocument::$formatOutput
,如果设置,不格式化$newRoot
当你终于打电话输出$doc->saveXML()
文章来源: How to change root of a node with DomDocument methods?