gpt4 book ai didi

c# - HTMLAgilityPack 中的 XPath 选择不能按预期工作

转载 作者:太空狗 更新时间:2023-10-29 23:22:50 24 4
gpt4 key购买 nike

我正在用 C# 编写简单的屏幕抓取程序,为此我需要选择一个名为“aspnetForm”的单一表单内的所有输入(页面上有 2 个表单,我不希望输入来自另一个),并且此表单中的所有输入都放置在不同的表、div 中,或仅放在此表单的第一个子级。

所以我编写了非常简单的 XPath 查询:

//form[@id='aspnetForm']//input

它在我测试的所有浏览器(Chrome、IE、Firefox)中都按预期工作 - 它返回我想要的。

但在 HTMLAgilityPack 中它根本不起作用 - SelectNodes 总是返回 NULL。

我为测试编写的这个查询工作正常,但返回的不是我想要的。首先为我的表单选择所有第一个 child 的输入,然后选择返回的表单:

//form[@id='aspnetForm']/input
//form[@id='aspnetForm']

是的,我知道我可以枚举上次查询的节点,或者在其结果上创建另一个 SelectNodes,但我真的不想这样做。我想使用与浏览器中相同的查询。

目前 XPath 在 HTMLAgilityPack 中有问题吗? C# 有任何替代的 XPath 实现吗?

更新:测试代码:

using HtmlAgilityPack;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace HtmlAGPTests
{
[TestClass]
public class XPathTests
{
private const string html =
"<form id=\"aspnetForm\">" +
"<input name=\"first\" value=\"first\" />" +
"<div>" +
"<input name=\"second\" value=\"second\" />" +
"</div>" +
"</form>";

private static HtmlNode GetHtmlDocumentNode()
{
var document = new HtmlDocument();
document.LoadHtml(html);
return document.DocumentNode;
}

[TestMethod]
public void TwoLevelXpathTest() // fail - nodes is NULL actually.
{
var query = "//form[@id='aspnetForm']//input"; // what i want
var documentNode = GetHtmlDocumentNode();

var inputNodes = documentNode.SelectNodes(query);

Assert.IsTrue(inputNodes.Count == 2);
}

[TestMethod]
public void TwoSingleLevelXpathsTest() // works
{
var formQuery = "//form[@id='aspnetForm']";
var inputQuery = "//input";
var documentNode = GetHtmlDocumentNode();

var formNode = documentNode.SelectSingleNode(formQuery);
var inputNodes = formNode.SelectNodes(inputQuery);

Assert.IsTrue(inputNodes.Count == 2);
}

[TestMethod]
public void SingleLevelXpathTest() // works
{
var query = "//form[@id='aspnetForm']";
var documentNode = GetHtmlDocumentNode();

var formNode = documentNode.SelectSingleNode(query);

Assert.IsNotNull(formNode);
}

}
}

最佳答案

测试中出现意外行为是因为 html 包含 <form>元素。这是相关的讨论:

Ariman : "I've found that after parsing any node does not have any child nodes. All nodes that should be inside the form (, , etc.) are created as it's siblings rather then children.

VikciaR : "In Html specification form tag can overlap, so Htmlagilitypack handle this node a little different..."

[CodePlex discussion : No child nodes for FORM objects ]

按照 VikciaR 的建议,尝试像这样修改您的测试代码初始化:

private static HtmlNode GetHtmlDocumentNode()
{
var document = new HtmlDocument();
document.LoadHtml(html);

//execute this line once
HtmlNode.ElementsFlags.Remove("form");

return document.DocumentNode;
}

旁注: inputQuery测试方法中的值 TwoSingleLevelXpathsTest()应该是 .//input .注意开头的点 ( . ) 表示此查询是相对于当前节点的。否则它将从根开始搜索,忽略前一个 formQuery (没有点,您可以将 formQuery 更改为任何内容,只要它不返回 null,inputQuery 将始终返回相同的结果)。

关于c# - HTMLAgilityPack 中的 XPath 选择不能按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23232671/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com