DOMXPath 类

(PHP 5, PHP 7, PHP 8)

简介

支持 XPath 1.0

类概要

class DOMXPath {
/* 属性 */
public readonly DOMDocument $document;
/* 方法 */
public __construct(DOMDocument $document, bool $registerNodeNS = true)
public evaluate(string $expression, ?DOMNode $contextNode = null, bool $registerNodeNS = true): mixed
public query(string $expression, ?DOMNode $contextNode = null, bool $registerNodeNS = true): mixed
public registerNamespace(string $prefix, string $namespace): bool
}

属性

document

registerNodeNamespaces

当设置为 true 时,节点中的命名空间将被注册。

变更日志

版本 描述
8.0.0 添加了 registerNodeNamespaces 属性。

目录

添加备注

用户贡献的备注 6 个备注

Mark Omohundro, ajamyajax dot com
15 年前
<?php
// 要检索选定的 html 数据,请尝试以下 DomXPath 示例:

$file = $DOCUMENT_ROOT. "test.html";
$doc = new DOMDocument();
$doc->loadHTMLFile($file);

$xpath = new DOMXpath($doc);

// 示例 1:对于所有具有 id 的元素
//$elements = $xpath->query("//*[@id]");

// 示例 2:对于选定 id 中的节点数据
//$elements = $xpath->query("/html/body/div[@id='yourTagIdHere']");

// 示例 3:与上述相同,使用通配符
$elements = $xpath->query("*/div[@id='yourTagIdHere']");

if (!
is_null($elements)) {
foreach (
$elements as $element) {
echo
"<br/>[". $element->nodeName. "]";

$nodes = $element->childNodes;
foreach (
$nodes as $node) {
echo
$node->nodeValue. "\n";
}
}
}
?>
TechNyquist
4 年前
在处理 XML(作为严格格式)时,为 XPath 对象指定命名空间可能非常重要,以确保其正常工作。

我遇到过“query”始终返回空节点列表的情况,它无法找到任何东西。只有广泛的“//*”能够显示出根元素。

然后发现,在 XPath 对象中注册根元素的“xmlns”属性中报告的命名空间,并在元素名称附近编写该命名空间,可以使其正常工作。

因此,对于类似于以下内容的 XML(来自站点地图)

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>http://example.com/index.php</loc>
<lastmod>2005-01-01</lastmod>
<changefreq>monthly</changefreq>
<priority>0.5</priority>
</url>
</urlset>

我需要以下 XPath 配置

<?php

$doc
= new DOMDocument;
$doc->load("sitemap.xml");
$xpath = new DOMXPath($doc);
$xpath->registerNamespace('ns', 'http://www.sitemaps.org/schemas/sitemap/0.9');
$nodes = $xpath->query('//ns:urlset/ns:url');

?>

当然,该“xmlns”也可以从根元素的属性中动态提供。
peter at softcoded dot com
7 年前
你可能并不总是在运行时知道你的文件是否拥有
是否存在命名空间。这可能会导致创建
XPath 查询变得困难。请使用严重缺乏文档的
"namespaceURI" 属性,该属性属于 DOMDocument 的 documentElement,
以确定是否存在命名空间。
使用以下代码

$doc = new DOMDocument();
$doc->load($file);
$xpath = new DOMXPath($doc);
$ns = $doc->documentElement->namespaceURI;
if($ns) {
$xpath->registerNamespace("ns", $ns);
$nodes = $xpath->query("//ns:em[@class='glossterm']");
} else {
$nodes = $xpath->query("//em[@class='glossterm']");
}
//在此查看节点
peter at softcoded dot com
7 年前
使用 XPath 表达式可以节省大量编程工作
并让您只关注所需的节点。
假设您想要删除所有空的 <p> 标签。
如果您使用以下 XPath 表达式创建查询,
您可以找到没有文本的 <p> 标签
(除了空格)、任何属性、
任何子节点或注释

$expression = "//p[not(@*)
and not(*)
and not(./comment())
and normalize-space(text())='']";

此表达式只会找到类似于以下内容的段落标签

<p>[任意数量的空格]</p>
<p></p>

想象一下,如果您使用
DOMDocument::getElementsByTagName("p"),则需要添加多少代码。
archimedix32783262 at mailinator dot com
9 年前
请注意,evaluate() 将使用与 XML 文档相同的编码。

因此,如果您有 UTF-16 XML,则必须使用 UTF-16 字符串进行查询。

您可以使用 iconv() 将代码的编码转换为目标编码,以便更好地阅读。
dhz
13 年前
我刚花了很多时间追踪这个问题....

在对表格运行 xpath 查询时,请注意表格内部节点(即:<tr></tr> 和 <td></td>)。如果主 <table> 标签丢失,则 query()(以及 evaluate() 也可能)将返回意外结果。

我有一个结构类似于此的 DOMNode

<td>
<table></table>
<table>
<tr>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
</table>
</td>

我试图对它进行相对查询(即:<?php $xpath_obj->query('my/x/path', $relative_node); ?>)。

但是,由于存在单独的外层 <td></td> 标签,内部标签被视为无效,而节点仍被识别。这意味着以下查询将起作用

<?php $xpath_obj->query('*[2]/*[*[2]]', $relative_node); ?>

但是,当用相应的(有效)"table"、"tr" 或 "td" 标记替换任何 "*" 标记时,查询将莫名其妙地中断。
To Top