2013-03-14 16 views
6

Sto provando a leggere i valori degli elementi da un semplice documento XML e li lego a un oggetto, tuttavia sto incontrando dei problemi con il mio documento XML. Ho convalidato e posso confermare non ci sono problemi con il documento stesso però espandendo i risultati sulla linea:Problema di serializzazione di XML a Object - C'è un errore nel documento XML (0, 0)

var nodes = from xDoc in xml.Descendants("RewriteRule") 
       select xmlSerializer.Deserialize(xml.CreateReader()) as Url; 

Mostra "C'è un errore nel documento XML (0, 0)"

Le eccezioni interne si legge <RewriteRules xmlns=''> was not expected.

Non sono sicuro di cosa sto facendo male qui?

mio XML è qui sotto:

<?xml version="1.0" encoding="utf-8" ?> 
<RewriteRules> 
    <RewriteRule> 
     <From>fromurl</From> 
     <To>tourl</To> 
     <Type>301</Type> 
    </RewriteRule> 
</RewriteRules> 

Il codice che carica il file XML e cerca di de-serializzare: -

public static UrlCollection GetRewriteXML(string fileName) 
{ 
    XDocument xml = XDocument.Load(HttpContext.Current.Server.MapPath(fileName)); 
    var xmlSerializer = new XmlSerializer(typeof(Url)); 

    var nodes = from xDoc in xml.Descendants("RewriteRule") 
       select xmlSerializer.Deserialize(xml.CreateReader()) as Url; 

    return nodes as UrlCollection; 
} 

mio URL classe di oggetti: -

[Serializable] 
[XmlRoot("RewriteRule")] 
public class Url 
{ 
    [XmlElement("From")] 
    public string From { get; set; } 
    [XmlElement("To")] 
    public string To { get; set; } 
    [XmlElement("Type")] 
    public string StatusCode { get; set; } 

    public Url() 
    { 
    } 

    public Url(Url url) 
    { 
     url.From = this.From; 
     url.To = this.To; 
     url.StatusCode = this.StatusCode; 
    } 
} 

Qualcuno può vedere cosa sto facendo male qui?

Grazie

+0

scavare nella eccezione di base che ha causato questo. – leppie

risposta

4

io non sono troppo familiarità con la dichiarazione from select, ma sembra che hai appena passare in xml che è l'intero XDocument, invece dello XElement è il tuo RewriteRule. Questo è il motivo per cui viene visualizzato il messaggio di errore che RewriteRules è sconosciuto: lo XmlSerializer prevede un singolo RewriteRule.

