2010-11-04 18 views
14

tengo las siguientes clases de C#:xml condicional serialización

public class Books 
{ 

public List<Book> BookList; 

} 

public class Book 
{ 

public string Title; 
public string Description; 
public string Author; 
public string Publisher; 

} 

Como puedo serializar esta clase en el siguiente XML?

<Books> 
    <Book Title="t1" Description="d1"/> 
    <Book Description="d2" Author="a2"/> 
    <Book Title="t3" Author="a3" Publisher="p3"/> 
</Books> 

Quiero que el XML tenga solo aquellos atributos cuyos valores no sean nulos/vacíos. Por ejemplo: en el primer elemento del Libro, el autor está en blanco, por lo que no debería estar presente en el XML serializado.

Respuesta

29

Debe ser capaz de utilizar el patrón ShouldSerialize*:

public class Book 
{ 
    [XmlAttribute] public string Title {get;set;} 
    public bool ShouldSerializeTitle() { 
     return !string.IsNullOrEmpty(Title); 
    } 

    [XmlAttribute] public string Description {get;set;} 
    public bool ShouldSerializeDescription() { 
     return !string.IsNullOrEmpty(Description); 
    } 

    [XmlAttribute] public string Author {get;set;} 
    public bool ShouldSerializeAuthor() { 
     return !string.IsNullOrEmpty(Author); 
    } 

    [XmlAttribute] public string Publisher {get;set;} 
    public bool ShouldSerializePublisher() { 
     return !string.IsNullOrEmpty(Publisher); 
    } 
} 
+0

me ganaste por 1 minuto;) –

+2

No estaba claro cómo funcionó la solución anterior hasta que leí la siguiente publicación: http: //kjellsj.blogspot .com/2006/02/conditional-xml-serialization_08.html – Dean

+1

+1 La cosa más genial que nunca supe :) Simplemente resolvió un problema de compatibilidad con esta joya especialmente pegajoso. –

1
public class Books 
{ 
    [XmlElement("Book")] 
    public List<Book> BookList; 
} 

public class Book 
{ 
    [XmlAttribute] 
    public string Title; 
    [XmlAttribute] 
    public string Description; 
    [XmlAttribute] 
    public string Author; 
    [XmlAttribute] 
    public string Publisher; 
} 

class Program 
{ 
    static void Main() 
    { 
     var books = new Books 
     { 
      BookList = new List<Book>(new[] 
      { 
       new Book 
       { 
        Title = "t1", 
        Description = "d1" 
       }, 
       new Book 
       { 
        Author = "a2", 
        Description = "d2" 
       }, 
       new Book 
       { 
        Author = "a3", 
        Title = "t3", 
        Publisher = "p3" 
       }, 
      }) 
     }; 

     var serializer = new XmlSerializer(books.GetType()); 
     serializer.Serialize(Console.Out, books); 
    } 
} 

Y si desea eliminar el espacio de nombres del nodo raíz:

var namespaces = new XmlSerializerNamespaces(); 
namespaces.Add(string.Empty, string.Empty); 
serializer.Serialize(Console.Out, books, namespaces); 

También le recomiendo que usando properties en lugar de fields en las clases del modelo para una mejor encapsulación:

public class Books 
{ 
    [XmlElement("Book")] 
    public List<Book> BookList { get; set; } 
} 
+5

¿Esto realmente está respondiendo a la pregunta sobre saltarse los elementos nulos/en blanco? –

+1

@Will, no, no es ... –

+0

De hecho, mi código funciona para elementos nulos, pero no funciona para elementos en blanco (todavía estarán presentes en el XML generado). –

6

alternativa:

  • Cambiar el sistema de campos públicos a las propiedades
  • Definir valores por defecto con el atributo DefaultValueAttribute
  • Definir propiedad de contenido con el atributo ContentPropertyAttribute
  • Uso XamlWriter/XamlReader

Se termina con algo como esto:

[ContentProperty("Books")] 
public class Library { 

    private readonly List<Book> m_books = new List<Book>(); 

    public List<Book> Books { get { return m_books; } } 

} 

public class Book 
{ 

    [DefaultValue(string.Empty)] 
    public string Title { get; set; } 

    [DefaultValue(string.Empty)] 
    public string Description { get; set; } 

    [DefaultValue(string.Empty)] 
    public string Author { get; set; } 

} 
+0

La solución más rápida y con el código repetitivo menos ... –

+0

Esta debería ser la respuesta. ShouldSerialize * funciona, pero [DefaultValue ("")] es, por lejos, el método más simple –

Cuestiones relacionadas