DOMNode 类

(PHP 5, PHP 7, PHP 8)

类概述

class DOMNode {
/* 属性 */
public readonly string $nodeName;
public readonly int $nodeType;
public readonly ?DOMNode $parentNode;
public readonly ?DOMElement $parentElement;
public readonly DOMNodeList $childNodes;
public readonly ?DOMNode $firstChild;
public readonly ?DOMNode $lastChild;
public readonly ?DOMNode $previousSibling;
public readonly ?DOMNode $nextSibling;
public readonly ?DOMNamedNodeMap $attributes;
public readonly bool $isConnected;
public readonly ?DOMDocument $ownerDocument;
public readonly ?string $namespaceURI;
public string $prefix;
public readonly ?string $localName;
public readonly ?string $baseURI;
/* 方法 */
public C14N(
    bool $exclusive = false,
    bool $withComments = false,
    ?array $xpath = null,
    ?array $nsPrefixes = null
): string|false
public C14NFile(
    string $uri,
    bool $exclusive = false,
    bool $withComments = false,
    ?array $xpath = null,
    ?array $nsPrefixes = null
): int|false
public cloneNode(bool $deep = false): DOMNode|false
public getLineNo(): int
public getRootNode(?array $options = null): DOMNode
public insertBefore(DOMNode $node, ?DOMNode $child = null): DOMNode|false
public isDefaultNamespace(string $namespace): bool
public isEqualNode(?DOMNode $otherNode): bool
public isSameNode(DOMNode $otherNode): bool
public isSupported(string $feature, string $version): bool
public lookupPrefix(string $namespace): ?string
public normalize(): void
public replaceChild(DOMNode $node, DOMNode $child): DOMNode|false
}

属性

nodeName

返回当前节点类型的最准确名称

nodeValue

此节点的值,取决于其类型。与 W3C 规范相反,DOMElement 节点的节点值等于 DOMNode::textContent 而不是 null

nodeType

获取节点的类型。一个预定义的 XML_xxx_NODE 常量

parentNode

此节点的父节点。如果没有这样的节点,则返回 null

parentElement

此元素的父元素。如果没有这样的元素,则返回 null

childNodes

一个包含此节点所有子节点的 DOMNodeList。如果没有子节点,则为空 DOMNodeList

firstChild

此节点的第一个子节点。如果没有这样的节点,则返回 null

lastChild

此节点的最后一个子节点。如果没有这样的节点,则返回 null

previousSibling

紧接此节点之前的节点。如果没有这样的节点,则返回 null

nextSibling

紧接此节点之后的节点。如果没有这样的节点,则返回 null

attributes

一个包含此节点属性的 DOMNamedNodeMap(如果它是 DOMElement)或者 null

isConnected

节点是否连接到文档

ownerDocument

