Question

Comment puis-je deserialize ce document XML:

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

J'ai ceci:

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

qui ne semble pas fonctionner: - (

Était-ce utile?

La solution

Voici une version de travail. J'ai changé les étiquettes de XmlElementAttribute XmlElement parce que dans le xml du Numéro de stock, la marque et les valeurs du modèle sont des éléments, pas d'attributs. J'ai aussi enlevé le reader.ReadToEnd (); (Cette fonction lit tout le flux et retourne une chaîne, de sorte que la fonction Deserialze () ne pouvait plus utiliser le lecteur ... la position était à la fin du cours d'eau). J'ai aussi pris quelques libertés avec la dénomination:)

.

Voici les classes:

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

La fonction Désérialiser:

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

Et le xml légèrement modifié (je besoin d'ajouter un nouvel élément à envelopper ... Net est pointilleux sur les tableaux désérialisation):

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

Autres conseils

Que diriez-vous que vous venez d'enregistrer le xml dans un fichier, et utilisez xsd pour générer des classes C #?

  1. Ecrire le fichier sur le disque (je l'ai nommé foo.xml)
  2. Générer le xsd: xsd foo.xml
  3. Génération C #: xsd foo.xsd /classes

Et le tour est joué - et le fichier de code C # qui devrait être en mesure de lire les données via XmlSerializer:

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

(y compris les foo.cs générés dans le projet)

Vous avez deux possibilités.

Méthode 1. XSD outil


Supposons que vous avez votre fichier XML dans cet emplacement C:\path\to\xml\file.xml

  1. Ouvrir Invite de commandes de développeur Vous pouvez le trouver dans Start Menu > Programs > Microsoft Visual Studio 2012 > Visual Studio Tools Ou si vous avez Windows 8 peut commencer à taper Développeur Invite de commande Écran de démarrage
  2. Changer l'emplacement dans votre répertoire de fichier XML en tapant cd /D "C:\path\to\xml"
  3. Créer fichier XSD de votre fichier xml en tapant xsd file.xml
  4. Créer C classes # en tapant xsd /c file.xsd

Et voilà! Vous avez généré des classes C # à partir du fichier xml dans C:\path\to\xml\file.cs

Méthode 2 - Collage spécial


Visual Studio requis 2012+

  1. Copier le contenu de votre fichier XML dans le presse-papiers
  2. Ajoutez à votre solution nouveau fichier de classe vide ( Maj + Alt + C )
  3. Ouvrez ce fichier et dans le menu cliquez sur
    Edit > Paste special > Paste XML As Classes entrer image description ici

Et voilà!

Utilisation


L'utilisation est très simple avec cette classe d'aide:

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

Tout ce que vous avez à faire maintenant, est:

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

L'extrait suivant devrait faire l'affaire (et vous pouvez ignorer la plupart des attributs de sérialisation):

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

Voyez si cela aide:

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

Et à défaut utiliser le programme xsd.exe qui vient avec visual studio pour créer un document de schéma basé sur ce fichier xml, puis l'utiliser à nouveau pour créer une classe sur la base du document de schéma.

Je ne pense pas que .net est «pointilleux sur les tableaux désérialisation. Le premier document XML est pas bien formé. Il n'y a aucun élément racine, bien qu'il semble qu'il y ait. Le document XML canonique a une racine et au moins 1 élément (le cas échéant). Dans votre exemple:

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

essayez ce bloc de code si votre fichier .xml a été généré quelque part dans le disque et si vous avez utilisé List<T>:

//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();`

Remarque: le chemin est C:\serialize.xml de mon fichier .xml. Vous pouvez le modifier pour vos besoins.

Le Anser de Kevin est bon, à part le fait que dans le monde réel, vous êtes souvent pas en mesure de modifier le XML d'origine en fonction de vos besoins.

Il y a une solution simple pour le XML original, aussi:

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

Et vous pouvez simplement appeler:

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

Essayez cette classe générique pour Xml sérialisation et désérialisation.

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

pour les débutants

J'ai trouvé les réponses ici très utile, qui dit que je toujours eu du mal (juste un peu) pour obtenir ce travail. Ainsi, dans le cas où il aide quelqu'un que j'épelle la solution de travail:

XML de Original Question. Le XML est dans un Class1.xml de fichier, un fichier à path est utilisé dans le code pour localiser ce fichier xml.

J'ai utilisé la réponse par @erymski pour obtenir ce travail, donc créé un fichier appelé Car.cs et ajouté ce qui suit:

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

L'autre bit de code fourni par @erymski ...

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

... va dans votre programme principal (Program.cs), dans comme ceci static CarCollection XCar():

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

it helps: -)

L'idée est d'avoir tous les niveaux pour être manipulé désérialisation S'il vous plaît voir une solution échantillon qui a résolu mon problème similaire

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

Le XML ci-dessus est traité en deux niveaux

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

}

Le niveau intérieur

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

}

Way même vous avez besoin de multiples niveaux avec car as array Consultez cet exemple pour désérialisation multi-niveaux

Si vous obtenez des erreurs en utilisant xsd.exe pour créer votre fichier XSD, puis utilisez la classe XmlSchemaInference comme mentionné sur msdn. Voici un test unitaire pour démontrer:

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

Vous pouvez simplement changer un attribut pour vous Voitures propriété de voiture XmlArrayItem à XmlElment. C'est, de

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

My solution:

  1. Use Edit > Past Special > Paste XML As Classes to get the class in your code
  2. Try something like this: create a list of that class (List<class1>), then use the XmlSerializer to serialize that list to a xml file.
  3. Now you just replace the body of that file with your data and try to deserialize it.

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

NOTE: you must pay attention to the root name, don't change it. Mine is "ArrayOfClass1"

How about a generic class to deserialize an XML document

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

This part may, or may not be necessary. Open the XML document in Visual Studio, right click on the XML, choose properties. Then choose your schema file.

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;
        }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top