2010-04-19 14 views
10

Cuando uso la serialización Xml en C#, deseo deserializar una parte de mi XML de entrada en un XmlNode.¿Cómo deserializar un elemento como un XmlNode?

Por lo tanto, dado este XML:

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

Quiero deserializar el elemento documento a un XmlNode.

A continuación se muestra mi intento, que dado el XML anterior, establece Documento en el elemento 'subnode1' en lugar del elemento 'Documento'.

¿Cómo obtendré el código para establecer la propiedad del documento en el elemento del documento?

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

Sin embargo, cuando se utiliza un XmlSerializer para deserializar el XML anterior a una instancia de cosas, la propiedad de documento contiene el elemento hijo 'subnode1', en lugar de elemento del 'Documento'.

¿Cómo puedo obtener el XmlSerializer para establecer el documento en un XmlNode que contiene el elemento 'Documento'?

(Nota: Puedo obtener el elemento Documento especificando una propiedad de tipo XmlElement [] y marcándola [XmlAnyElement], pero eso se establece en la matriz de todos los elementos no reconocidos en lugar de uno solo llamado ' Documento ')

+0

Hmmm. ¡Eso es un rompecabezas! El DataContractSerializer exhibe el mismo comportamiento también. –

+0

¿La estructura siempre es Document/subnode1, Document/subnode2, o habrá subnode3, subnode4, etc.? De ser así, ¿estaría dispuesto a modificar el esquema en Documento/subnodo (subnodo minOccurs = 0, maxOccurs = ilimitado)? – code4life

+1

El contenido de Document es totalmente de forma libre, solo está allí como ejemplo para mostrar cómo el deserializador selecciona el primer nodo secundario de Document. – mackenir

Respuesta

10

Intente marcar la propiedad del documento con el atributo [XmlAnyElement].

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

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

Esto tendrá un efecto secundario desafortunado en el que se encuentra más que subnode1 y subnode2 (todos los espacios en blanco consiguen deserializan también ... uf), por lo que necesitará para filtrar hacia fuera:

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

Espero que esto ayude!

+0

En la parte inferior de mi pregunta mencioné que una solución alternativa era usar el atributo XmlAnyElement, pero no sabía que podría colocarse en un solo XmlNode. Quizás respondiste antes de agregar ese texto. Aunque prefiero capturar todos los elementos no reconocidos, así puedo detectar errores en el XML (es decir, solo debe haber un elemento secundario). – mackenir

Cuestiones relacionadas