2010-11-04 11 views
14

Ich habe folgende C# -Klassen:Conditional XML-Serialisierung

public class Books 
{ 

public List<Book> BookList; 

} 

public class Book 
{ 

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

} 

Wie kann ich diese Klasse in den folgenden XML-Serialisierung?

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

Ich mag die XML nur die Attribute, deren Werte haben, ist nicht null/leer. Zum Beispiel: Im ersten Buchelement ist der Autor leer, daher sollte er im serialisierten XML nicht vorhanden sein.

Antwort

29

Sie sollten in der Lage sein, das ShouldSerialize* Muster zu verwenden:

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

Sie schlagen mich um 1 Minute;) –

+2

Ich war unklar, wie die obige Lösung funktionierte, bis ich den folgenden Beitrag las: http: //kjellsj.blogspot .com/2006/02/conditional-xml-serialization_08.html – Dean

+1

+1 Coolste Sache, von der ich noch nie etwas wusste :) Habe gerade ein besonders klebriges Rückwärtskompatibilitätsproblem mit diesem Juwel gelöst. –

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

Und wenn Sie den Namespace von dem Wurzelknoten entfernen:

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

Auch würde ich empfehlen Sie für eine bessere Kapselung properties statt fields in Ihrem Modell-Klassen:

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

Beantwortet das tatsächlich die Frage über das Überspringen der null/leeren Elemente? –

+1

@Will, nein ist es nicht ... –

+0

In der Tat funktioniert mein Code für Null-Elemente, aber es funktioniert nicht für leere Elemente (sie werden immer noch in der generierten XML vorhanden sein). –

6

Alternative:

  • Schalten Sie öffentliche Felder zu Immobilien
  • mit dem DefaultValueAttribute Attribut definieren Standardwerte
  • Inhalt Eigenschaft mit dem Attribut ContentPropertyAttribute definieren
  • Verwenden XamlWriter/XamlReader

Am Ende haben Sie so etwas wie dies oben:

+0

Die schnellste Lösung und mit dem weniger möglichen Boilerplate-Code ... –

+0

Dies sollte die Antwort sein. ShouldSerialize * funktioniert, aber [DefaultValue ("")] ist bei weitem einfachere Methode –