2012-06-28 5 views
5

Iniziato a praticare con XML e C# e ho un messaggio di errore "C'è un errore nel documento XML (3,2)". Dopo aver guardato il file, non riesco a vedere nulla di sbagliato in esso (attenzione, probabilmente mi sono perso qualcosa dato che sono un noob). Sto usando un'applicazione console per C# in questo momento. Sto provando a restituire una lista di avventurieri e solo una nota a margine, l'elemento GEAR è facoltativo. Ecco quello che ho finora:Deserialize XML to object (è necessario restituire un elenco di oggetti)

file XML - Test1

<?xml version="1.0" encoding="utf-8"?> 
<Catalog> 
    <Adventurer> 
     <ID>001</ID> 
     <Name>John Smith</Name> 
     <Address>123 Fake Street</Address> 
     <Phone>123-456-7890</Phone> 
     <Gear> 
      <Attack> 
       <Item> 
        <IName>Sword</IName> 
        <IPrice>15.00</IPrice> 
       </Item> 
       <Item> 
        <IName>Wand</IName> 
        <IPrice>20.00</IPrice> 
       </Item>   
      </Attack> 
      <Defense> 
       <Item> 
        <IName>Shield</IName> 
        <IPrice>5.00</IPrice> 
       </Item> 
     </Defense> 
     </Gear> 
    </Adventurer> 
    <Adventurer> 
     <ID>002</ID> 
     <Name>Guy noone likes</Name> 
     <Address>Some Big House</Address> 
     <Phone>666-666-6666</Phone> 
     <Gear></Gear> 
    </Adventurer> 
</Catalog> 

classi C#

public class Catalog 
{ 
    List<Adventurer> Adventurers { get; set; } 
} 

public class Adventurer 
{ 
    public int ID { get; set; } 
    public string Name { get; set; } 
    public string Address { get; set; } 
    public string Phone { get; set; } 
    public Gear Gear { get; set; } 
} 

public class Gear 
{ 
    public List<Item> Attack { get; set; } 
    public List<Item> Defense { get; set; } 
} 

public class Item 
{ 
    public string IName { get; set; } 
    public decimal IPrice { get; set; } 
} 

Serialize Funzione - in cui il problema si verifica in Linea 5

Catalog obj = null; 
string path = @"C:\Users\Blah\Desktop\test1.xml"; 
XmlSerializer serializer = new XmlSerializer(typeof(Catalog)); 
StreamReader reader = new StreamReader(path); 
obj = (Catalog)serializer.Deserialize(reader); 
reader.Close(); 

Console.ReadLine(); 
+0

Si prega di vedere, "[Se le domande specifiche della lingua contengono il nome della lingua nel titolo?] (Http://meta.stackexchange.com/questions/19190/should-language-specific-questions-contain-the-language -name-in-the-title) ", dove il consenso è" no, non dovrebbero ". –

risposta

3

La questione è la lista degli Avventurieri in catalogo:

<?xml version="1.0" encoding="utf-8"?> 
<Catalog> 
    <Adventurers> <!-- you're missing this --> 
     <Adventurer> 
     </Adventurer> 
     ... 
     <Adventurer> 
     </Adventurer> 
    </Adventurers> <!-- and missing this --> 
</Catalog> 

Non hai l'elemento di avvolgimento per la raccolta Adventurers.

EDIT: A proposito, trovo il modo più semplice per costruire la struttura XML e assicurarmi che sia compatibile sia creare gli oggetti in C#, quindi eseguire il built-in XmlSerializer e utilizzare il suo output XML come una base per qualsiasi XML che creo piuttosto che formarlo a mano.

+0

Grazie per il suggerimento. Sono stato in grado di farlo funzionare. Quindi immagino che dovrei creare un "avventuriero" in C# e poi serializzarlo in XML giusto? –

+0

@ J-Y: vorrei creare un tipico 'catalogo' con dati di esempio nel codice C#, quindi serializzarlo in XML da utilizzare come stencil per quando si crea il proprio contenuto XML. –

1

tuo XML non del tutto allineata con gli oggetti ... cioè questi due ...

public string City { get; set; } 

e

<Address>123 Fake Street</Address> 

Cambia città di Indirizzo o viceversa, e che dovrebbe risolvere il problema .

Edit: Ha ottenuto questo al lavoro in un progetto di test, combinazione di tutte le nostre risposte ...

Aggiungi <Adventurers> tag dopo <Catalog> (e </Adventurers> prima </Catalog>) e cambiare

List<Adventurer> Adventurers { get; set; } 

a

public List<Adventurer> Adventurers { get; set; } 

e funziona correttamente per me.

+0

Grazie per la correzione. Ho ancora lo stesso errore per qualche motivo:/ –

+0

XmlSerializer ignorerebbe semplicemente tutti gli elementi che non sono nell'oggetto e dato che 'City' non è definito nell'XML, gli assegnerà il valore predefinito' null'. –

2

In primo luogo, la proprietà "Adventurers" non è pubblica, è inaccessibile, penso che il modo migliore per trovare l'errore sia serializzare l'oggetto e quindi confrontare il risultato con il file xml.

+0

Ah, buon punto. Ho perso quello. –

1

Sono stato in grado di ottenere il tuo xml per deserializzare con un paio di modifiche minori (vale a dire il qualificatore pubblico su Adventurer).

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

namespace TempSandbox 
{ 
    [XmlRoot] 
    public class Catalog 
    { 
     [XmlElement("Adventurer")] 
     public List<Adventurer> Adventurers; 

     private readonly static Type[] myTypes = new Type[] { typeof(Adventurer), typeof(Gear), typeof(Item) }; 
     private readonly static XmlSerializer mySerializer = new XmlSerializer(typeof(Catalog), myTypes); 

     public static Catalog Deserialize(string xml) 
     { 
      return (Catalog)Utils.Deserialize(mySerializer, xml, Encoding.UTF8); 
     } 
    } 

    [XmlRoot] 
    public class Adventurer 
    { 
     public int ID; 

     public string Name; 

     public string Address; 

     public string Phone; 

     [XmlElement(IsNullable = true)] 
     public Gear Gear; 
    } 

    [XmlRoot] 
    public class Gear 
    { 
     public List<Item> Attack; 

     public List<Item> Defense; 
    } 

    [XmlRoot] 
    public class Item 
    { 
     public string IName; 

     public decimal IPrice; 
    } 
} 

sto usando [XmlElement ("Adventurer")], perché i nomi degli elementi XML non corrispondono esattamente i nomi di proprietà di classe.

NOTA: sto utilizzando un programma di deserializzazione generico che avevo già a disposizione.