防止引发异常

时间:2014-04-07 09:19:49

标签: c# parsing exception html-agility-pack raiserror

我正在使用以下代码解析以下html:

 var exroom = (from roomItem in
           doc.DocumentNode.SelectNodes("//div[@class='dias']//h2")

       from s  in roomItem.NextSibling.NextSibling.SelectNodes(".//label")

       let rName = roomItem.InnerText.CleanInnerText()

       select new
       {
           roomID = rName,
           Pers = 2,
           Currency = "EUR",
           rateName = s.InnerText.CleanInnerText(),
           roomName = rName,
           Price = PriceHelper.Convert(PriceRegEx.Match(s.Attributes["precio"].Value.CleanInnerText()).Groups["price"].Value)
       }
).ToArray();

但是当我解析没有上述标签的html内容时,它会引发异常,如何在解析时防止引发异常并为exroom数组返回0?比如我在班级dias中没有任何元素。

2 个答案:

答案 0 :(得分:1)

分三步拆分处理。

  • 选择'dias'类的元素
  • 检查所选变量,并仅在不同于null
  • 时继续处理
  • 其余的处理

因为你在exroom变​​量中有一些匿名类型对象,所以创建空数组可能会很棘手。

我建议在某个类中包装该类型:

public class RoomItem {
    public string roomID { get; set; }
    public string Pers { get; set; }
    ...
}

然后选择exroom变​​量看起来像:

var diasElements = doc.DocumentNode.SelectNodes("//div[@class='dias']//h2");
var exroom = new RoomItem[] { };
if(null != diasElements) { 
    exroom = (from roomItem in diasElements
    from s in roomItem.NextSibling.NextSibling.SelectNodes(".//label")
    let rName = roomItem.InnerText.CleanInnerText()
    select new RoomItem
    {
         roomID = rName,
         Pers = 2,
         Currency = "EUR",
         rateName = s.InnerText.CleanInnerText(),
         roomName = rName,
         Price =
              PriceHelper.Convert(
                  PriceRegEx.Match(s.Attributes["precio"].Value.CleanInnerText()).Groups["price"].Value)
              }
    ).ToArray()
}

从示例代码中看起来像带有'dias'类的元素的空列表应该会产生某种形式的错误消息(可能是throw / catch异常,或者使BookingEngineResponse适应传递有关空dias集合的信息)。

编辑: 完整的代码示例后澄清答案。

答案 1 :(得分:1)

据我所知,如果LINQ中的两个.SelectNodes()中的任何一个都没有产生结果,则不会出现异常。您认为查询还有两个部分可能会引发异常:

  1. NextSibling部分,如果当前roomItem没有下一个 兄弟姐妹或下一个兄弟姐妹。您可以将此部分更改为纯XPath 而不是访问NextSibling属性。使用纯XPath更省钱 如果没有元素与整个查询匹配,则安全地不返回结果。

  2. 如果当前Attributes["precio"]没有属性“precio”,则与s部分对接。您可以使用GetAttributeValue("attrName", "defaultValue")替换此部件,如果该属性不存在,此方法将返回默认值。

  3. 证明以上建议的代码:

    from roomItem in doc.DocumentNode.SelectNodes("//div[@class='dias']//h2")
    from s  in roomItem.SelectNodes("./following-sibling::*[2]//label")
    let rName = roomItem.InnerText.CleanInnerText()
    select new
    {
       roomID = rName,
       Pers = 2,
       Currency = "EUR",
       rateName = s.InnerText.CleanInnerText(),
       roomName = rName,
       Price = PriceHelper.Convert(PriceRegEx.Match(s.GetAttributeValue("precio","").CleanInnerText()).Groups["price"].Value)
    }