在 xpath 中使用“.//”
Use of ".//" in xpath
SO 上有很多关于 Xpath 不能与 HtmlAgilityPack 一起工作的问题。我读了六本,但没有找到解决我的问题的方法。
我想 select 任何级别的 "form" 元素内的所有 "input" 元素。
我希望它能工作:
var all = html.DocumentNode.SelectNodes("//form//input");
它没有 - 没有返回任何元素。这也不起作用(在此测试用例中假设有一个表单元素,以缩小问题范围):
var node = html.DocumentNode.SelectSingleNode("//form");
var nodes = node.SelectNodes(".//input");
现在,以上所有内容自然适用于 xml:
XmlDocument d = new XmlDocument();
d.LoadXml("<html><body><form><div><input></input></div></form></body></html>");
var xmlNode = d.SelectSingleNode("//form");
var xmlNodes = xmlNode.SelectNodes(".//input");
Console.WriteLine($"Two step xml: {xmlNodes?.Count}");
var xmlAll = d.SelectNodes("//form//input");
Console.WriteLine($"One step xml: {xmlAll?.Count}");
如预期的那样,上面的两种情况都显示计数为 1。
现在是 HtmlAgilityPack 的示例,它不起作用:
string test = @"<!DOCTYPE html>
<html lang=""en"" xmlns=""http://www.w3.org/1999/xhtml"">
<head id=""Head1"">
<body>
<form method=""post"" action=""/SignIn"" id=""mainform"">
<div class=""aspNetHidden"">
<input type=""hidden"" name=""hello"" id=""hello"" value="""" />
</div>
</form>
</body>
</html>";
HtmlDocument html = new HtmlDocument();
html.LoadHtml(test);
var node = html.DocumentNode.SelectSingleNode("//form");
var nodes = node.SelectNodes(".//input");
Console.WriteLine($"Two steps html: {nodes?.Count}");
var all = html.DocumentNode.SelectNodes("//form//input");
Console.WriteLine($"One step html: {all?.Count}");
这里没有显示1,因为没有找到节点。
为什么?是否可以在不求助于 loops/code 的情况下修复 xpath 表达式?
我正在设计一个 class 需要接受单个 xpath 表达式(可能用于配置 and/or 数据存储)以了解它需要处理的节点子集。
所以你的代码没有问题。问题是 HTMLAgilityPack 本身。
基本上你需要添加这一行
HtmlNode.ElementsFlags.Remove("form");
根据花岗岩龙评论:
There are indeed a lot of questions regarding HtmlAgilityPack and xpath, mostly because its xpath implementation is incorrect and not up with generic xpath specifications.
SO 上有很多关于 Xpath 不能与 HtmlAgilityPack 一起工作的问题。我读了六本,但没有找到解决我的问题的方法。
我想 select 任何级别的 "form" 元素内的所有 "input" 元素。
我希望它能工作:
var all = html.DocumentNode.SelectNodes("//form//input");
它没有 - 没有返回任何元素。这也不起作用(在此测试用例中假设有一个表单元素,以缩小问题范围):
var node = html.DocumentNode.SelectSingleNode("//form");
var nodes = node.SelectNodes(".//input");
现在,以上所有内容自然适用于 xml:
XmlDocument d = new XmlDocument();
d.LoadXml("<html><body><form><div><input></input></div></form></body></html>");
var xmlNode = d.SelectSingleNode("//form");
var xmlNodes = xmlNode.SelectNodes(".//input");
Console.WriteLine($"Two step xml: {xmlNodes?.Count}");
var xmlAll = d.SelectNodes("//form//input");
Console.WriteLine($"One step xml: {xmlAll?.Count}");
如预期的那样,上面的两种情况都显示计数为 1。
现在是 HtmlAgilityPack 的示例,它不起作用:
string test = @"<!DOCTYPE html>
<html lang=""en"" xmlns=""http://www.w3.org/1999/xhtml"">
<head id=""Head1"">
<body>
<form method=""post"" action=""/SignIn"" id=""mainform"">
<div class=""aspNetHidden"">
<input type=""hidden"" name=""hello"" id=""hello"" value="""" />
</div>
</form>
</body>
</html>";
HtmlDocument html = new HtmlDocument();
html.LoadHtml(test);
var node = html.DocumentNode.SelectSingleNode("//form");
var nodes = node.SelectNodes(".//input");
Console.WriteLine($"Two steps html: {nodes?.Count}");
var all = html.DocumentNode.SelectNodes("//form//input");
Console.WriteLine($"One step html: {all?.Count}");
这里没有显示1,因为没有找到节点。
为什么?是否可以在不求助于 loops/code 的情况下修复 xpath 表达式?
我正在设计一个 class 需要接受单个 xpath 表达式(可能用于配置 and/or 数据存储)以了解它需要处理的节点子集。
所以你的代码没有问题。问题是 HTMLAgilityPack 本身。
基本上你需要添加这一行
HtmlNode.ElementsFlags.Remove("form");
根据花岗岩龙评论:
There are indeed a lot of questions regarding HtmlAgilityPack and xpath, mostly because its xpath implementation is incorrect and not up with generic xpath specifications.