【问题标题】:Select Parent XML Elements based on Child element values LINQ C#根据子元素值 LINQ C# 选择父 XML 元素
【发布时间】:2013-03-13 17:51:02
【问题描述】:

在使用 LINQ 过滤相当大的 XML 文档时遇到一些困难。

这是我的 XML(其中的一部分)...

  <?xml version="1.0" encoding="UTF-8"?>
<response xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XML-Schema-instance" version="1.2" xsi:noNamespaceSchemaLocation="http://weather.aero/schema/metar1_2.xsd">
  <request_index>54966812</request_index>
  <data_source name="metars" />
  <request type="retrieve" />
  <errors />
  <warnings />
  <time_taken_ms>3</time_taken_ms>
  <data num_results="6">
    <METAR>
      <raw_text>KDEN 131653Z 06007KT 9SM FEW080 SCT140 BKN250 09/01 A3025 RMK AO2 SLP238 T00940006</raw_text>
      <station_id>KDEN</station_id>
      <observation_time>2013-03-13T16:53:00Z</observation_time>
      <latitude>39.83</latitude>
      <longitude>-104.65</longitude>
      <temp_c>9.4</temp_c>
      <dewpoint_c>0.6</dewpoint_c>
      <wind_dir_degrees>60</wind_dir_degrees>
      <wind_speed_kt>7</wind_speed_kt>
      <visibility_statute_mi>9.0</visibility_statute_mi>
      <altim_in_hg>30.250984</altim_in_hg>
      <sea_level_pressure_mb>1023.8</sea_level_pressure_mb>
      <quality_control_flags>
        <auto_station>TRUE</auto_station>
      </quality_control_flags>
      <sky_condition sky_cover="FEW" cloud_base_ft_agl="8000" />
      <sky_condition sky_cover="SCT" cloud_base_ft_agl="14000" />
      <sky_condition sky_cover="BKN" cloud_base_ft_agl="25000" />
      <flight_category>VFR</flight_category>
      <metar_type>METAR</metar_type>
      <elevation_m>1640.0</elevation_m>
    </METAR>
    <METAR>
      <raw_text>KSEA 131653Z 20006KT 10SM FEW008 BKN070 OVC200 11/08 A3019 RMK AO2 SLP232 T01060083</raw_text>
      <station_id>KSEA</station_id>
      <observation_time>2013-03-13T16:53:00Z</observation_time>
      <latitude>47.45</latitude>
      <longitude>-122.32</longitude>
      <temp_c>10.6</temp_c>
      <dewpoint_c>8.3</dewpoint_c>
      <wind_dir_degrees>200</wind_dir_degrees>
      <wind_speed_kt>6</wind_speed_kt>
      <visibility_statute_mi>10.0</visibility_statute_mi>
      <altim_in_hg>30.188976</altim_in_hg>
      <sea_level_pressure_mb>1023.2</sea_level_pressure_mb>
      <quality_control_flags>
        <auto_station>TRUE</auto_station>
      </quality_control_flags>
      <sky_condition sky_cover="FEW" cloud_base_ft_agl="800" />
      <sky_condition sky_cover="BKN" cloud_base_ft_agl="7000" />
      <sky_condition sky_cover="OVC" cloud_base_ft_agl="20000" />
      <flight_category>VFR</flight_category>
      <metar_type>METAR</metar_type>
      <elevation_m>136.0</elevation_m>
    </METAR>

我要做的是获取所有在纬度和经度范围内的 METAR 元素。例如:

纬度 > 52 && -123

我们的想法是捕获给定区域的 METAR。

这是我的代码:

     double southLat = 52.09;
     double northLat = 53.95;
     double westLong = -123.17;
     double eastLong = -121.87;

     XDocument response = XDocument.Load("file");

     var metars = response.Descendants("METAR")
        .Where
        (l => l.Element("latitude") != null || l.Element("longitude") != null
        && (Double)l.Element("latitude") >= southLat 
        && (Double)l.Element("latitude") <= northLat
        && (Double)l.Element("longitude") >= westLong
        && (Double)l.Element("longitude") <= eastLong
   );

我设法让第一部分工作(排除具有空纬度或经度值的元素....但是我仍然得到超出我想要的范围的 METAR。

有什么建议吗?

【问题讨论】:

  • l => l.Element("纬度") != null || l.Element(“经度”)!= null。更改 ||到 &&。
  • 做到了。我很困惑为什么......我认为 !=null 排除了任何没有 Lat 或 Long 的 METAR ......鉴于此 - 我希望根据指定的标准过滤结果项目。跨度>

标签: c# xml linq lambda


【解决方案1】:

正如@roughnex 在 cmets 中所说,以下行:

l.Element("latitude") != null || l.Element("longitude") != null

需要改成:

l.Element("latitude") != null && l.Element("longitude") != null

原因是how boolean logic works

在您的代码中,您有以下条件语句:

l.Element("latitude") != null || l.Element("longitude") != null
&& (Double)l.Element("latitude") >= southLat 
&& (Double)l.Element("latitude") <= northLat
&& (Double)l.Element("longitude") >= westLong
&& (Double)l.Element("longitude") <= eastLong

但是让我们删掉细节,让每个字母都是一个条件的地方更简单:

A || B && C && D && F

当它被简化为更简单的术语时,更容易看出如果A 解析为True,则条件的其余部分将被忽略。这就是为什么你得到的结果超出了你想要的区域,因为它们的纬度不是空的。

【讨论】:

  • 这绝对有道理。我并不声称自己擅长这一点(显然)。但是-我从未真正遇到过诸如我所遇到的逻辑错误。我的印象是必须满足所有条件 - 而不仅仅是遇到的第一个条件为真。感谢您的澄清。
【解决方案2】:

作为参考,这是一个称为短路的编程概念。在布尔逻辑中,如果你有一个条件

A || B

如果 A 的计算结果为真,则不会计算 B,因为无论 B 的值如何,表达式 (A || B) 都将为真。同样,如果

A && B

并且 A 的计算结果为 false,则 B 不会被计算,因为整个表达式将计算为 false,而不管 B 的值如何。 (false && true 永远都是 false。)

如果

A || B 

并且 A 为假,那么 B 必须被评估,因为在 OR 比较中,只有一个为真,整个表达式为真(假 || 真为真)。所以既然A是假的,那么B仍然有可能是真的,所以我们必须检查一下。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    相关资源
    最近更新 更多