DOMDocument::importNode

(PHP 5, PHP 7, PHP 8)

DOMDocument::importNode将节点导入当前文档

描述

public DOMDocument::importNode(DOMNode $node, bool $deep = false): DOMNode|false

此函数返回要导入的节点的副本,并将其与当前文档相关联。

参数

node

要导入的节点。

deep

如果设置为 true,此方法将递归地导入 node 下的子树。

注意:

要复制节点的属性,deep 需要设置为 true

返回值

复制的节点或 false,如果无法复制。

错误/异常

DOMException 如果无法导入节点,则抛出异常。

范例

示例 #1 DOMDocument::importNode() 示例

在文档之间复制节点。

<?php

$orgdoc
= new DOMDocument;
$orgdoc->loadXML("<root><element><child>text in child</child></element></root>");

// 我们想要导入到新文档的节点
$node = $orgdoc->getElementsByTagName("element")->item(0);


// 创建一个新文档
$newdoc = new DOMDocument;
$newdoc->formatOutput = true;

// 添加一些标记
$newdoc->loadXML("<root><someelement>text in some element</someelement></root>");

echo
"The 'new document' before copying nodes into it:\n";
echo
$newdoc->saveXML();

// 将节点及其所有子节点导入到文档中
$node = $newdoc->importNode($node, true);
// 然后将其追加到 "<root>" 节点
$newdoc->documentElement->appendChild($node);

echo
"\nThe 'new document' after copying the nodes into it:\n";
echo
$newdoc->saveXML();
?>

上面的示例将输出

The 'new document' before copying nodes into it:
<?xml version="1.0"?>
<root>
  <someelement>text in some element</someelement>
</root>

The 'new document' after copying the nodes into it:
<?xml version="1.0"?>
<root>
  <someelement>text in some element</someelement>
  <element>
    <child>text in child</child>
  </element>
</root>

添加注释

用户贡献注释 11 个注释

5
rikdnua at mail dot ru
10 年前
importNode($node, false) 的行为在 PHP 5.2.9-2 和 PHP 5.2.17 中有所不同。
第二个选项显式设置为 false。在 PHP 5.2.9-2 中,importNode() 导入元素时不包含属性。在 PHP 5.2.17 中,导入元素时包含它们的属性。
<?php
$xml
="
<html>
<a href='yandex.com'>Yandex.com</a>
<a href='rik.dn.ua'>RiK.dn.ua</a>
</html>
"
;
$doc=new domDocument('1.0');
$doc->loadXML($xml);
$list=$doc->getElementsByTagName('a');
$doc1=new domDocument('1.0');
$doc1->formatOutput=true;
for(
$i=0; $i<$list->length; $i++) $doc1->appendChild($doc1->importNode($list->item($i), false));
$doc1->save('file.xml');
?>

file.xml PHP 5.2.9-2
<?xml version="1.0"?>
<a/>
<a/>

file.xml PHP 5.2.17
<?xml version="1.0"?>
<a href="yandex.com"/>
<a href="rik.dn.ua"/>
3
mailme at sove dot nl
16 年前
DOMDocument->importNode 且第二个参数为 false 将保留属性。要解决此问题,

$__DOM->importNode
(
$__INPUT->cloneNode(false), true
);

$__DOM(DOMDocument)将导入 $__INPUT 节点(DOMElement)包括属性。
3
c dot 1 at smithies dot org
14 年前
假设 $source 和 $dest 是 DOMDocument 的实例。假设 $sourcedoc 包含一个 ID 为 'sourceID' 的元素,而 $destdoc 包含一个 ID 为 'destID' 的元素。假设我们已经设置了源元素和目标元素变量,如下所示

<?php
$src
= $sourcedoc->getElementById('sourceID');
$dst = $destdoc->getElementById('destID');
?>

最后,假设 $sel 有多个子节点。

为了将 $src 的子元素作为 $dst 的子元素导入,您可以执行以下操作

<?php
$src
= $dest->importNode($src, TRUE);

foreach (
$src->childNodes as $el) $dst->appendChild($el);
?>

但这不起作用。foreach 会感到困惑,因为(如下所述)将导入的元素追加到同一文档中的另一个现有元素会导致它从其当前父元素中删除。

因此,应使用以下技术

<?php
foreach ($src->childNodes as $el) $dst->appendChild($destdoc->importNode($el, TRUE));
?>
3
Fitopaldi
19 年前
importNode 返回要导入的节点的副本并将其与当前文档关联,但不会将节点导入到当前 DOMDocument 中。使用 appendChild 将节点副本导入当前 DOMDocument 中。

<?
$domNode = $dom->importNode($aDomNode, true);
$currentDomDocument->appendChild($domNode);
?>
2
Colin
17 年前
从 PHP 5.1.6(使用 libxml 2.6.26 和 DOM/XML API 版本 20031129)开始,如果尝试从同一文档导入,importNode() 不会执行任何操作。这意味着,如果你执行 $ret = importNode,然后执行 appendChild($ret) 或 insertBefore($ret, ...),那么最终会*移动*节点,而不是最终得到副本。

如果你希望 importNode 为你提供源代码的副本(在本例中为深层副本),那么你必须考虑它们是否来自同一文档。此函数解决了这个问题

