将这两个表达式组合成一个LINQ表达式

时间:2013-03-30 15:40:28

标签: c# html linq xpath html-agility-pack

我使用HTMLAgilityPack来解析一些html。我在使用和xpath查询结合linq查询时得到了我期望的结果集。有没有办法可以将它们组合成一个LINQ查询?

var test = doc.DocumentNode.SelectNodes("//div[@class='product']");

foreach (var item in test)
{

    var result = from input in item.Descendants("span")
                 where input.Attributes["class"].Value == "Bold"
                 where input.InnerHtml.ToUpper() == "GetItem"
                 select input;   

    return result;           
}

4 个答案:

答案 0 :(得分:2)

如果你想把所有的跨度聚集在一起(如果我认为你想要的是正确的话)......

我首先将它转换为更流畅的符号(我发现SelectMany更容易掌握这种方式 - 但那只是我)

(免责声明:我是从内存中写这个,复制/粘贴你的代码 - 目前不是VS的 - 你需要检查,如果有任何问题可以写,但我想我得到了它好的或多或少)

var test = doc.DocumentNode.SelectNodes("//div[@class='product']");
foreach(var item in test)
    item.Descendants("span").Where(input => input.Attributes["class"].Value == "Bold").Where(input => input.InnerHtml.ToUpper() == "GetItem").Select(input => input);

最后......

var allSpans = doc.DocumentNode.SelectNodes("//div[@class='product']")
    .SelectMany(item => item.Descendants("span").Where(input => input.Attributes["class"].Value == "Bold").Where(input => input.InnerHtml.ToUpper() == "GetItem"));

......或沿着这些方向

答案 1 :(得分:2)

只是想告诉你在Linq做SelectMany的另一种方式。这是一种样式选择,SO中的许多人更喜欢.SelectMany扩展方法,因为他们可以看到Monad如何应用于IEnumerable。我更喜欢这种方法,因为它更接近函数式编程模型的作用。

return from product in doc.DocumentNode.SelectNodes("//div[@class='product']")
       from input in product.Descendants("span")
       where input.Attributes["class"].Value == "Bold"
       where input.InnerHtml.ToUpper() == "GetItem"
       select input;        

答案 2 :(得分:1)

如果您真的想在一个查询中完成所有操作,可以使用以下内容:

var result = doc.DocumentNode.SelectNodes("//div[@class='product']")
    .SelectMany(e => e.Descendants("span")
        .Where(x => x.Attributes["class"].Value == "Bold" && 
                    x.InnerHtml.ToUpper() == "GetItem"))
    .ToList();

return result;

为了便于阅读,我建议将它分开一点,更像是这样:

var result = new List<SomeType>();
var nodes = doc.DocumentNode.SelectNodes("//div[@class='product']");

nodes.SelectMany(e => e.Descendants("span")
    .Where(x => x.Attributes["class"].Value == "Bold" && 
                x.InnerHtml.ToUpper() == "GetItem"));

return result.ToList();

SelectMany()方法会将内部查询的结果展平为单个IEnumerable<T>

答案 3 :(得分:1)

return (
    from result in 
        from item in doc.DocumentNode.SelectNodes("//div[@class='product']")
        from input in item.Descendants("span")
        where input.Attributes["class"].Value == "Bold"
        where input.InnerHtml.ToUpper() == "GetItem"
        select input
    select result
    ).First();