如何忽略具有LINQ where子句的特定?

时间:2012-02-06 20:16:53

标签: c# linq

我有一个发送xml feed的客户端,我使用以下代码解析它。这段代码有效。

reviews = from item in xmlDoc.Descendants("node")
                          select new ForewordReview()
                          {
                              PubDate = (string)item.Element("created"),
                              Isbn = (string)item.Element("isbn"),
                              Summary = (string)item.Element("review")
                          };

获取所有“评论”后,我将IEnumerable转换为List并将其返回。最初,我有一个很好的,很容易解析他们的XML的过去看起来像这样:

<reviews>
    <node>
        <created>01-01-1900</created>
        <ISBN>12345657890123</ISBN>
        <Review>This is a nice and silly book</Review>
    </node>
    <node>
        <created>01-01-2011</created>
        <ISBN>1236245234554</ISBN>
        <Review>This is a stupid book</Review>
    </node>
    <node>
        <created>12-06-1942</created>
        <ISBN>1234543234577</ISBN>
        <Review>This is a old, naughty book</Review>
    </node>
</reviews>
但是,他们已经改变了我们无法访问的架构,现在他们的XML在最终的<node>标签中添加了一个不包含我正在寻找的欺骗元素的结尾,所以,我的解析打破了这最后一个标签,我抛出一个异常。这是一个例子:

<reviews>
    <node>
        <created>01-01-1900</created>
        <ISBN>12345657890123</ISBN>
        <Review>This is a nice and silly book</Review>
    </node>
    <node>
        <created>01-01-2011</created>
        <ISBN>1236245234554</ISBN>
        <Review>This is a stupid book</Review>
    </node>
    <node>
        <created>12-06-1942</created>
        <ISBN>1234543234577</ISBN>
        <Review>This is a old, naughty book</Review>
    </node>
    <node>
        <count>4656</count>
    </node>
</reviews>

我需要知道是否有办法忽略这个最终标记(它总是在文档的末尾),即使它与我正在寻找的所有其他“节点”标记具有相同的名称。我确实尝试了解这段代码,但如果发现此错误,它不会返回好的评论列表。

谢谢你们。

5 个答案:

答案 0 :(得分:4)

如果它始终是最后一个节点,

var nodes = xmlDoc.Descendants("node");
reviews = nodes.Take(nodes.Count() - 1).Select(...);

答案 1 :(得分:2)

这样的事情可以解决问题:

var reviews = from item in xmlDoc.Descendants("node").Where(x => x.Element("created") != null)
select new
{
    PubDate = (string)item.Element("created"),
    Isbn = (string)item.Element("isbn"),
    Summary = (string)item.Element("review")
};

如果愿意,您可以对其他元素进行额外的空检查。

答案 2 :(得分:1)

添加空检查

PubDate = (string)(item.Element("created") ?? ""),
Isbn = (string)(item.Element("isbn") ?? ""),
Summary = (string)(item.Element("review") ?? "")

始终将null检查添加到您执行的所有操作中。只是好习惯。在这种情况下,它将消除此错误,但可能会在您假设这些字符串不为空的程序中稍后出现错误,因此请确保稍后再进行空检查。

答案 3 :(得分:1)

您可以计算节点数,然后使用Where的重载,它也会传递一个索引号:(http://msdn.microsoft.com/en-us/library/bb549418.aspx)

public static IEnumerable<TSource> Where<TSource>(
this IEnumerable<TSource> source,
Func<TSource, int, bool> predicate)

所以,像这样:

var count = xmlDoc.Descendants("node").Count();
xmlDoc.Descendants("node").Where((node,index) => index < count-1).Select(..)

答案 4 :(得分:0)

你可以在那里抛出“where”子句。

reviews = from item in xmlDoc.Descendants("node") where item.Descendants().Any(n => n.Name == "Review")
                      select new ForewordReview()
                      {
                          PubDate = (string)item.Element("created"),
                          Isbn = (string)item.Element("isbn"),
                          Summary = (string)item.Element("review")
                      };

此示例只是检查名为“Review”的子节点,因此最好检查所有必需的子节点。