使用已知的XSD从XML读取类型化对象

Ste*_*n_W 29 c# xml xsd xmldocument compact-framework

我有以下(作为示例)XML文件和XSD.

<?xml version="1.0" encoding="utf-8" ?>
<foo>
  <DateVal>2010-02-18T01:02:03</DateVal>
  <TimeVal>PT10H5M3S</TimeVal>
</foo>
Run Code Online (Sandbox Code Playgroud)

version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="foo">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="DateVal" type="xs:dateTime" />
        <xs:element name="TimeVal" type="xs:duration" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>
Run Code Online (Sandbox Code Playgroud)

然后是以下C#代码:

  static void Main(string[] args)
  {
     XmlDocument xd = new XmlDocument();
     XmlSchema xs;
     using (var fs = File.OpenRead(FilePath + "SimpleFields.xsd"))
     {
        xs = XmlSchema.Read(fs, null);
     }

     xd.Schemas.Add(xs);
     xd.Load((FilePath + "SimpleFields.xml"));
     xd.Validate(null);

     var el_root = xd.DocumentElement;

     var el_date = (XmlElement)el_root.SelectSingleNode("./DateVal");
     //WANTED: el_date.Value = 2010-02-18 01:02:03 (as a DateTime Object)
     //ACTUAL: el_date.InnerText="2010-02-18T01:02:03"

     var el_duration = (XmlElement)el_root.SelectSingleNode("./TimeVal");
     //WANTED: el_date.Value = 10 hours, 5 minutes, 3 seconds (as a TimeSpan Object)
     //ACTUAL: el_date.InnerText="PT10H5M3S"

     Console.WriteLine("DONE");
     Console.ReadLine();
  }
Run Code Online (Sandbox Code Playgroud)

如何将数据作为强类型对象读取?

我将针对WindowsMo​​bile设备,但这不应该太多地影响答案.(可以是.NET 2.0或3.5 ......不确定Sstem.Xml.Linq是否有帮助)

mar*_*c_s 58

您需要执行两个步骤:

1)获取您的XML模式文件并通过该xsd.exe实用程序(它随Windows SDK一起提供 - C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\或者在类似的路径中运行它.这可以将XSD文件转换为C#类:

xsd /c yourfile.xsd
Run Code Online (Sandbox Code Playgroud)

这应该为您提供一个文件yourfile.cs,其中包含一个表示该XML架构的类.

2)现在,使用该C#类,您应该能够将XML文件反序列化为新对象的实例:

XmlSerializer ser = new XmlSerializer(typeof(foo));

string filename = Path.Combine(FilePath, "SimpleFields.xml");

foo myFoo = ser.Deserialize(new FileStream(filename, FileMode.Open)) as foo;

if (myFoo != null)
{
   // do whatever you want with your "foo"
}
Run Code Online (Sandbox Code Playgroud)

这就像它得到的一样简单!:-)

  • 正如marc_s猜测的那样,这个问题与代码生成有关.我曾尝试过xsd.exe我也查看了其他问题,如[xsd codegenerators - C#的比较](http://stackoverflow.com/questions/386155/comparison-of-xsd-codegenerators-c),但大多数这些选项似乎使用XmlSerializer.这本身并不是一件坏事,但我想知道是否还有另一种方法可以解决更多的控制(而不仅仅是绑定到XmlSerializer类的各种事件. (2认同)
  • 这在运行时不使用 xsd。它不提供验证。 (2认同)

Ste*_*n_W 9

好的 - 找到我想要的答案.

它是XmlConvert类.

     var el_date = (XmlElement)el_root.SelectSingleNode("./DateVal");
     //WANTED: el_date.Value = 2010-02-18 01:02:03 (as a DateTime Object)
     var val_date = XmlConvert.ToDateTime(el_date.InnerText);
     //ACTUAL: el_date.InnerText="2010-02-18T01:02:03"

     var el_duration = (XmlElement)el_root.SelectSingleNode("./TimeVal");
     //WANTED: el_date.Value = 10 hours, 5 minutes, 3 seconds (as a TimeSpan Object)
     var val_duration = XmlConvert.ToTimeSpan(el_duration.InnerText);
     //ACTUAL: el_date.InnerText="PT10H5M3S"
Run Code Online (Sandbox Code Playgroud)

Marc的答案在读取整个强类型类中是正确的,但在这种情况下我只想读取一个强类型元素/节点.