2017-07-11 6 views
0

J'ai le xml suivant que je veux désérialiser à un objet.Deserializing XML aux objets qui a la liste des objets dans C#

<result> 
    <reporttype>2</reporttype> 
    <items> 
     <item> 
      <sku>0B0005</sku> 
      <style>0B0005.DAK.GREY</style> 
      <reason>Barcode cannot be moved to different SKUs</reason> 
     </item> 
     <item> 
      <sku>0B0006</sku> 
      <style>0B0006.DAK.GREY</style> 
      <reason>Barcode cannot be moved to different SKUs</reason> 
     </item> 
    </items> 
</result> 

Mais le code ci-dessous ne remplit pas la liste des éléments, quelqu'un peut-il me rappeler ce que je fais mal ici

string inputString = @"<result><reporttype>2</reporttype><items><item><sku>0B0005</sku><style>0B0005.DAK.GREY</style><reason>Barcode cannot be moved to different SKUs</reason></item><item><sku>0B0005</sku><style>0B0005.DAK.GREY</style><reason>Barcode cannot be moved to different SKUs</reason></item></items></result>"; 

XmlDocument doc = new XmlDocument(); 
doc.LoadXml(inputString); 

XmlSerializer serializer = new XmlSerializer(typeof(Result)); 
StringReader rdr = new StringReader(doc.InnerXml); 
Result resultingMessage = (Result)serializer.Deserialize(rdr); 

public enum ReportType { 
    [XmlEnum("0")] 
    InternalErrorReport, 
    [XmlEnum("1")] 
    ErrorReport, 
    [XmlEnum("2")] 
    InternalSuccessReport 
} 

[XmlRoot(ElementName = "result")] 
public class Result { 
    [XmlElement(ElementName = "reporttype")] 
    public ReportType reportType { get; set; } 
    [XmlElement(ElementName = "items")] 
    public List<Item> items = new List<Item>(); 

    public string error { get; set; } 

    public class Item { 
     [XmlElement(ElementName = "sku")] 
     string sku { get; set; } 
     [XmlElement(ElementName = "style")] 
     string style { get; set; } 
     [XmlElement(ElementName = "reason")] 
     string reason { get; set; } 
    } 
} 

Ou est-il une meilleure façon de le faire?

+0

Vous n'avez pas ajouté l'attribut 'XmlElement' à la classe' Item', donc le sérialiseur ne sait pas que l'élément '' est une instance de classe 'Item'. – Dai

+0

Merci pour la réponse rapide, j'ai essayé, mais nous ne pouvons pas utiliser [XmlElement (ElementName = "item")] pour les classes, il est uniquement valide sur la propriété, le champ, ... – Ash

+1

à '[XmlArray (" items ")] et [XmlArrayItem (" items ")]'. – Fabio

Répondre

1

besoin d'être variable publique.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Xml; 
using System.Xml.Serialization; 
using System.IO; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     const string FILENAME = @"c:\temp\test.xml"; 
     static void Main(string[] args) 
     { 
      string xml = File.ReadAllText(FILENAME); 

      XmlSerializer serializer = new XmlSerializer(typeof(Result)); 
      StringReader rdr = new StringReader(xml); 
      Result resultingMessage = (Result)serializer.Deserialize(rdr); 


     } 
    } 
    public enum ReportType 
    { 
     [XmlEnum("0")] 
     InternalErrorReport, 
     [XmlEnum("1")] 
     ErrorReport, 
     [XmlEnum("2")] 
     InternalSuccessReport 
    } 

    [XmlRoot(ElementName = "result")] 
    public class Result 
    { 
     [XmlElement(ElementName = "reporttype")] 
     public ReportType reportType { get; set; } 
     public Items items { get; set; } 
     public string error { get; set; } 


    } 
    [XmlRoot("items")] 
    public class Items 
    { 
     [XmlElement(ElementName = "item")] 
     public List<Item> items = new List<Item>(); 
    } 
    [XmlRoot("item")] 
    public class Item 
    { 
     [XmlElement(ElementName = "sku")] 
     public string sku { get; set; } 
     [XmlElement(ElementName = "style")] 
     public string style { get; set; } 
     [XmlElement(ElementName = "reason")] 
     public string reason { get; set; } 
    } 
} 
+0

