2010-04-19 16 views
10

Quando si utilizza la serializzazione Xml in C#, desidero deserializzare una parte del mio XML di input in un XmlNode.Come deserializzare un elemento come XmlNode?

Quindi, dato questo XML:

<Thing Name="George"> 
    <Document> 
    <subnode1/> 
    <subnode2/> 
    </Document> 
</Thing> 

voglio deserializzare l'elemento del documento per un XmlNode.

Di seguito è riportato il mio tentativo che ha fornito l'XML sopra riportato, imposta Documento sull'elemento 'subnode1' anziché sull'elemento 'Documento'.

Come si ottiene il codice per impostare la proprietà Document sull'elemento Document?

using System; 
using System.IO; 
using System.Xml; 
using System.Xml.Serialization; 

[Serializable] 
public class Thing 
{ 
    [XmlAttribute] public string Name {get;set;} 
    public XmlNode Document { get; set; } 
} 

class Program 
{ 
    static void Main() 
    { 
    const string xml = @" 
<Thing Name=""George""> 
    <Document> 
    <subnode1/> 
    <subnode2/> 
    </Document> 
</Thing>"; 
    var s = new XmlSerializer(typeof(Thing)); 
    var thing = s.Deserialize(new StringReader(xml)) as Thing; 
    } 
} 

Tuttavia, quando uso un XmlSerializer per deserializzare il XML sopra a un'istanza di cose, la proprietà documento contiene l'elemento figlio 'subnode1', piuttosto che elemento del 'Documento'.

Come è possibile ottenere XmlSerializer per impostare Documento su un XmlNode contenente l'elemento "Documento"?

(NB: È possibile accedere all'elemento Document specificando una proprietà di tipo XmlElement [] e contrassegnandolo [XmlAnyElement], ma è impostato sull'array di tutti gli elementi non riconosciuti anziché solo su uno singolo denominato ' Documento ")

+0

Hmmm. Questo è un puzzle! Anche DataContractSerializer presenta lo stesso comportamento. –

+0

La struttura è sempre Document/subnode1, Document/subnode2, o ci saranno subnode3, subnode4, ecc. Ecc.? In tal caso, si sarebbe disposti a modificare lo schema in Document/subnode (sottonodo minOccurs = 0, maxOccurs = non limitato)? – code4life

+1

Il contenuto del documento è completamente in forma libera, è solo lì come un esempio per mostrare come il primo nodo figlio di Documento è selezionato dal deserializzatore. – mackenir

risposta

10

Provare a contrassegnare la proprietà Documento con l'attributo [XmlAnyElement].

[Serializable] 
public class Thing 
{ 
    [XmlAttribute] 
    public string Name {get;set;} 

    [XmlAnyElement] 
    public XmlNode Document { get; set; } 
} 

Ciò avrà un effetto collaterale in che troverete più di un semplice subnode1 e subnode2 (tutti gli spazi bianchi ottenere deserializzate troppo ... ugh), quindi sarà necessario filtrare fuori:

class Program 
{ 
    static void Main() 
    { 
     const string xml = @" 
<Thing Name=""George""> 
    <Document> 
    <subnode1/> 
    <subnode2/> 
    </Document> 
</Thing>"; 
     var s = new XmlSerializer(typeof(Thing)); 
     var thing = s.Deserialize(new StringReader(xml)) as Thing; 

     foreach (XmlNode node in thing.Document) 
     { 
      // should filter to only subnode1 and subnode2. 
      if (node.Name != "" && node.Name != "#whitespace") 
      { 
       Console.WriteLine(node.Name); 
      } 
     } 

     Console.ReadLine(); 
    } 
} 

Spero che questo aiuti!

+0

Alla fine della mia domanda ho detto che una soluzione alternativa era usare l'attributo XmlAnyElement, ma non sapevo che potesse essere inserito su un singolo XmlNode. Forse hai risposto prima che aggiungessi quel testo. Preferisco catturare tutti gli elementi non riconosciuti, quindi posso rilevare errori nell'XML (cioè dovrebbe esserci un solo elemento figlio). – mackenir

Problemi correlati