Frage

Wie Deserialisieren ich dieses XML-Dokument:

<?xml version="1.0" encoding="utf-8"?>
<Cars>
  <Car>
    <StockNumber>1020</StockNumber>
    <Make>Nissan</Make>
    <Model>Sentra</Model>
  </Car>
  <Car>
    <StockNumber>1010</StockNumber>
    <Make>Toyota</Make>
    <Model>Corolla</Model>
  </Car>
  <Car>
    <StockNumber>1111</StockNumber>
    <Make>Honda</Make>
    <Model>Accord</Model>
  </Car>
</Cars>

Ich habe diese:

[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;
    }
}

, die scheinen nicht zu funktionieren: - (

War es hilfreich?

Lösung

Hier ist eine Arbeitsversion. Ich habe die XmlElementAttribute Etiketten XmlElement weil in der xml der Stock Number, Marke und Modell Werte sind Elemente, Attribute nicht. Auch entfernte ich die reader.ReadToEnd (); (Die Funktion liest den ganzen Strom und kehrt ein String, so dass die Deserialze () Funktion, um den Leser nicht mehr benutzen kann ... war die Position am Ende des Streams). Ich habe auch ein paar Freiheiten mit der Namensgebung:)

.

Hier sind die Klassen:

[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 Funktion:

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 die leicht gezwickt xml (ich brauchte ein neues Element hinzuzufügen, zu wickeln ... Net ist pingelig Deserialisieren Arrays):

<?xml version="1.0" encoding="utf-8"?>
<CarCollection>
<Cars>
  <Car>
    <StockNumber>1020</StockNumber>
    <Make>Nissan</Make>
    <Model>Sentra</Model>
  </Car>
  <Car>
    <StockNumber>1010</StockNumber>
    <Make>Toyota</Make>
    <Model>Corolla</Model>
  </Car>
  <Car>
    <StockNumber>1111</StockNumber>
    <Make>Honda</Make>
    <Model>Accord</Model>
  </Car>
</Cars>
</CarCollection>

Andere Tipps

Wie wäre es einfach die XML in einer Datei speichern, und verwenden Sie xsd C # -Klassen zu generieren?

  1. Schreiben Sie die Datei auf die Festplatte (ich nannte es foo.xml)
  2. Generieren Sie das xsd: xsd foo.xml
  3. Erstellen Sie den C #: xsd foo.xsd /classes

Et voilà - und C # -Code-Datei, die 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);
    }

(einschließlich der generierten foo.cs im Projekt)

Sie haben zwei Möglichkeiten.

Methode 1. XSD Werkzeug


Nehmen wir an, dass Sie Ihre XML-Datei in diesem Ort C:\path\to\xml\file.xml haben

  1. Öffnen Entwickler-Eingabeaufforderung
    Sie können es in Start Menu > Programs > Microsoft Visual Studio 2012 > Visual Studio Tools finden Oder wenn Sie Windows 8 kann nur beginnen eingeben Entwickler-Eingabeaufforderung in Startbildschirm
  2. Standort ändern, um die XML-Dateiverzeichnis von cd /D "C:\path\to\xml" eingeben
  3. Erstellen XSD-Datei aus der XML-Datei durch xsd file.xml eingeben
  4. Erstellen C # -Klassen , indem Sie xsd /c file.xsd

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

Methode 2 - Inhalte einfügen


Erforderlich Visual Studio 2012+

  1. Kopieren Inhalt Ihrer XML-Datei in die Zwischenablage kopieren
  2. Fügen Sie zu Ihrer Lösung neue, leere Klassendatei ( Umschalttaste + Alt + C )
  3. Öffnen Sie die Datei und in Menü klicken Edit > Paste special > Paste XML As Classes
    eingeben Bild Beschreibung hier

Und das ist es!

Verwendung


Die Benutzung 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<T>(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<T>(this string @this) where T : class
        {
            return JSON.Deserialize<T>(@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<catalog>();

    string json = File.ReadAllText(@"D:\file.json");
    var catalog2 = json.ParseJSON<JSONRoot>();

Das folgende Snippet sollte es tun (und Sie können die meisten der Serialisierung Attribute 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; }
}

Und in Ermangelung eines solchen, die xsd.exe Programm verwenden, das mit Visual Studio kommt ein Schema-Dokument zu erstellen auf der Grundlage dieser XML-Datei, und es dann wieder verwenden, um eine Klasse zu erstellen, basierend auf dem Schema-Dokument.

Ich glaube nicht, .net ‚pingelig Deserialisieren Arrays‘ ist. Das erste XML-Dokument ist nicht gut ausgebildet. Es gibt kein Wurzelelement, obwohl es, wie es aussieht, ist. Das kanonische XML-Dokument hat eine Wurzel und mindestens 1 Element (wenn überhaupt). In Ihrem Beispiel:

<Root> <-- well, the root
  <Cars> <-- an element (not a root), it being an array
    <Car> <-- an element, it being an array item
    ...
    </Car>
  </Cars>
</Root>

versuchen, diesen Code-Block, wenn Ihre XML-Datei in der Scheibe irgendwo erzeugt worden ist, und wenn Sie List<T> verwendet haben:

//deserialization

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

Hinweis: C:\serialize.xml ist meine XML-Datei in den Weg. Sie können es für Ihre Bedürfnisse ändern.

Kevins Anser ist gut, abgesehen von der Tatsache, dass in der realen Welt, Sie sind oft nicht in der Lage, die ursprüngliche XML zu ändern, um Ihre Bedürfnisse gerecht zu werden.

Es gibt eine einfache Lösung für das ursprüngliche XML, auch:

[XmlRoot("Cars")]
public class XmlData
{
    [XmlElement("Car")]
    public List<Car> 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 rufen Sie einfach an:

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

Versuchen Sie, diese allgemeine Klasse für die XML-Serialisierung und Deserialisierung.

public class SerializeConfig<T> 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;
    }
}

für Anfänger

Ich fand hier die Antworten sehr hilfreich sein, dass das Ich kämpfte noch (nur ein wenig), um diese Funktion zu erhalten. Also, falls es hilft jemand Ich werde die Arbeitslösung buchstabieren:

XML von der ursprünglichen Frage. Die XML wird in einer Datei Class1.xml, ein path auf diese Datei im Code verwendet wird, diese XML-Datei zu suchen.

habe ich die Antwort von @erymski diese Funktion zu erhalten, so eine Datei erstellt namens Car.cs und addierten die folgenden:

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 Stück Code zur Verfügung gestellt von @erymski ...

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

... geht in das Hauptprogramm (Program.cs), in static CarCollection XCar() wie folgt aus:

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

Hoffe, es hilft: -)

