注意:这个问题及其答案对于大多数/所有支持 XPath 的编程语言和库都有效,而不仅仅是 JavaScript!
使用以下代码创建一个非常简单的 HTML 页面(实际代码加载远程页面,但我试图将您的注意力集中在此处的主要问题上):
var dt = document.implementation.createDocumentType("html", "-//W3C//DTD HTML 4.01 Transitional//EN", "http://www.w3.org/TR/html4/loose.dtd");
var doc = document.implementation.createDocument("http://www.w3.org/1999/xhtml", "html", dt);
var src = "<head></head><body></body>";
doc.documentElement.innerHTML = src;
alert(doc.evaluate(".", doc, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue);
alert(doc.evaluate("/body", doc, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue);
alert(doc.evaluate("//body", doc, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue);
alert(doc.evaluate("/html", doc, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue);
第一个 alert()
显示“[object HTMLDocument]”,另一个 alert()
显示“null”。这是为什么?为了让 XPath 查询工作并让它找到 body 元素,我缺少什么?
编辑:
- 在示例中添加了“//body”
- 我想我应该提到我使用的是 Opera 12.17。有没有任何解决方法可以使我得到相同的结果?
最佳答案
第一个 XPath 选择文档根(.
是当前上下文)。
第二个为 null,因为根上下文中没有 body
。您可以使用:
/html/body
或
//body
这将为您提供节点。从那里,您可以使用上下文 XPath 表达式或 DOM 方法和属性获取上下文中的子节点。要查看节点名称,您可以使用所选节点上的 nodeName
属性:
doc.evaluate(".", doc, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null)
.singleNodeValue.nodeName;
doc.evaluate("//body", doc, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null)
.singleNodeValue.nodeName;
此替代版本使用 DOM 来创建节点。
var head = document.createElement("head");
var body = document.createElement("body");
doc.documentElement.appendChild(head);
doc.documentElement.appendChild(body);
它还强制执行命名空间(在第一个示例中,Chrome 中会忽略该命名空间),因此 XPath 表达式需要包含命名空间映射函数(作为 evaluate
方法的第三个参数,或忽略它们(使用通配符和本地名称测试,如下例所示)。
doc.evaluate(".//*[local-name()='body']", doc.documentElement, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue.nodeName
请注意,我还使用了 doc.documentElement
作为上下文节点。
在浏览器中尝试一下:
关于javascript - XPath 不适用于动态 HTML 文档,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24109226/