【问题标题】:Read typed objects from XML using known XSD使用已知的 XSD 从 XML 读取类型化对象
【发布时间】:2010-02-19 18:25:26
【问题描述】:

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

<?xml version="1.0" encoding="utf-8" ?>
<foo>
  <DateVal>2010-02-18T01:02:03</DateVal>
  <TimeVal>PT10H5M3S</TimeVal>
</foo>

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>

然后是下面的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();
  }

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

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

【问题讨论】:

    标签: c# xml compact-framework xsd xmldocument


    【解决方案1】:

    你需要做两步:

    1) 获取您的 XML 架构文件并通过 xsd.exe 实用程序运行它(Windows SDK 随附 - 它位于 C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\ 或类似路径中。这可以将 XSD 文件转换为 C# 类:

    xsd /c yourfile.xsd
    

    这应该会为您提供一个文件 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"
    }
    

    就是这么简单! :-)

    【讨论】:

    • 正如 marc_s 猜测的那样,这个问题与代码生成有关。我试过 xsd.exe 我也看过其他问题,例如Comparison of xsd codegenerators - C#,但这些选项中的大多数似乎都使用了 XmlSerializer。这本身并不是一件坏事,但我想知道是否有另一种方法可以提供更多控制(而不是仅仅绑定到 XmlSerializer 类的各种事件。
    • 这在运行时不使用 xsd。它不提供验证。
    • 我已经安装了 Visual Studio 2013,我在 C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools 中找到了 xsd.exe util。所以: 1. 如果您有 64 位版本的 Windows,请尝试在 c:\Program Files (x86) 中找到此工具 2. 查看 C:\Program Files (x86)\Microsoft SDKs\Windows\ 中的所有子文件夹v6.0A
    【解决方案2】:

    好的 - 找到了我正在寻找的答案。

    它是 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"
    

    就阅读整个强类型类而言,Marc 的回答是正确的,但在这种情况下,我只想阅读单个强类型元素/节点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-28
      • 2020-02-22
      • 2013-08-27
      • 1970-01-01
      • 2011-06-21
      • 1970-01-01
      相关资源
      最近更新 更多