在 Node.js 中使用 XPath

Den*_*sky 4 html javascript xpath dom node.js

我正在使用 Node.js 构建一个小型文档解析器。为了进行测试,我有一个原始 HTML 文件,通常是在应用程序执行时从真实网站下载的。

我想从 Console.WriteLine 的每个部分中提取与我的约束匹配的第一个代码示例 - 它必须用 C# 编写。为此,我有以下示例 XPath:

//*[@id='System_Console_WriteLine_System_String_System_Object_System_Object_System_Object_']/parent::div/following-sibling::div/pre[position()>1]/code[contains(@class,'lang-csharp')]
Run Code Online (Sandbox Code Playgroud)

如果我在线测试 XPath,我会得到预期的结果,这在这个 Gist 中

在我的 node.js 应用程序中,我使用xmldomxpath尝试解析出完全相同的信息:

var exampleLookup = `//*[@id='System_Console_WriteLine_System_String_System_Object_System_Object_System_Object_']/parent::div/following-sibling::div/pre[position()>1]/code[contains(@class,'lang-csharp')]`;
var doc = new dom().parseFromString(rawHtmlString, 'text/html');
var sampleNodes = xpath.select(exampleLookup,doc);
Run Code Online (Sandbox Code Playgroud)

但是,这不会返回任何内容。

这里可能发生了什么?

Dan*_*ley 5

xmlns="http://www.w3.org/1999/xhtml"这很可能是由HTML (XHTML) 中的默认命名空间 ( ) 引起的。

查看xpath 文档,您应该能够使用 xpath 将命名空间绑定到前缀useNamespaces并使用该前缀(未经测试)...

var exampleLookup = `//*[@id='System_Console_WriteLine_System_String_System_Object_System_Object_System_Object_']/parent::x:div/following-sibling::x:div/x:pre[position()>1]/x:code[contains(@class,'lang-csharp')]`;
var doc = new dom().parseFromString(rawHtmlString, 'text/html');
var select = xpath.useNamespaces({"x": "http://www.w3.org/1999/xhtml"});
var sampleNodes = xpath.select(exampleLookup,doc);
Run Code Online (Sandbox Code Playgroud)

您还可以在 XPath 中使用名称空间,而不是将名称空间绑定到前缀local-name(),但我不推荐这样做。文档中也对此进行了介绍。

例子...

//*[@id='System_Console_WriteLine_System_String_System_Object_System_Object_System_Object_']/parent::*[local-name()='div']/following-sibling::*[local-name()='div']/*[local-name()='pre'][position()>1]/*[local-name()='code'][contains(@class,'lang-csharp')]
Run Code Online (Sandbox Code Playgroud)