Условная сериализация xml - PullRequest
17 голосов
/ 04 ноября 2010

У меня есть следующие классы C #:

public class Books
{

public List<Book> BookList;

}

public class Book
{

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

}

Как я могу сериализовать этот класс в следующий XML?

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

Я хочу, чтобы в XML были только те атрибуты, значения которыхне являются нулевыми / пустыми.Например: в первом элементе Book автор не указан, поэтому он не должен присутствовать в сериализованном XML.

Ответы [ 3 ]

37 голосов
/ 04 ноября 2010

Вы должны использовать шаблон 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);
    }
}
6 голосов
/ 04 ноября 2010

Альтернатива:

  • Переключите ваши открытые поля на свойства
  • Определить значения по умолчанию с атрибутом DefaultValueAttribute
  • Определение свойства содержимого с атрибутом ContentPropertyAttribute
  • Использовать XamlWriter / XamlReader

В итоге вы получите что-то вроде этого:

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

 }
1 голос
/ 04 ноября 2010
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);
    }
}

И если вы хотите удалить пространство имен из корневого узла:

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

Также я бы порекомендовал вам использовать свойства вместо поля в вашей модели классов для лучшей инкапсуляции:

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