【问题标题】:Prevent raising an exception防止引发异常
【发布时间】:2014-04-07 09:19:49
【问题描述】:

我正在使用以下代码解析以下 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 类中没有任何元素。

【问题讨论】:

  • 那是HtmlAgilityPack吗?
  • @TimSchmelter 是的
  • 为什么不返回一个长度为 0 的数组而不是 0?
  • @bluewonder:捕获异常并返回适当的东西可能不是理想的解决方案,但这不是一种自我暗示吗?
  • 我已经编辑了你的标题。请参阅“Should questions include “tags” in their titles?”,其中的共识是“不,他们不应该”。

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


【解决方案1】:

分三步处理。

  • 选择“dias”类的元素
  • 检查选定的变量,只有当它不为空时才继续处理
  • 您的其余处理

因为您在 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”的元素的空列表应该会导致某种形式的错误消息(可能是抛出/捕获异常,或调整 BookingEngineResponse 以传递有关空 dias 集合的信息)。

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

【讨论】:

  • 非常感谢,但我不明白你在哪里声明 var exroom = new roomItem[] {};
  • @bluewonder 它应该与代码示例中的 'var exroom = (from roomItem in' 在同一级别声明。
  • @Wojtek 这是我拥有的完整代码,notepad.cc/share/PdWWsP2f4Y,由于 exroom 与 HTML 中的元素一起返回,我一开始不知道如何声明它
【解决方案2】:

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

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

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

演示上述建议的代码:

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)
}

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2017-12-26
  • 2011-06-27
  • 2021-07-30
  • 2016-01-12
  • 1970-01-01
  • 1970-01-01
  • 2018-12-23
  • 1970-01-01
相关资源
最近更新 更多