C# 解析XML和创建对象的更好方法?
我目前正在学习如何用C处理XML,并尝试从以下url解析和创建一个对象: 函数调用 解析 代码可以工作,但效率似乎有点低,因为我返回了一个必须使用的IEnumerable。使用这段代码,我也无法获得其他时间元素,其中from=和to=属性与该小时的预测相同,我希望获得至少未来三个小时的小时预测 我曾尝试使用xsd.exe从模式创建一个类,但这毫无意义,因此目前我坚持使用LocationForecast类C# 解析XML和创建对象的更好方法?,c#,.net,xml,xml-parsing,C#,.net,Xml,Xml Parsing,我目前正在学习如何用C处理XML,并尝试从以下url解析和创建一个对象: 函数调用 解析 代码可以工作,但效率似乎有点低,因为我返回了一个必须使用的IEnumerable。使用这段代码,我也无法获得其他时间元素,其中from=和to=属性与该小时的预测相同,我希望获得至少未来三个小时的小时预测 我曾尝试使用xsd.exe从模式创建一个类,但这毫无意义,因此目前我坚持使用LocationForecast类 是否有一种更有效的方法来执行此解析,并获得下一个每小时的预测?如果您不想处理XDocumen
是否有一种更有效的方法来执行此解析,并获得下一个每小时的预测?如果您不想处理XDocument及其元素,可以创建一个类层次结构,供XmlSerializer使用DataContractSerializer无法真正利用,因为它不支持XML属性,它将回退到XmlSerializer 好处是它将降低GetXmlData方法的复杂性。作为一个缺点,您不会得到更少的代码,而且您似乎希望值是双倍的,因此需要一些运算符魔术来支持隐式强制转换 GetXmlData 此方法现在将打开一个流并使用获取所有天气数据。获得后,它将获得Forecast集合中的第一个位置项。如果您需要其他物品,可以更改此项
public Location GetXmlData(string url)
{
Location loc;
using(var wc = new WebClient())
{
// Type you want to deserialize
var ser = new XmlSerializer(typeof(WeatherData));
using(var stream = wc.OpenRead(url))
{
// create the object, cast the result
var w = (WeatherData) ser.Deserialize(stream);
// w.Dump(); // linqpad testing
// what do we need
loc = w.Product.ForeCasts.First().Location;
}
}
return loc;
}
反序列化类
您的XML大致如下所示:
void Main()
{
var url = @"https://api.met.no/weatherapi/locationforecast/1.9/?lat=60.10&lon=9.58";
var loc = GetXmlData(url);
Double f = loc.Fog;
f.Dump("Percent as double");
Double t = loc.Temperature;
t.Dump("Temperature as double");
}
特例
location中的元素都具有相似的属性,因此我创建了一个主类来捕获所有这些变化:
// covers all kind of things
public class Measurement
{
[XmlAttribute("id")]
public string Id {get;set;}
[XmlAttribute("unit")]
public string Unit {get;set;}
[XmlAttribute("deg")]
public double Deg {get;set;}
[XmlAttribute("value")]
public double Value {get;set;}
[XmlAttribute("mps")]
public double Mps {get;set;}
[XmlAttribute("percent")]
public double Percent {get;set;}
}
具体测量
您的用例似乎表明您希望使用度量的某个属性(现在是属性)的双精度。为此,我将测量分为值和百分比。这里的类实现了一个,因此它不需要为这个类的使用者进行强制转换
// for properties that use the Value attribute
public class Value:Measurement
{
// operators for easy casting
public static implicit operator Value(Double d)
{
var v = new Value();
v.Value = d;
return v;
}
public static implicit operator Double(Value v)
{
return v.Value;
}
public override string ToString()
{
return this.Value.ToString();
}
}
// for properties that use the Percent attribute
public class Percent:Measurement
{
// operators for easy casting
public static implicit operator Percent(Double d)
{
var p = new Percent();
p.Percent = d;
return p;
}
public static implicit operator Double(Percent p)
{
return p.Percent;
}
public override string ToString()
{
return this.Percent.ToString();
}
}
小型测试方法如下所示:
void Main()
{
var url = @"https://api.met.no/weatherapi/locationforecast/1.9/?lat=60.10&lon=9.58";
var loc = GetXmlData(url);
Double f = loc.Fog;
f.Dump("Percent as double");
Double t = loc.Temperature;
t.Dump("Temperature as double");
}
如果您不认为属性不是double类型,那么可以重用LocationForecast类,但在这种情况下,您需要实例化并映射自己的值,例如:
var lf = new LocationForcast {
Temperature = loc.Temperature,
Precent = loc.Percent,
// etc.
};
或者使用像这样的库使用XmlSerializer或DataContractSerializerI强烈建议研究如何在c中反序列化xml。您将看到如何更好地处理这个问题,在这里您可以创建一个类来表示XML,这样您的生活将更加轻松。首先选择您感兴趣的所有节点,然后创建业务对象。由于xdoc.subjects.Firstx=>stringx.Attributedatatype==forecast,目前您只获取第一个节点;而不是先。。它应该在。。。。您甚至可以将部分查询提取到方法中,以使其更具可读性。
// for properties that use the Value attribute
public class Value:Measurement
{
// operators for easy casting
public static implicit operator Value(Double d)
{
var v = new Value();
v.Value = d;
return v;
}
public static implicit operator Double(Value v)
{
return v.Value;
}
public override string ToString()
{
return this.Value.ToString();
}
}
// for properties that use the Percent attribute
public class Percent:Measurement
{
// operators for easy casting
public static implicit operator Percent(Double d)
{
var p = new Percent();
p.Percent = d;
return p;
}
public static implicit operator Double(Percent p)
{
return p.Percent;
}
public override string ToString()
{
return this.Percent.ToString();
}
}
void Main()
{
var url = @"https://api.met.no/weatherapi/locationforecast/1.9/?lat=60.10&lon=9.58";
var loc = GetXmlData(url);
Double f = loc.Fog;
f.Dump("Percent as double");
Double t = loc.Temperature;
t.Dump("Temperature as double");
}
var lf = new LocationForcast {
Temperature = loc.Temperature,
Precent = loc.Percent,
// etc.
};