2013-03-14 12 views
6

Próbuję odczytać wartości elementów z prostego dokumentu XML i powiązać je z obiektem, ale mam problemy z moim dokumentem XML. I potwierdziły to i może potwierdzić, że nie ma żadnych problemów z dokumentu Sam jednak rozszerzenie wyników na linii:Problem z serializacją kodu XML do obiektu - Wystąpił błąd w dokumencie XML (0, 0)

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

Pokaż „Występuje błąd w dokumencie XML (0, 0)”

Wewnętrzne wyjątki brzmią: <RewriteRules xmlns=''> was not expected.

Nie jestem pewien, co robię źle tutaj?

Moje XML jest poniżej:

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

Kod, który ładuje plik XML i próbuje de-serializacji go: -

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

Moje Url klasa obiektu: -

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

Czy ktoś może zobaczyć, co robię źle?

Dzięki

+0

kopać wyjątkiem bazowego, który spowodował, że. – leppie

Odpowiedz

4

nie jestem zbyt obeznany ze stwierdzeniem from select, ale wydaje się po prostu przejść w xml który jest cały XDocument, zamiast XElement, który jest twój RewriteRule. Właśnie dlatego pojawia się komunikat o błędzie, że RewriteRules jest nieznany - XmlSerializer oczekuje pojedynczego RewriteRule.

Udało mi się przepisać kod przy użyciu LINQ zamiast (ale jeśli wiesz, jak uzyskać pojedynczy element z oświadczenia from select, to powinno działać równie dobrze).

To powinno dać poprawny wynik - rr jest XElement który jest zwracany z 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

może to 'xDoc'? więc 'wybierz xmlSerializer.Deserialize (xDoc.CreateReader())'? – Default

+0

Tak, element byłby 'xDoc', nie sądziłem, że spróbuję CreateReader na samym elemencie, dam to szybki test – DGibbs

+0

Tak, to było wszystko czego mi brakowało. Zmieniono 'xml.CreateReader()' na 'xDoc.CreateReader()'. Działa teraz idealnie, dzięki! – DGibbs

3

EDIT: Nazwa klasy Url nie pasuje. Trzeba zmienić jego nazwę na „RewriteRule” lub zdefiniować to w ten sposób:

[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

Witam @Patrick, próbowałem dodać swoją klasę 'RewriteRules' i modyfikując moją metodę, ale nadal otrzymuję ten sam błąd. Co ciekawe, jeśli zmienię atrybut 'Url' class' XmlRoot' na 'RewriteRules' zamiast' RewriteRule', to deserializator nie wygeneruje błędu, ale wartości związane z moim obiektem będą miały wartość 'null', więc nadal jest coś bardzo dziwne dzieje się – DGibbs

+0

To jest dziwne. Zrobiłem test i zadziałało (użyłem również twojego kodu powyżej z rozmową deserialze). Czy twój edytor dostarcza poprawne pliki xml? Używam notatnika ++. Nie, że problemem jest plik xml. – Patrick

+0

Utworzono dokument xml za pośrednictwem VS i użyłem w3c [validator] (http://validator.w3.org), aby to sprawdzić. – DGibbs

1

moje podejście jest bardziej używany, gdy deserializowania go bezpośrednio do instancji klasy.

Jeśli chcesz używać XDocument, możesz po prostu napisać tak. Nie używam XDocument w moim kodzie. Ponieważ muszę deserializować pełne pakiety XML, robię to bezpośrednio z deserializacją węzła głównego. Dlatego zaproponowałem węzłowi głównemu we właściwe miejsce w poprzednim poście.

Dzięki XDocument można uzyskać bezpośredni dostęp do podstanów. Tutaj jest kod działa dla celu, ale nie mogą być inni, którzy mogą pomóc w ustawieniu ten kod się bardziej eleganckie:

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

To działało dzięki, pomyliłem się, dlaczego użyto anonimowej wersji typu, a przed zwróceniem wartości null dla właściwości. Możesz wytłumaczyć? Zamiast powtarzania adresów URL stworzyłem nowy konstruktor w klasie 'UrlCollection', który pobiera kolekcję dynamiczną i tworzy nowy adres URL z tego adresu URL. 'public UrlCollection (IEnumerable ) {this.Items.Clear(); foreach (dynamiczny element w urlach) {Url url = new Url (item.From, item.To, item.StatusCode); this.Add (url); }} '. P.s zawsze możesz edytować istniejącą odpowiedź;) – DGibbs

+0

Cześć, wygląda na to, że serializator nie lubi nazwy URL-a klasy. Musisz zmienić nazwę na "RewriteRule" lub dodać wiersz: [Serializable] [System.Xml.Serialization.XmlRoot ("RewriteRule")] public class Url – Patrick

Powiązane problemy