我正在使用Html Agility包从rss xml中选择文本数据。对于每个其他节点类型(title,pubdate,guid .etc),我可以使用XPath约定选择内部文本,但是当查询“// 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”返回零节点。运行“// link”会返回正确数量的节点,但内部文本的长度为零个字符。
使用下面的测试数据,“// name”返回“fred”的单个记录,但是使用“// link”返回带有空字符串的单个记录。
<site><link>Hello World</link><name>Fred</name></site>
我确信它是因为世界的“链接”。如果我将其更改为“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();
}
答案 0 :(得分:4)
如果您打印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);
}
<强> Dotnetfiddle Demo
强>
输出
<site><link>Hello World</link><name>Fred</name></site>
Hello World
*)除了link
之外的特殊标记的完整列表,默认情况下包含在ElementsFlags
字典中,可以在{{3}的源代码中看到}。其中一些最受欢迎的是<meta>
,<img>
,<frame>
,<input>
,<form>
,<option>
等。