gpt4 book ai didi

c# - 解析 html -> xml 并使用 Xpath 查询

转载 作者:数据小太阳 更新时间:2023-10-29 01:48:29 24 4
gpt4 key购买 nike

我想解析一个 html 页面来获取一些数据。首先,我使用 SgmlReader 将其转换为 XML 文档。然后,我将结果加载到 XMLDocument,然后通过 XPath 导航:

//contains html document
var loadedFile = LoadWebPage();

...

Sgml.SgmlReader sgmlReader = new Sgml.SgmlReader();
sgmlReader.DocType = "HTML";
sgmlReader.WhitespaceHandling = WhitespaceHandling.All;
sgmlReader.CaseFolding = Sgml.CaseFolding.ToLower;

sgmlReader.InputStream = new StringReader(loadedFile);

XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = true;
doc.XmlResolver = null;
doc.Load(sgmlReader);

此代码适用于大多数情况,但本网站除外 - www.arrow.com (尝试搜索类似 OP295GS 的内容)。我可以使用以下 XPath 获取包含结果的表格:

var node = doc.SelectSingleNode(".//*[@id='results-table']");

这给了我一个有几个子节点的节点:

[0]         {Element, Name="thead"}  
[1] {Element, Name="tbody"}
[2] {Element, Name="tbody"}
FirstChild {Element, Name="thead"}

好的,让我们尝试使用 XPath 获取一些子节点。但这不起作用:

var childNodes = node.SelectNodes("tbody");
//childnodes.Count = 0

这也是:

var childNode = node.SelectSingleNode("thead");
// childNode = null

甚至这个:

var childNode = doc.SelectSingleNode(".//*[@id='results-table']/thead")

Xpath 查询有什么问题?


我刚刚尝试使用 Html Agility Pack 解析该 HTML 页面,我的 XPath 查询运行良好。但是我的应用程序内部使用 XmlDocument,Html Agility Pack 不适合我。


我什至用 Html Agility Pack 尝试了以下技巧,但 Xpath 查询也不起作用:

//let's parse and convert HTML document using HTML Agility Pack and then load
//the result to XmlDocument
HtmlDocument xmlDocument = new HtmlDocument();
xmlDocument.OptionOutputAsXml = true;
xmlDocument.Load(new StringReader(webPage));

XmlDocument document = new XmlDocument();
document.LoadXml(xmlDocument.DocumentNode.InnerHtml);

也许网页包含错误(并非所有标签都已关闭等),但尽管如此我可以看到子节点(通过 Visual Studio 中的 Quick Watch),但无法通过 XPath 访问它们。


我的 XPath 查询在 Firefox + FirePath + XPather 插件中工作正常,但在 .net XmlDocument 中不工作:(

最佳答案

我没有使用过 SqmlReader,但每次我看到这个问题都是由于 namespace 引起的。快速查看 www.arrow.com 上的 HTML 显示该节点有一个命名空间(注意 xmlns:javaurlencoder):

<form name="CatSearchForm" method="post" action="http://components.arrow.com/part/search/OP295GS" xmlns:javaurlencoder="java.net.URLEncoder">

此代码是我如何遍历文档中的所有节点以查看哪些节点具有 namespace 而哪些节点没有。如果您要查找的节点或其任何父节点具有 namespace ,您必须创建一个 XmlNamespaceManager 并将其与对 SelectNodes() 的调用一起传递。

这有点烦人,所以另一个想法可能是在将 XML 加载到 XmlDocument 之前从 XML 中去除所有 xmlns: 属性。然后,您就不需要愚弄 XmlNamespaceManager 了!

XmlDocument doc = new XmlDocument();
doc.Load(@"C:\temp\X.loadtest.xml");

Dictionary<string, string> namespaces = new Dictionary<string, string>();
XmlNodeList nlAllNodes = doc.SelectNodes("//*");
foreach (XmlNode n in nlAllNodes)
{
if (n.NodeType != XmlNodeType.Element) continue;

if (!String.IsNullOrEmpty(n.NamespaceURI) && !namespaces.ContainsKey(n.Name))
{
namespaces.Add(n.Name, n.NamespaceURI);
}
}

// Inspect the namespaces dictionary to write the code below

XmlNamespaceManager nMgr = new XmlNamespaceManager(doc.NameTable);
// Sometimes this works
nMgr.AddNamespace("ns1", doc.DocumentElement.NamespaceURI);
// You can make the first param whatever you want, it just must match in XPath queries
nMgr.AddNamespace("javaurlencoder", "java.net.URLEncoder");

XmlNodeList iter = doc.SelectNodes("//ns1:TestProfile", nMgr);
foreach (XmlNode n in iter)
{
// Do stuff
}

关于c# - 解析 html -> xml 并使用 Xpath 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5359805/

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