Wie man ein XML-Dokument deserialisiert

Wie demeralisiere ich dieses XML-Dokument:

   1020 Nissan Sentra   1010 Toyota Corolla   1111 Honda Accord   

Ich habe das:

 [Serializable()] public class Car { [System.Xml.Serialization.XmlElementAttribute("StockNumber")] public string StockNumber{ get; set; } [System.Xml.Serialization.XmlElementAttribute("Make")] public string Make{ get; set; } [System.Xml.Serialization.XmlElementAttribute("Model")] public string Model{ get; set; } } 

.

 [System.Xml.Serialization.XmlRootAttribute("Cars", Namespace = "", IsNullable = false)] public class Cars { [XmlArrayItem(typeof(Car))] public Car[] Car { get; set; } } 

.

 public class CarSerializer { public Cars Deserialize() { Cars[] cars = null; string path = HttpContext.Current.ApplicationInstance.Server.MapPath("~/App_Data/") + "cars.xml"; XmlSerializer serializer = new XmlSerializer(typeof(Cars[])); StreamReader reader = new StreamReader(path); reader.ReadToEnd(); cars = (Cars[])serializer.Deserialize(reader); reader.Close(); return cars; } } 

das scheint nicht zu funktionieren 🙁

    Hier ist eine funktionierende Version. Ich habe die XmlElementAttribute-Labels in XmlElement geändert, da in der XML-Datei die StockNumber-, Make- und Model-Werte Elemente und keine Attribute sind. Auch ich entfernte den Leser. ReadToEnd (); (Diese function liest den gesamten Stream und gibt einen String zurück, so dass die Deserialze () – function den Reader nicht mehr benutzen konnte … die Position war am Ende des Streams). Ich habe auch ein paar Freiheiten mit der Namensgebung genommen :).

    Hier sind die classn:

     [Serializable()] public class Car { [System.Xml.Serialization.XmlElement("StockNumber")] public string StockNumber { get; set; } [System.Xml.Serialization.XmlElement("Make")] public string Make { get; set; } [System.Xml.Serialization.XmlElement("Model")] public string Model { get; set; } } [Serializable()] [System.Xml.Serialization.XmlRoot("CarCollection")] public class CarCollection { [XmlArray("Cars")] [XmlArrayItem("Car", typeof(Car))] public Car[] Car { get; set; } } 

    Die Deserialize-function:

     CarCollection cars = null; string path = "cars.xml"; XmlSerializer serializer = new XmlSerializer(typeof(CarCollection)); StreamReader reader = new StreamReader(path); cars = (CarCollection)serializer.Deserialize(reader); reader.Close(); 

    Und das leicht modifizierte Xml (Ich musste ein neues Element hinzufügen, um … zu verweben. Net ist wählerisch beim Deserialisieren von Arrays):

     < ?xml version="1.0" encoding="utf-8"?>    1020 Nissan Sentra   1010 Toyota Corolla   1111 Honda Accord    

    Wie wäre es, wenn Sie das XML einfach in eine Datei speichern und xsd verwenden ?

    1. Schreibe die Datei auf die Festplatte (ich habe sie foo.xml genannt)
    2. Generiere die Datei xsd: xsd foo.xml
    3. Generiere die C #: xsd foo.xsd /classes

    Et voila – und C # -Code-Datei, die in der Lage sein sollte, die Daten über XmlSerializer zu lesen:

      XmlSerializer ser = new XmlSerializer(typeof(Cars)); Cars cars; using (XmlReader reader = XmlReader.Create(path)) { cars = (Cars) ser.Deserialize(reader); } 

    (Fügen Sie die generierten foo.cs in das Projekt ein)

    Du hast zwei Möglichkeiten.

    Methode 1. XSD- Tool


    Angenommen, Sie haben Ihre XML-Datei an diesem Speicherort C:\path\to\xml\file.xml

    1. Öffnen Sie die Eingabeaufforderung des Entwicklers
      Sie finden es unter Start Menu > Programs > Microsoft Visual Studio 2012 > Visual Studio Tools Oder wenn Sie Windows 8 haben, können Sie einfach mit der Eingabe von Developer Command Prompt auf dem Startbildschirm beginnen
    2. Ändern Sie den Speicherort in Ihr XML-Dateiverzeichnis, indem Sie cd /D "C:\path\to\xml" eingeben
    3. Erstellen Sie eine XSD-Datei aus Ihrer XML-Datei, indem xsd file.xml
    4. Erstellen Sie C # -classn, indem Sie xsd /c file.xsd

    Und das ist es! Sie haben C # -classn aus der XML-Datei in C:\path\to\xml\file.cs

    Methode 2 – Inhalte einfügen


    Erforderliches Visual Studio 2012+

    1. Kopieren Sie den Inhalt Ihrer XML-Datei in die Zwischenablage
    2. Fügen Sie Ihrer Lösung eine neue, leere classndatei hinzu ( Umschalt + Alt + C )
    3. Öffnen Sie diese Datei und klicken Sie im Menü auf Edit > Paste special > Paste XML As Classes
      Bildbeschreibung hier eingeben

    Und das ist es!

    Verwendung


    Die Verwendung ist sehr einfach mit dieser Hilfsklasse:

     using System; using System.IO; using System.Web.Script.Serialization; // Add reference: System.Web.Extensions using System.Xml; using System.Xml.Serialization; namespace Helpers { internal static class ParseHelpers { private static JavaScriptSerializer json; private static JavaScriptSerializer JSON { get { return json ?? (json = new JavaScriptSerializer()); } } public static Stream ToStream(this string @this) { var stream = new MemoryStream(); var writer = new StreamWriter(stream); writer.Write(@this); writer.Flush(); stream.Position = 0; return stream; } public static T ParseXML(this string @this) where T : class { var reader = XmlReader.Create(@this.Trim().ToStream(), new XmlReaderSettings() { ConformanceLevel = ConformanceLevel.Document }); return new XmlSerializer(typeof(T)).Deserialize(reader) as T; } public static T ParseJSON(this string @this) where T : class { return JSON.Deserialize(@this.Trim()); } } } 

    Alles, was Sie jetzt tun müssen, ist:

      public class JSONRoot { public catalog catalog { get; set; } } // ... string xml = File.ReadAllText(@"D:\file.xml"); var catalog1 = xml.ParseXML(); string json = File.ReadAllText(@"D:\file.json"); var catalog2 = json.ParseJSON(); 

    Das folgende Snippet sollte den Trick machen (und Sie können die meisten Serialisierungsattribute ignorieren):

     public class Car { public string StockNumber { get; set; } public string Make { get; set; } public string Model { get; set; } } [XmlRootAttribute("Cars")] public class CarCollection { [XmlElement("Car")] public Car[] Cars { get; set; } } 

     using (TextReader reader = new StreamReader(path)) { XmlSerializer serializer = new XmlSerializer(typeof(CarCollection)); return (CarCollection) serializer.Deserialize(reader); } 

    Sehen Sie, ob das hilft:

     [Serializable()] [System.Xml.Serialization.XmlRootAttribute("Cars", Namespace = "", IsNullable = false)] public class Cars { [XmlArrayItem(typeof(Car))] public Car[] Car { get; set; } } 

    .

     [Serializable()] public class Car { [System.Xml.Serialization.XmlElement()] public string StockNumber{ get; set; } [System.Xml.Serialization.XmlElement()] public string Make{ get; set; } [System.Xml.Serialization.XmlElement()] public string Model{ get; set; } } 

    Wenn dies nicht möglich ist, verwenden Sie das Programm “xsd.exe”, das mit Visual Studio geliefert wird, um ein Schemadokument basierend auf dieser XML-Datei zu erstellen, und verwenden Sie es dann erneut zum Erstellen einer class basierend auf dem Schemadokument.

    Ich glaube nicht, dass .net “wählerisch bei der Deserialisierung von Arrays” ist. Das erste XML-Dokument ist nicht gut formatiert. Es gibt kein Root-Element, obwohl es so aussieht. Das kanonische XML-Dokument hat eine Wurzel und mindestens ein Element (wenn überhaupt). In Ihrem Beispiel:

      < -- well, the root  < -- an element (not a root), it being an array  < -- an element, it being an array item ...    

    Probieren Sie diesen Code-Block aus, wenn Ihre .xml-Datei irgendwo auf der Festplatte erstellt wurde und Sie List :

     //deserialization XmlSerializer xmlser = new XmlSerializer(typeof(List)); StreamReader srdr = new StreamReader(@"C:\serialize.xml"); List p = (List)xmlser.Deserialize(srdr); srdr.Close();` 

    Hinweis: C:\serialize.xml ist der Pfad meiner XML-Datei. Sie können es für Ihre Bedürfnisse ändern.

    Kevins Anser ist gut, abgesehen davon, dass Sie in der realen Welt oft nicht in der Lage sind, das ursprüngliche XML an Ihre Bedürfnisse anzupassen.

    Auch für das ursprüngliche XML gibt es eine einfache Lösung:

     [XmlRoot("Cars")] public class XmlData { [XmlElement("Car")] public List Cars{ get; set; } } public class Car { public string StockNumber { get; set; } public string Make { get; set; } public string Model { get; set; } } 

    Und dann können Sie einfach anrufen:

     var ser = new XmlSerializer(typeof(XmlData)); XmlData data = (XmlData)ser.Deserialize(XmlReader.Create(PathToCarsXml)); 

    Versuchen Sie diese generische class für Xml Serialisierung und Deserialisierung.

     public class SerializeConfig where T : class { public static void Serialize(string path, T type) { var serializer = new XmlSerializer(type.GetType()); using (var writer = new FileStream(path, FileMode.Create)) { serializer.Serialize(writer, type); } } public static T DeSerialize(string path) { T type; var serializer = new XmlSerializer(typeof(T)); using (var reader = XmlReader.Create(path)) { type = serializer.Deserialize(reader) as T; } return type; } } 

    Die Idee ist, dass alle Ebenen für die Deserialisierung behandelt werden. Bitte sehen Sie sich eine Beispiellösung an, die mein ähnliches Problem getriggers hat

     < ?xml version="1.0" ?>   25429 02700701354375000964 F a16af68d4c3e2280e44bd7c2c23f2af6cb1f0e5a28c266ea741608e72b1a5e4224da5b975909cc43c53b6c0f7f1bbf0820269caa3e350dd1812484edc499b279 B1684258EA112C8B5BA51F73CDA9864D1BB98E04F5A78B67A3E539BEF96CCF4D16CFF6B9E04818B50E855E0783BB075309D112CA596BDC49F9738C4BF3AA1FB4 29-09-2015 07:36:59 150929093703RUDZMX4 9967 Bank rejected transaction! RUDZMX       0.00   

    Das obige XML wird auf zwei Ebenen gehandhabt

      [XmlType("TRANSACTION_RESPONSE")] public class TransactionResponse { [XmlElement("TRANSACTION")] public BankQueryResponse Response { get; set; } } 

    Die innere Ebene

     public class BankQueryResponse { [XmlElement("TRANSACTION_ID")] public string TransactionId { get; set; } [XmlElement("MERCHANT_ACC_NO")] public string MerchantAccNo { get; set; } [XmlElement("TXN_SIGNATURE")] public string TxnSignature { get; set; } [XmlElement("TRAN_DATE")] public DateTime TranDate { get; set; } [XmlElement("TXN_STATUS")] public string TxnStatus { get; set; } [XmlElement("REFUND_DATE")] public DateTime RefundDate { get; set; } [XmlElement("RESPONSE_CODE")] public string ResponseCode { get; set; } [XmlElement("RESPONSE_DESC")] public string ResponseDesc { get; set; } [XmlAttribute("MERCHANT_TRANID")] public string MerchantTranId { get; set; } } 

    Gleiches, wie Sie mehrere Ebenen mit car as array benötigen Überprüfen Sie dieses Beispiel für Multi-Level- Deserialisierung

    Wenn Sie mit xsd.exe Fehler beim Erstellen Ihrer xsd-Datei erhalten, verwenden Sie die XmlSchemaInference-class wie in msdn erwähnt . Hier ist ein Komponententest, um zu demonstrieren:

     using System.Xml; using System.Xml.Schema; [TestMethod] public void GenerateXsdFromXmlTest() { string folder = @"C:\mydir\mydata\xmlToCSharp"; XmlReader reader = XmlReader.Create(folder + "\some_xml.xml"); XmlSchemaSet schemaSet = new XmlSchemaSet(); XmlSchemaInference schema = new XmlSchemaInference(); schemaSet = schema.InferSchema(reader); foreach (XmlSchema s in schemaSet.Schemas()) { XmlWriter xsdFile = new XmlTextWriter(folder + "\some_xsd.xsd", System.Text.Encoding.UTF8); s.Write(xsdFile); xsdFile.Close(); } } // now from the visual studio command line type: xsd some_xsd.xsd /classes 

    Sie können nur ein Attribut für Ihre Auto-Auto-Eigenschaft von XmlArrayItem zu XmlElment ändern. Das heißt, von

     [System.Xml.Serialization.XmlRootAttribute("Cars", Namespace = "", IsNullable = false)] public class Cars { [XmlArrayItem(typeof(Car))] public Car[] Car { get; set; } } 

    zu

     [System.Xml.Serialization.XmlRootAttribute("Cars", Namespace = "", IsNullable = false)] public class Cars { [XmlElement("Car")] public Car[] Car { get; set; } } 

    Meine Lösung:

    1. Verwenden Sie Edit > Past Special > Paste XML As Classes einfügen, um die class in Ihrem Code zu erhalten
    2. Versuchen Sie List : Erstellen Sie eine Liste dieser class ( List >), und verwenden XmlSerializer dann den XmlSerializer um diese Liste in eine xml Datei zu serialisieren.
    3. Jetzt ersetzen Sie einfach den Körper dieser Datei durch Ihre Daten und versuchen, sie zu deserialize .

    Code:

     StreamReader sr = new StreamReader(@"C:\Users\duongngh\Desktop\Newfolder\abc.txt"); XmlSerializer xml = new XmlSerializer(typeof(Class1[])); var a = xml.Deserialize(sr); sr.Close(); 

    HINWEIS: Sie müssen auf den Stammnamen achten, ändern Sie ihn nicht. Meine ist "ArrayOfClass1"

    Für Anfänger

    Ich fand die Antworten hier sehr hilfreich, das heißt, ich habe mich immer noch angestrengt (nur ein bisschen), um das funktionieren zu lassen. Also, für den Fall, dass es jemandem hilft, werde ich die Arbeitslösung formulieren:

    XML von der ursprünglichen Frage. Das XML befindet sich in einer Datei Class1.xml, ein path zu dieser Datei wird im Code verwendet, um diese XML-Datei zu finden.

    Ich habe die Antwort von @erymski verwendet, um dies zum Laufen zu bringen. Also habe ich eine Datei namens Car.cs erstellt und folgendes hinzugefügt:

     using System.Xml.Serialization; // Added public class Car { public string StockNumber { get; set; } public string Make { get; set; } public string Model { get; set; } } [XmlRootAttribute("Cars")] public class CarCollection { [XmlElement("Car")] public Car[] Cars { get; set; } } 

    Das andere Bit von @erymski zur Verfügung gestellt …

     using (TextReader reader = new StreamReader(path)) { XmlSerializer serializer = new XmlSerializer(typeof(CarCollection)); return (CarCollection) serializer.Deserialize(reader); } 

    … geht in Ihr Hauptprogramm (Program.cs), in static CarCollection XCar() so:

     using System; using System.IO; using System.Xml.Serialization; namespace ConsoleApp2 { class Program { public static void Main() { var c = new CarCollection(); c = XCar(); foreach (var k in c.Cars) { Console.WriteLine(k.Make + " " + k.Model + " " + k.StockNumber); } c = null; Console.ReadLine(); } static CarCollection XCar() { using (TextReader reader = new StreamReader(@"C:\Users\SlowLearner\source\repos\ConsoleApp2\ConsoleApp2\Class1.xml")) { XmlSerializer serializer = new XmlSerializer(typeof(CarCollection)); return (CarCollection)serializer.Deserialize(reader); } } } } 

    Ich hoffe es hilft 🙂

    Wie wäre es mit einer generischen class zum Deserialisieren eines XML-Dokuments?

     //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Generic class to load any xml into a class // used like this ... // YourClassTypeHere InfoList = LoadXMLFileIntoClass(xmlFile); using System.IO; using System.Xml.Serialization; public static T LoadXMLFileIntoClass(string xmlFile) { T returnThis; XmlSerializer serializer = new XmlSerializer(typeof(T)); if (!FileAndIO.FileExists(xmlFile)) { Console.WriteLine("FileDoesNotExistError {0}", xmlFile); } returnThis = (T)serializer.Deserialize(new StreamReader(xmlFile)); return (T)returnThis; } 

    Dieser Teil kann oder muss nicht unbedingt notwendig sein. Öffnen Sie das XML-Dokument in Visual Studio, klicken Sie mit der rechten Maustaste auf das XML, und wählen Sie Eigenschaften. Wählen Sie dann Ihre Schemadatei.