<?
// 将 $b 导入到 $a 的文档中
function myimport($a, $b)
{
if ($a->ownerDocument->isSameNode($b->ownerDocument))
{
$temp = new DOMDocument();
$ret = $temp->importNode($b, TRUE);
return $a->ownerDocument->importNode($ret, TRUE);
}
else
{
return $a->ownerDocument->importNode($b, TRUE);
}
}
?>

(此函数是为该注释新编写的,但我将其基于我另一个可用的函数。)

此函数检查文档是否相同,并使用一个新文档(以这种方式保证不同)强制将副本复制到 $temp 中,然后强制将副本复制回 $a->ownerDocument 中。

显然,没有进行错误检查。
1
andy dot clark at dial dot pipex dot com
17 年前
importNode 的一个有用用法是将一个节点复制到另一个节点上。

function CopyXMLNode($SourceNode,$DestNode)
{
if ($SourceNode->nodeName != '#text')
{
// 复制此节点
$node = $DestNode->ownerDocument->importNode($SourceNode, true);
$node = $DestNode->appendChild($node);
// 现在复制子节点
foreach ($SourceNode->childNodes AS $item)
{
$this->CopyXMLNode($item,$node);
}
}
}
2
mark at 4inloop dot de
17 年前
当你省略第二个参数或输入 false 时,不仅子节点被省略。节点的属性也会被切断。
2
adjwilli
17 年前
使用 PHP 编辑 XML 可能很痛苦,因此这里有一个脚本可以通过 POST 用用户提供的节点替换 XML 节点。通常最好在运行此脚本之前对 $_POST['xml'] 进行验证检查并清理其他内容。

这个脚本基本上希望用户提供一个名为 $_POST['xml'] 的节点,以及要替换的原始文档中节点的 XPath,名为 $_POST['XPath']。它还从 $xml 加载原始 XML 文档。nodeRunner 函数从你正在编辑的文档的根节点和根元素的 XPath 开始(这些更多是为了使递归变得容易,而不是其他任何东西)。

$doc = new DOMDocument();
$doc->loadXML($xml); // $xml 期望一个 XML 字符串

function nodeRunner ($node,$xpath) {
global $doc;
if ($xpath == $_POST['XPath']) {

$xmlPost = new DOMDocument();
$xmlPost->loadXML($_POST['xml']);

$newNode = $doc->importNode($xmlPost->firstChild,true);

$node->parentNode->replaceChild($newNode,$node);
} else {

$page = 1;
$section = 1;

if ($node->hasChildNodes()) {
foreach ($node->childNodes as $nodling) {
$nodeName = $nodling->nodeName;
if ($nodeName == 'page' || $nodeName == 'section') {
nodeRunner ($nodling,$xpath."/".$nodeName."[".$$nodeName."]");
$$nodeName++;
}
}
}
}
}

nodeRunner ($doc->documentElement,"/root[1]"); // /root 应该是 XPath 中根元素的显式名称

$doc->saveXML();
1
p dot reisinger at gmail dot com
15 年前
方法(也可以用作函数)用于连接两个 xml 文件。第一个参数是父 xml(要插入的 xml),第二个是子 xml(要插入的 xml),第三个是可选参数,用于指定要插入子 xml 的父标签。如果没有指定,则子 xml 将作为最后一个元素插入,位于根元素结束之前。
<?php
protected function joinXML($parent, $child, $tag = null)
{
$DOMChild = new DOMDocument;
$DOMChild->loadXML($child);
$node = $DOMChild->documentElement;

$DOMParent = new DOMDocument;
$DOMParent->formatOutput = true;
$DOMParent->loadXML($parent);

$node = $DOMParent->importNode($node, true);

if (
$tag !== null) {
$tag = $DOMParent->getElementsByTagName($tag)->item(0);
$tag->appendChild($node);
} else {
$DOMParent->documentElement->appendChild($node);
}

return
$DOMParent->saveXML();
}
?>
1
p dot reisinger at gmail dot com
15 年前
当你使用下面的函数/方法时,php 会自动插入命名空间(如果你有一些)。如果你想完全连接 xml 文件,那么你可以只使用占位符并将 xml 视为字符串。
<?php
function joinXMLStrings($file1, $file2)
{
// 移除 xml 声明
$file2 = trim(preg_replace('/<\?xml.*\?>/', '', $file2, 1));

// 在第一个文件中的占位符位置插入 file2
$file1 = trim(preg_replace('/<\?file2\s\?>/', $file2, $file1, 1));
}
?>

所以函数看起来像这样,你插入两个 xml 文件。第一个文件必须包含占位符(你将在其中插入 file2)。在本例中,占位符将是 <?file2 ?>

!!! 这仅仅是为了说明 - 在使用之前进行测试
1
stomas
17 年前
我认为这应该做同样的事情

<?
// 将 $b 导入到 $a 的文档中
function myimport($a, $b)
{
if ($a->ownerDocument->isSameNode($b->ownerDocument))
{
return $b->cloneNode(TRUE);
}
else
{
return $a->ownerDocument->importNode($b, TRUE);
}
}
?>
To Top