web-dev-qa-db-fra.com

Lire des objets typés à partir de XML à l'aide de XSD connu

J'ai le fichier XML (et à titre d'exemple) suivant et XSD.

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

et

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>

Ensuite, le code C # suivant:

  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();
  }

Comment lire les données comme des objets fortement typés?

Je vais cibler un appareil WindowsMobile, mais cela ne devrait pas trop affecter la réponse. (peut être .NET 2.0 ou 3.5 ... Je ne sais pas si Sstem.Xml.Linq va aider ou non)

30
Steven_W

OK - J'ai trouvé la réponse que je cherchais.

c'est la classe 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"

La réponse de Marc était correcte en termes de lecture dans toute une classe fortement typée, mais dans ce cas, je ne voulais lire qu'un seul élément/nœud fortement typé.

9
Steven_W

Vous devez effectuer deux étapes:

1) Prenez votre fichier de schéma XML et exécutez-le via xsd.exe utilitaire (fourni avec le SDK Windows - il est dans C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\ ou un chemin similaire. Cela peut transformer le fichier XSD en une classe C #:

xsd /c yourfile.xsd

Cela devrait vous donner un fichier yourfile.cs qui contient une classe représentant ce schéma XML.

2) Maintenant, armé de cette classe C #, vous devriez pouvoir simplement désérialiser le fichier XML en une instance de votre nouvel objet:

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"
}

C'est aussi simple que cela! :-)

56
marc_s