与此节点关联的 DOMDocument 对象,或者 null(如果此节点是 DOMDocument

namespaceURI

此节点的命名空间 URI,或者 null(如果未指定)。

prefix

此节点的命名空间前缀。

localName

返回此节点限定名的局部部分。

baseURI

此节点的绝对基本 URI 或者 null(如果实现无法获取绝对 URI)。

textContent

此节点及其后代的文本内容。

变更日志

版本 描述
8.3.0 添加了属性 DOMNode::$parentElementDOMNode::$isConnected
8.0.0 删除了未实现的方法 DOMNode::compareDocumentPosition()DOMNode::isEqualNode()DOMNode::getFeature()DOMNode::setUserData()DOMNode::getUserData()

注释

注意:

DOM 扩展使用 UTF-8 编码。使用 mb_convert_encoding()UConverter::transcode()iconv() 处理其他编码。

目录

添加注释

用户贡献的注释 14 个注释

marc at ermshaus dot org
15 年前
我花了很长时间才找到 XML_*_NODE 常量的映射。因此,我认为将它粘贴在这里会很方便

1 XML_ELEMENT_NODE
2 XML_ATTRIBUTE_NODE
3 XML_TEXT_NODE
4 XML_CDATA_SECTION_NODE
5 XML_ENTITY_REFERENCE_NODE
6 XML_ENTITY_NODE
7 XML_PROCESSING_INSTRUCTION_NODE
8 XML_COMMENT_NODE
9 XML_DOCUMENT_NODE
10 XML_DOCUMENT_TYPE_NODE
11 XML_DOCUMENT_FRAGMENT_NODE
12 XML_NOTATION_NODE
David Rekowski
14 年前
你不能简单地覆盖 $textContent 来替换 DOMNode 的文本内容,因为缺少只读标志。相反,你必须做类似这样的事情

<?php

$node
->removeChild($node->firstChild);
$node->appendChild(new DOMText('new text content'));

?>

此示例显示了会发生什么

<?php

$doc
= DOMDocument::loadXML('<node>old content</node>');
$node = $doc->getElementsByTagName('node')->item(0);
echo
"Content 1: ".$node->textContent."\n";

$node->textContent = 'new content';
echo
"Content 2: ".$node->textContent."\n";

$newText = new DOMText('new content');

$node->appendChild($newText);
echo
"Content 3: ".$node->textContent."\n";

$node->removeChild($node->firstChild);
$node->appendChild($newText);
echo
"Content 4: ".$node->textContent."\n";

?>

输出为

Content 1: old content // 初始内容
Content 2: old content // 尝试通过覆盖 $node->textContent 来替换
Content 3: old contentnew content // 仅将新的文本节点附加
Content 4: new content // 在附加新的文本节点之前移除第一个子节点

如果你想要 CDATA 部分,请使用以下内容

<?php
$doc
= DOMDocument::loadXML('<node>old content</node>');
$node = $doc->getElementsByTagName('node')->item(0);
$node->removeChild($node->firstChild);
$newText = $doc->createCDATASection('new cdata content');
$node->appendChild($newText);
echo
"Content withCDATA: ".$doc->saveXML($node)."\n";
?>
R. Studer
14 年前
澄清一下
先前发布者“发现”的,看似没有文档记录的方法(.getElementsByTagName 和 .getAttribute),实际上是 DOMElement 类的方法,该类继承自 DOMNode。

参见:https://php.net/manual/en/class.domelement.php
Steve K
14 年前
这个类似乎也有 getElementsByTagName 方法。

我通过使用 is_a() 函数评估 DOMNodeList->item() 的输出结果来确认这一点。
brian wildwoodassociates.info
15 年前
这个类有一个 getAttribute 方法。

假设 DOMNode 对象 $ref 包含从 DOMNode 列表中提取的锚点,那么

$url = $ref->getAttribute('href');

将分离与锚点 href 部分关联的 url。
alastair dot dallas at gmail dot com
12 年前
关于混合内容的问题,我需要进行一些实验才能记住,所以我写下这个笔记,希望能够为其他人节省时间。

当你的标记像这样:<div><p>First text.</p><ul><li><p>First bullet</p></li></ul></div> 时,你将获得非常规范的 XML_ELEMENT_NODEs。<div> 的子节点是 <p> 和 <ul>,两个 <p> 的 nodeValue 都将产生你期望的文本。

但当你的标记更像是 <p>This is <b>bold</b> and this is <i>italic</i>.</p> 时,你就会意识到 XML_ELEMENT_NODEs 的 nodeValue 并不可靠。在这种情况下,你需要查看 <p> 的子节点。在这个例子中,<p> 的子节点是:#text、<b>、#text、<i>、#text。

在这个例子中,<b> 和 <i> 的 nodeValue 与它们的 #text 子节点相同。但你的标记可能是这样的:<p>This <b>is bold and <i>bold italic</i></b>, you see?</p>。在这种情况下,你需要查看 <b> 的子节点,它们将是 #text、<i>,因为 <b> 的 nodeValue 不足以满足需求。

XML_TEXT_NODEs 没有子节点,始终命名为 "#text"。根据空白的处理方式,你的树可能在 <body> 以及其他地方拥有“空”的 #text 节点作为子节点。

属性是节点,但我忘记了它们并不在 childNodes 表达的树中。使用 childNodes 遍历整棵树不会访问任何属性节点。
imranomar at gmail dot com
13 年前
刚刚发现 node->nodeValue 会去除所有标签。
metanull
10 年前
另一个 DOMNode 到 php 数组的转换函数。
页面上的其他函数会生成过于“复杂”的数组;这个函数应该尽可能保持数组的整洁。
注意:在调用 DOMDocument::load、loadXML 或 loadHTML 时,请确保设置 LIBXML_NOBLANKS。
参见:http://be2.php.net/manual/en/libxml.constants.php
参见:http://be2.php.net/manual/en/domdocument.loadxml.php

<?php
/**
* 返回 DOMNode 的数组表示形式
* 注意,在将 XML 加载到 DOMDocument 时,请确保使用 LIBXML_NOBLANKS 标志
* @param DOMDocument $dom
* @param DOMNode $node
* @return array
*/
function nodeToArray( $dom, $node) {
if(!
is_a( $dom, 'DOMDocument' ) || !is_a( $node, 'DOMNode' )) {
return
false;
}
$array = false;
if( empty(
trim( $node->localName ))) {// 丢弃空节点
return false;
}
if(
XML_TEXT_NODE == $node->nodeType ) {
return
$node->nodeValue;
}
foreach (
$node->attributes as $attr) {
$array['@'.$attr->localName] = $attr->nodeValue;
}
foreach (
$node->childNodes as $childNode) {
if (
1 == $childNode->childNodes->length && XML_TEXT_NODE == $childNode->firstChild->nodeType ) {
$array[$childNode->localName] = $childNode->nodeValue;
} else {
if(
false !== ($a = self::nodeToArray( $dom, $childNode))) {
$array[$childNode->localName] = $a;
}
}
}
return
$array;
}
?>
pizarropablo at gmail dot com
10 年前
回复:alastair dot dallas at gmail dot com 关于 "#text" 节点。
"#text" 节点出现在结束标签和下一个起始标签之间存在空格或换行符时。

例如 "<data><age>10</age>[SPACES]<other>20</other>[SPACES]</data>"

"data" 的 childNodes 有 4 个子节点
- age = 10
- #text = 空格
- other = 20
- #text = 空格
matt at lamplightdb dot co dot uk
15 年前
显然,它还有 setAttribute 方法。

$node->setAttribute( 'attrName' , 'value' );
matej dot golian at gmail dot com
10 年前
这是一个用于将 DomNode 截断到指定文本字符数的小函数。我用它来为我的博客文章生成 HTML 片段。

<?php

function makehtmlexcerpt(DomNode $html, $excerptlength)
{
$remove = 0;
$htmllength = strlen(html_entity_decode($html->textContent, ENT_QUOTES, 'UTF-8'));
$truncate = $htmllength - $excerptlength;
if(
$htmllength > $excerptlength)
{
if(
$html->hasChildNodes())
{
$children = $html->childNodes;
for(
$counter = 0; $counter < $children->length; $counter ++)
{
$child = $children->item($children->length - ($counter + 1));
$childlength = strlen(html_entity_decode($child->textContent, ENT_QUOTES, 'UTF-8'));
if(
$childlength <= $truncate)
{
$remove ++;
$truncate = $truncate - $childlength;
}
else
{
$child = makehtmlexcerpt($child, $childlength - $truncate);
break;
}
}
if(
$remove != 0)
{
for(
$counter = 0; $counter < $remove; $counter ++)
{
$html->removeChild($html->lastChild);
}
}
}
else
{
if(
$html->nodeName == '#text')
{
$html->nodeValue = substr(html_entity_decode($html->nodeValue, ENT_QUOTES, 'UTF-8'), 0, $htmllength - $truncate);
}
}
}
return
$html;
}

?>
匿名
6 年前
如果具体属性的文档提到某些属性的只读状态,将会有所帮助
"
ownerDocument

与该节点关联的 DOMDocument 对象。

"
zlk1214 at gmail dot com
8 年前
一个可以在不编码错误的情况下设置内部 HTML 的函数。$html 可以是断开的 内容,例如“<a ID=id20>ssss”
function setInnerHTML($node, $html) {
removeChildren($node);
if (empty($html)) {
return;
}

$doc = $node->ownerDocument;
$htmlclip = new DOMDocument();
$htmlclip->loadHTML('<meta http-equiv="Content-Type" content="text/html;charset=utf-8"><div>' . $html . '</div>');
$clipNode = $doc->importNode($htmlclip->documentElement->lastChild->firstChild, true);
while ($item = $clipNode->firstChild) {
$node->appendChild($item);
}
}
I. Cook
14 年前
有关 XML DOM 节点类型的更多信息,请参阅 https://w3schools.org.cn/dom/dom_nodetype.asp

(使用 PHP DOMNode 时,这些常量需要以“XML_”为前缀)
To Top