无法使用 HtmlAgilityPack 和 XPath 提取 <link> 元素
Cannot extract <link> element using HtmlAgilityPack and XPath
我正在使用 Html 敏捷包 select 从 rss xml 中输出文本数据。对于其他所有节点类型(title、pubdate、guid 等),我可以使用 XPath 约定 select 排除 inner-text,但是在查询“//link”或 "item/link" 时返回空字符串。
public static IEnumerable<string> ExtractAllLinks(string rssSource)
{
//Create a new document.
var document = new HtmlDocument();
//Populate the document with an rss file.
document.LoadHtml(rssSource);
//Select out all of the required nodes.
var itemNodes = document.DocumentNode.SelectNodes("item/link");
//If zero nodes were found, return an empty list, otherwise return the content of those nodes.
return itemNodes == null ? new List<string>() : itemNodes.Select(itemNode => itemNode.InnerText).ToList();
}
有人知道为什么这个元素的行为与其他元素不同吗?
附加:运行 "item/link" returns 零个节点。 运行 "//link" returns 正确的节点数但是内部文本的长度为零个字符。
使用下面的测试数据,使用“//name”returns "fred" 的单个记录但是使用“//link”的单个记录带有空字符串是返回。
<site><link>Hello World</link><name>Fred</name></site>
我肯定是因为这个世界"link"。如果我将其更改为 "linkz",它会完美运行。
以下解决方法非常有效。但是我想了解为什么搜索“//link”不像其他元素那样有效。
public static IEnumerable<string> ExtractAllLinks(string rssSource)
{
rssSource = rssSource.Replace("<link>", "<link-renamed>");
rssSource = rssSource.Replace("</link>", "</link-renamed>");
//Create a new document.
var document = new HtmlDocument();
//Populate the document with an rss file.
document.LoadHtml(rssSource);
//Select out all of the required nodes.
var itemNodes = document.DocumentNode.SelectNodes("//link-renamed");
//If zero nodes were found, return an empty list, otherwise return the content of those nodes.
return itemNodes == null ? new List<string>() : itemNodes.Select(itemNode => itemNode.InnerText).ToList();
}
如果你打印 DocumentNode.OuterHtml
,你会看到问题:
var html = @"<site><link>Hello World</link><name>Fred</name></site>";
var doc = new HtmlDocument();
doc.LoadHtml(html);
Console.WriteLine(doc.DocumentNode.OuterHtml);
输出:
<site><link>Hello World<name>Fred</name></site>
link
恰好是一些 特殊标签 * 之一,被 HAP 视为自关闭标签。您可以通过在解析 HTML 之前设置 ElementsFlags
来更改此行为,例如:
var html = @"<site><link>Hello World</link><name>Fred</name></site>";
HtmlNode.ElementsFlags.Remove("link"); //remove link from list of special tags
var doc = new HtmlDocument();
doc.LoadHtml(html);
Console.WriteLine(doc.DocumentNode.OuterHtml);
var links = doc.DocumentNode.SelectNodes("//link");
foreach (HtmlNode link in links)
{
Console.WriteLine(link.InnerText);
}
输出:
<site><link>Hello World</link><name>Fred</name></site>
Hello World
*) 除link
之外的特殊标签的完整列表,默认包含在ElementsFlags
字典中,可以在源代码中看到HtmlNode.cs
。其中一些最受欢迎的是<meta>
、<img>
、<frame>
、<input>
、<form>
、<option>
等
我正在使用 Html 敏捷包 select 从 rss xml 中输出文本数据。对于其他所有节点类型(title、pubdate、guid 等),我可以使用 XPath 约定 select 排除 inner-text,但是在查询“//link”或 "item/link" 时返回空字符串。
public static IEnumerable<string> ExtractAllLinks(string rssSource)
{
//Create a new document.
var document = new HtmlDocument();
//Populate the document with an rss file.
document.LoadHtml(rssSource);
//Select out all of the required nodes.
var itemNodes = document.DocumentNode.SelectNodes("item/link");
//If zero nodes were found, return an empty list, otherwise return the content of those nodes.
return itemNodes == null ? new List<string>() : itemNodes.Select(itemNode => itemNode.InnerText).ToList();
}
有人知道为什么这个元素的行为与其他元素不同吗?
附加:运行 "item/link" returns 零个节点。 运行 "//link" returns 正确的节点数但是内部文本的长度为零个字符。
使用下面的测试数据,使用“//name”returns "fred" 的单个记录但是使用“//link”的单个记录带有空字符串是返回。
<site><link>Hello World</link><name>Fred</name></site>
我肯定是因为这个世界"link"。如果我将其更改为 "linkz",它会完美运行。
以下解决方法非常有效。但是我想了解为什么搜索“//link”不像其他元素那样有效。
public static IEnumerable<string> ExtractAllLinks(string rssSource)
{
rssSource = rssSource.Replace("<link>", "<link-renamed>");
rssSource = rssSource.Replace("</link>", "</link-renamed>");
//Create a new document.
var document = new HtmlDocument();
//Populate the document with an rss file.
document.LoadHtml(rssSource);
//Select out all of the required nodes.
var itemNodes = document.DocumentNode.SelectNodes("//link-renamed");
//If zero nodes were found, return an empty list, otherwise return the content of those nodes.
return itemNodes == null ? new List<string>() : itemNodes.Select(itemNode => itemNode.InnerText).ToList();
}
如果你打印 DocumentNode.OuterHtml
,你会看到问题:
var html = @"<site><link>Hello World</link><name>Fred</name></site>";
var doc = new HtmlDocument();
doc.LoadHtml(html);
Console.WriteLine(doc.DocumentNode.OuterHtml);
输出:
<site><link>Hello World<name>Fred</name></site>
link
恰好是一些 特殊标签 * 之一,被 HAP 视为自关闭标签。您可以通过在解析 HTML 之前设置 ElementsFlags
来更改此行为,例如:
var html = @"<site><link>Hello World</link><name>Fred</name></site>";
HtmlNode.ElementsFlags.Remove("link"); //remove link from list of special tags
var doc = new HtmlDocument();
doc.LoadHtml(html);
Console.WriteLine(doc.DocumentNode.OuterHtml);
var links = doc.DocumentNode.SelectNodes("//link");
foreach (HtmlNode link in links)
{
Console.WriteLine(link.InnerText);
}
输出:
<site><link>Hello World</link><name>Fred</name></site>
Hello World
*) 除link
之外的特殊标签的完整列表,默认包含在ElementsFlags
字典中,可以在源代码中看到HtmlNode.cs
。其中一些最受欢迎的是<meta>
、<img>
、<frame>
、<input>
、<form>
、<option>
等