Sono riuscito a riscrivere il codice utilizzando LINQ invece (ma se si sa come ottenere il singolo elemento dall'istruzione from select, dovrebbe funzionare altrettanto bene).

Questo dovrebbe dare il risultato corretto - rr è la XElement che viene restituito da Descendants:

public static IEnumerable<Url> GetRewriteXML() 
{ 
    XDocument xml = XDocument.Load(HttpContext.Current.Server.MapPath(fileName)); 

    var xmlSerializer = new XmlSerializer(typeof(Url)); 

    var nodes = xml.Descendants("RewriteRule") 
       .Select(rr => xmlSerializer.Deserialize(rr.CreateReader()) as Url); 

    return nodes; 
} 
+0

forse è 'xDoc'? quindi 'seleziona xmlSerializer.Deserialize (xDoc.CreateReader())'? – Default

+0

Sì, l'elemento sarebbe 'xDoc', non pensavo di provare CreateReader sull'elemento stesso, darò un test rapido – DGibbs

+0

Sì, era tutto ciò che mi mancava. Modificato 'xml.CreateReader()' in 'xDoc.CreateReader()'. Funziona perfettamente ora, grazie! – DGibbs

3

EDIT: Il nome della classe URL non corrisponde. È necessario rinominarlo in "RewriteRule" o definire in questo modo:

[Serializable] 
[System.Xml.Serialization.XmlRoot("RewriteRule")] 
public class Url 
{ 
    [XmlElement("From")] 
    public string From { get; set; } 
    [XmlElement("To")] 
    public string To { get; set; } 
    [XmlElement("Type")] 
    public string StatusCode { get; set; } 

    public Url() 
    { 
    } 
    public Url(Url url) 
    { 
     url.From = this.From; 
     url.To = this.To; 
     url.StatusCode = this.StatusCode; 
    } 
} 
+0

Ciao @Patrick, ho provato ad aggiungere la tua classe 'RewriteRules' e modificare il mio metodo, ma continuo a ricevere lo stesso errore. Curiosamente, se modifico il mio attributo 'XmlRoot' di' Url' in 'RewriteRules' invece di' RewriteRule' il deserializzatore non lancia un errore ma i valori legati al mio oggetto sono tutti 'nulli' quindi c'è ancora qualcosa di molto strano andare su – DGibbs

+0

Questo è strano. Ho fatto un test e ha funzionato (ho anche usato il tuo codice sopra con la chiamata deserialze). Il tuo editor fornisce file xml corretti? Io uso Notepad ++. Non che il problema sia il file xml. – Patrick

+0

Ho creato il documento xml tramite VS e ho usato il w3c [validatore] (http://validator.w3.org) per controllarlo – DGibbs

1

il mio approccio è più utilizzato, quando si deserializzare direttamente a un'istanza di una classe.

Se si desidera utilizzare XDocument, è sufficiente scriverlo in questo modo. Non uso XDocument nel mio codice. Dato che ho bisogno di deserializzare i pacchetti completi di xml, lo faccio direttamente con la deserializzazione del nodo root. Pertanto, ho proposto al nodo root il posto giusto nel post precedente.

Con XDocument è possibile accedere direttamente alle parti secondarie. Ecco il codice di lavoro per il vostro scopo, ma ci possono essere altri che possono aiutare a impostare questo codice su più elegante:

public static UrlCollection GetRewriteXML(string fileName) 
    { 
     XDocument xml = XDocument.Load(HttpContext.Current.Server.MapPath(fileName)); 
     var urls = from s in xml.Descendants("RewriteRule") 
        select new 
        { 
         From = (string)s.Element("From").Value, 
         To = (string)s.Element("To").Value, 
         StatusCode = (string)s.Element("Type").Value 
        }; 
     UrlCollection nodes = new UrlCollection(); 
     foreach (var url in urls) 
     { 
      nodes.Add(new Url(url.From, url.To, url.StatusCode)); 
     } 
     return nodes; 
    } 

[Serializable] 
public class Url 
{ 
    [XmlElement("From")] 
    public string From { get; set; } 
    [XmlElement("To")] 
    public string To { get; set; } 
    [XmlElement("Type")] 
    public string StatusCode { get; set; } 

    public Url() 
    { 
    } 

    public Url(string From, string To, string StatusCode) 
    { 
     this.From = From; 
     this.To = To; 
     this.StatusCode = StatusCode; 
    } 

    public Url(Url url) 
    { 
     url.From = this.From; 
     url.To = this.To; 
     url.StatusCode = this.StatusCode; 
    } 
} 
+0

Questo ha funzionato grazie, confuso sul perché utilizzare la versione anonima del tipo ha funzionato mentre prima restituiva valori nulli per le proprietà. Puoi spiegare? Invece di scorrere gli URL ho creato un nuovo costruttore nella mia classe 'UrlCollection' che accetta una raccolta dinamica e ha creato un nuovo URL da quello ad es. 'public UrlCollection (IEnumerable urls) {this.Items.Clear(); foreach (elemento dinamico in url) {Url url = new Url (item.From, item.To, item.StatusCode); this.Add (url); }} '. P.s puoi sempre modificare una risposta esistente;) – DGibbs

+0

Ciao, sembra che il serializzatore non ami il nome della tua classe Url. È necessario rinominarlo in "RewriteRule" o aggiungere la riga: [Serializable] [System.Xml.Serialization.XmlRoot ("RewriteRule")] Url classe pubblica – Patrick