it-swarm.com.de

So deserialisieren Sie ein XML-Dokument

Wie kann ich dieses XML-Dokument deserialisieren?

<?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 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 :-(

413
Alex

Hier ist eine funktionierende Version. Ich habe die XmlElementAttribute-Beschriftungen in XmlElement geändert, da in der XML-Datei die Werte StockNumber, Make und Model Elemente und keine Attribute sind. Ich habe auch den Reader entfernt.ReadToEnd (); (Da function den gesamten Stream liest und einen String zurückgibt, konnte die Deserialze () - Funktion den Reader nicht mehr verwenden ... die Position befand sich am Ende des Streams. Ich habe auch ein paar Freiheiten mit der Benennung gemacht :).

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 etwas angepasste xml-Datei (Ich musste ein neues Element hinzufügen, um <Cars> einzuwickeln ... Das Netz ist wählerisch bei der Deserialisierung von 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>
321
Kevin Tighe

Wie wäre es, wenn Sie die XML-Datei in einer Datei speichern und mit xsd C # -Klassen erstellen?

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

Et voila - und C # -Codedatei, die die Daten über XmlSerializer lesen kann:

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

(füge die generierten foo.cs in das Projekt ein)

411
Marc Gravell

Das folgende Snippet sollte den Trick ausführen (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);
}
76
erymski

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

Andernfalls verwenden Sie das Programm xsd.exe, das im Lieferumfang von Visual Studio enthalten ist, um ein auf dieser XML-Datei basierendes Schemadokument zu erstellen, und verwenden Sie es erneut, um eine auf dem Schemadokument basierende Klasse zu erstellen.

22
Joel Coehoorn

Ich denke nicht, dass .net 'Deserialisierung von Arrays' wählerisch macht. Das erste XML-Dokument ist nicht gut ausgebildet. Es gibt kein Stammelement, obwohl es so aussieht, als wäre es vorhanden. Das kanonische XML-Dokument hat einen Stamm und mindestens ein Element (falls überhaupt). In deinem 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>
9
janbak

versuchen Sie diesen Codeblock, wenn Ihre XML-Datei irgendwo auf der Festplatte erstellt wurde und 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 der Pfad der XML-Datei. Sie können es für Ihre Bedürfnisse ändern. 

7
sheetal nainwal

Kevins Anser ist gut, abgesehen davon, dass Sie in der realen Welt die ursprüngliche XML-Datei häufig nicht an Ihre Bedürfnisse anpassen können.

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

[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 kannst du einfach anrufen:

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

Probieren Sie diese generische Klasse für die XML-Serialisierung und Deserialisierung aus. 

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;
    }
}
4
Hasan Javaid

Für Anfänger

Ich fand die Antworten hier sehr hilfreich und sagte, ich habe immer noch Schwierigkeiten (nur ein bisschen), um das zum Laufen zu bringen. Falls es jemandem hilft, formuliere ich die funktionierende Lösung:

XML aus der ursprünglichen Frage. Die XML-Datei befindet sich in einer Datei Class1.xml. Im Code wird eine path zu dieser Datei verwendet, um diese XML-Datei zu finden.

Ich habe die Antwort von @erymski verwendet, um diese Funktion zum Laufen zu bringen. Deshalb 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; }
}

Der andere Code von @erymski ...

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() wie folgt:

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 :-)

3
SlowLearner

Die Idee ist, dass alle Ebenen für die Deserialisierung behandelt werden

<?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> 

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

}

Genauso wie Sie mehrere Ebenen benötigen mit car as arrayÜberprüfen Sie dieses Beispiel für mehrstufige Deserialisierung

2
makdu

Sie können nur ein Attribut für Ihre Autos-Autos Eigenschaft von XmlArrayItem in Xml Element ä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; }
}
1
XU Weijiang
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;
        }
1

Meine Lösung:

  1. Verwenden Sie Edit > Past Special > Paste XML As Classes, um die Klasse in Ihrem Code abzurufen
  2. Versuchen Sie Folgendes: Erstellen Sie eine Liste dieser Klasse (List<class1>) und verwenden Sie dann die 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 zu machen.

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, ihn nicht ändern. Mein ist "ArrayOfClass1"

1
haiduong87

Wenn Sie mit xsd.exe Fehler beim Erstellen Ihrer xsd-Datei erhalten, verwenden Sie die XmlSchemaInference-Klasse, wie unter on msdn erwähnt. Hier ist ein Unit-Test, 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
1
goku_da_master

Wie wäre es mit einer generischen Klasse, um ein XML-Dokument zu 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 erforderlich sein oder nicht. Öffnen Sie das XML-Dokument in Visual Studio, klicken Sie mit der rechten Maustaste auf das XML, und wählen Sie Eigenschaften aus. Wählen Sie dann Ihre Schemadatei. 

0
David C Fuchs
string employeedata = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><tag><name>test</bar></nmae>";//demo xml data
        using (TextReader sr = new StringReader(employeedata))
        {
            XmlSerializer serializer = new XmlSerializer(typeof(Employee));//pass type name in XmlSerializer constructor here
            Employee response = (Employee)serializer.Deserialize(sr);
            Console.WriteLine(response.name);
        }

[System.Xml.Serialization.XmlRoot("tag")]
public class Employee
{
    public string name { get; set; }
}
0