Die Idee ist, alle Level haben für die Deserialisierung gehandhabt werden Bitte beachten Sie eine Probenlösung, die mein ähnliches Problem gelöst

<?xml version="1.0" ?> 
 <TRANSACTION_RESPONSE>
    <TRANSACTION>
        <TRANSACTION_ID>25429</TRANSACTION_ID> 
        <MERCHANT_ACC_NO>02700701354375000964</MERCHANT_ACC_NO> 
        <TXN_STATUS>F</TXN_STATUS> 
        <TXN_SIGNATURE>a16af68d4c3e2280e44bd7c2c23f2af6cb1f0e5a28c266ea741608e72b1a5e4224da5b975909cc43c53b6c0f7f1bbf0820269caa3e350dd1812484edc499b279</TXN_SIGNATURE> 
        <TXN_SIGNATURE2>B1684258EA112C8B5BA51F73CDA9864D1BB98E04F5A78B67A3E539BEF96CCF4D16CFF6B9E04818B50E855E0783BB075309D112CA596BDC49F9738C4BF3AA1FB4</TXN_SIGNATURE2> 
        <TRAN_DATE>29-09-2015 07:36:59</TRAN_DATE> 
        <MERCHANT_TRANID>150929093703RUDZMX4</MERCHANT_TRANID> 
        <RESPONSE_CODE>9967</RESPONSE_CODE> 
        <RESPONSE_DESC>Bank rejected transaction!</RESPONSE_DESC> 
        <CUSTOMER_ID>RUDZMX</CUSTOMER_ID> 
        <AUTH_ID /> 
        <AUTH_DATE /> 
        <CAPTURE_DATE /> 
        <SALES_DATE /> 
        <VOID_REV_DATE /> 
        <REFUND_DATE /> 
        <REFUND_AMOUNT>0.00</REFUND_AMOUNT> 
    </TRANSACTION>
  </TRANSACTION_RESPONSE> 

Die obige XML wird in zwei Ebenen behandelt

  [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; }

}

Same Way müssen Sie mehrere Level mit car as array Markieren Sie dieses Beispiel für Multi-Level-Deserialisierung

Wenn Sie Fehler bekommen xsd.exe mit Ihrem XSD-Datei zu erstellen, verwenden Sie dann die XmlSchemaInference Klasse wie erwähnt auf Msdn . Hier ist ein Unit-Test 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 ändern für Sie Autos auto Eigentum von XmlArrayItem zu XmlElment. Das heißt, von

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

[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 die Klasse in Ihrem Code zu bekommen
  2. Versuchen Sie so etwas wie dieses: Erstellen Sie eine Liste dieser Klasse (List<class1>), dann die XmlSerializer verwenden Sie diese Liste in eine xml Datei zu serialisiert
  3. .
  4. Jetzt ersetzen Sie nur den Körper der Datei mit Ihren Daten und versuchen, es 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 Aufmerksamkeit auf die Root-Name zahlen müssen, tun Sie es nicht ändern. Meins ist "ArrayOfClass1"

Wie über eine generische Klasse ein XML-Dokument deserialisieren

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Generic class to load any xml into a class
// used like this ...
// YourClassTypeHere InfoList = LoadXMLFileIntoClass<YourClassTypeHere>(xmlFile);

using System.IO;
using System.Xml.Serialization;

public static T LoadXMLFileIntoClass<T>(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 nicht notwendig sein. Öffnen Sie das XML-Dokument in Visual Studio mit der rechten klicken Sie auf das XML, wählen Sie Eigenschaften. Dann wählen Sie Ihre Schemadatei.

async public static Task<JObject> XMLtoNETAsync(XmlDocument ToConvert)
        {
            //Van XML naar JSON
            string jsonText = await Task.Run(() => JsonConvert.SerializeXmlNode(ToConvert));
            //Van JSON naar .net object
            var o = await Task.Run(() => JObject.Parse(jsonText));
            return o;
        }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top