XML 元素选择 [英] XML Element Selection

查看:23
本文介绍了XML 元素选择的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在从天气网站 xml 文件中收集 XML 数据 此处.

I am collecting XML data from a weather website xml file here.

我创建了以下代码,用于查找 'temp_c' 的第一个实例并返回该值.这是当前时刻的温度.

I have created the following code, which finds the first instance of 'temp_c' and returns the value. This is the temperature at the current moment.

using (XmlReader reader = XmlReader.Create(new StringReader(weather)))
   {
      while (reader.Read())
      {
         switch (reader.NodeType)
            {
               case XmlNodeType.Element:
                 if (reader.Name.Equals("temp_c"))
                 {
                    reader.Read();
                    temp_c = reader.Value;
                 }
                 break;
            }
     }
}
return temp_c

这会将名为temp_c"的 XML 文件中第一个实例的值返回到名为temp_c"的字符串

This returns the value of the first instance in the XML file called "temp_c" to the string called "temp_c"

我现在想要做的是使用 XML 文档中名为period"的元素,以及使用名为fcttext"的句点找到的元素.当period = 0"表示今天",1 = 明天等;我在寻找与该周期值相关联的fcttext_metric"数据.

What I would now like to do is use the Element in the XML document called "period" and the element found with period called "fcttext". When "period = 0" it means "today", 1 = tomorrow, etc; and I am after the "fcttext_metric" data that is associated with that period value.

我一直在努力将我找到的示例和 XML 读取代码处理到我这里的当前代码中.任何人都可以指出我正确的方向吗?

I've been struggling to work the examples and XML reading codes I've found into the current code that I have here. Can anyone please point me in the right direction?

编辑

以下是 XML 文件的示例:

Here is an example of the XML file:

<forecast>
   <forecastday>
      <period>0</period>
      <fcttext_metric>Sunny</fcttext_metric>
   <forecastday>
      <period>1</period>
      <fcttext_metric>Cloudy</fcttext_metric>

推荐答案

这最终比我原先预期的更烦人,但是您可以使用 DataContractSerializer 和一个从 XML 创建对象图与您正在阅读的 XML 匹配的一组类.

This ended up being more annoying that I originally expected, but you can create an object graph from the XML using a DataContractSerializer and a set of classes that match the XML you are reading.

首先,使用适当的 DataContract 属性创建类.

First, you create your classes, with appropriate DataContract attributes.

[DataContract(Name = "response", Namespace = "")]
public class WeatherData
{
    [DataMember(Name = "forecast")]
    public Forecast Forecast { get; set; }
}

[DataContract(Name = "forecast", Namespace = "")]
public class Forecast
{
    [DataMember(Name = "txt_forecast")]
    public TxtForecast TxtForecast { get; set; }
}

[DataContract(Name = "txt_forecast", Namespace = "")]
public class TxtForecast
{
    [DataMember(Name = "forecastdays")]
    public ForecastDay[] ForecastDays { get; set; }
}

[DataContract(Name = "forecastday", Namespace = "")]
public class ForecastDay
{
    [DataMember(Name = "period", Order = 1)]
    public int Period { get; set; }

    public string FctText { get; set; }

    [DataMember(Name = "fcttext", EmitDefaultValue = false, Order = 5)]
    private CDataWrapper FctTextWrapper
    {
        get { return FctText; }
        set { FctText = value; }
    }
}

这里变得复杂了.fcttext 元素是 CDATA,DataContractSerializer 默认不支持.

Heres where it got complicated. The fcttext element is CDATA, which the DataContractSerializer doesn't support by default.

使用 将 CDATA 与 WCF REST 入门套件一起使用,您创建一个 CDataWrapper 类.我不会在这里重复代码(因为那将毫无意义),只需按照链接即可.

Using the wonderful answer available at Using CDATA with WCF REST starter kits, you create a CDataWrapper class. I won't repeat the code here (because that would be pointless), just follow the link.

您可以看到我已经使用了上面的 CDataWrapper 类来处理 fcttext 元素.

You can see that I've already used the CDataWrapper class above in order to work with the fcttext element.

一旦您完成了类结构设置,您就可以使用以下代码来提取您想要的信息.此时您只是在浏览对象图,因此您可以使用任何您想要的 C#(我使用了一个简单的 LINQ 查询来查找 Period 0 并为其打印出 fcttext).

Once you've got the class structure setup you can use the following code to extract the information you were after. You're just navigating the object graph at this point, so you can use whatever C# you want (I've used a simple LINQ query to find Period 0 and print out the fcttext for it).

var s = new DataContractSerializer(typeof(WeatherData));
var reader = XmlReader.Create("http://api.wunderground.com/api/74e1025b64f874f6/forecast/conditions/q/zmw:00000.1.94787.xml");
var o = (WeatherData)s.ReadObject(reader);

var firstPeriod = o.Forecast.TxtForecast.ForecastDays.Where(a => a.Period == 0).Single();
Console.WriteLine(firstPeriod.FctText);

您可以根据需要扩展这些类,以便您可以访问 XML 中的其他字段.只要 DataMember 名称与 XML 字段匹配,它就可以正常工作.

You can extend the classes as necessary to give you access to additional fields inside the XML. As long as the DataMember names match the XML fields it will all work.

以下是我遇到的一些问题的简短摘要,供感兴趣的人参考:

Here's a short summary of some problems I ran into for anyone interested:

  • 我必须将所有类的命名空间属性设置为空字符串,因为 XML 中没有任何命名空间信息.
  • Order 属性在 ForecastDay 类中很重要.如果它们被省略,DataContractSerializer 最终根本不会读取 fcttext 字段(因为它认为 fcttext 应该排在第一位?不知道为什么要诚实).
  • I had to set the Namespace attributes of all of the classes to the empty string, because the XML doesn't have any namespace info in it.
  • The Order attributes were important on the ForecastDay class. If they are omitted, the DataContractSerializer ends up not reading the fcttext field in at all (because it thinks fcttext should come first? not sure why to be honest).

这篇关于XML 元素选择的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