Vous n'avez pas besoin de créer une classe supplémentaire pour les collections - le sérialiseur le déserialise parfaitement 'List ' – Fabio

+0

Si vous le faites de cette façon, vous devrez ajouter une étiquette indiquant que l'élément est un tableau. Je pense que cela est déroutant et indique explicitement que les classes sont plus faciles à comprendre pour les novices. – jdweng

0

Les éléments doivent être des éléments Xmlroot et ils contiennent un élément XmlElement, vous devez indiquer quand ils désérialisent l'objet. essayez ceci:

public class Item 
{ 
    [XmlElement(ElementName = "sku")] 
    public string Sku { get; set; } 
    [XmlElement(ElementName = "style")] 
    public string Style { get; set; } 
    [XmlElement(ElementName = "reason")] 
    public string Reason { get; set; } 
} 

[XmlRoot(ElementName = "items")] 
public class Items 
{ 
    [XmlElement(ElementName = "item")] 
    public List<Item> Item { get; set; } 
} 

[XmlRoot(ElementName = "result")] 
public class Result 
{ 
    [XmlElement(ElementName = "reporttype")] 
    public string Reporttype { get; set; } 
    [XmlElement(ElementName = "items")] 
    public Items Items { get; set; } 
} 
+0

cela a fonctionné aussi. Merci pour votre temps ... – Ash

0

Vous pouvez ajouter deux attributs pour items propriété - pour satisfaire sérialisation

[XmlRoot(ElementName = "result")] 
public class Result 
{ 
    [XmlArray("items")] 
    [XmlArrayItem("item")] 
    public List<Item> items = new List<Item>(); 
} 

ou un attribut de type juste set (XmlType) pour la classe d'objet.
Ensuite, il suffira d'utiliser uniquement l'attribut XmlArray pour la propriété Result.items. Ou ne pas utiliser d'attribut du tout parce que le nom de la propriété correspond au nom de l'élément dans xml.

[XmlType("item")] 
public class Item 
{ 
    [XmlElement(ElementName = "sku")] 
    public string sku { get; set; } 
    [XmlElement(ElementName = "style")] 
    public string style { get; set; } 
    [XmlElement(ElementName = "reason")] 
    public string reason { get; set; } 
} 

Et bien sûr faire des propriétés publiques

0

Comme expliqué ici, vous devez marquer la liste comme XmlArray specifing aussi XmlArrayItem: Deserializing nested lists with XmlSerializer

Ainsi, le code devient:

 string inputString = @"<result><error>error test</error><reporttype>2</reporttype><items><item><sku>0B0005</sku><style>0B0005.DAK.GREY</style><reason>Barcode cannot be moved to different SKUs</reason></item><item><sku>0B0005</sku><style>0B0005.DAK.GREY</style><reason>Barcode cannot be moved to different SKUs</reason></item></items></result>"; 

     XmlDocument doc = new XmlDocument(); 
     doc.LoadXml(inputString); 

     XmlSerializer serializer = new XmlSerializer(typeof(Result)); 
     object resultingMessage = null; 
     using (StringReader rdr = new StringReader(doc.InnerXml)) { 
      resultingMessage = (Result)serializer.Deserialize(rdr); 
     } 

et les classes:

public enum ReportType { 
    [XmlEnum("0")] 
    InternalErrorReport, 
    [XmlEnum("1")] 
    ErrorReport, 
    [XmlEnum("2")] 
    InternalSuccessReport 
} 

[XmlRoot(ElementName = "result")] 
public class Result { 
    [XmlElement(ElementName = "reporttype")] 
    public ReportType reporttype { get; set; } 
    [XmlArray("items")] 
    [XmlArrayItem("item")] 
    public List<Item> items { get; set; } 
    [XmlElement(ElementName = "error")] 
    public string error { get; set; } 

    [XmlRoot(ElementName = "items\\item")] 
    public class Item { 
     [XmlElement(ElementName = "sku")] 
     public string sku { get; set; } 
     [XmlElement(ElementName = "style")] 
     public string style { get; set; } 
     [XmlElement(ElementName = "reason")] 
     public string reason { get; set; } 
    } 

} 

S'il vous plaît, notez également que j'ai encapsulé le lecteur de chaîne dans un bloc d'utilisation, en afin de disposer de l'objet une fois la lecture terminée.

+0

Cela a fonctionné, merci pour votre temps ... :) – Ash