Условная сериализация XML
У меня есть следующие классы С#:
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 имел только те атрибуты, значения которых не равны null/empty.
Например: В первом элементе Book автор пуст, поэтому он не должен присутствовать в сериализованном XML.
Ответы
Ответ 1
Вы можете использовать шаблон 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);
}
}
Ответ 2
Альтернатива:
- Переключить общедоступные поля в свойства
- Определите значения по умолчанию с помощью атрибута
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; }
}
Ответ 3
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);
}
}
И если вы хотите удалить пространство имен из корневого каталога node:
var namespaces = new XmlSerializerNamespaces();
namespaces.Add(string.Empty, string.Empty);
serializer.Serialize(Console.Out, books, namespaces);
Также я бы рекомендовал вам использовать свойства вместо fields в ваших классах моделей для лучшего инкапсуляции:
public class Books
{
[XmlElement("Book")]
public List<Book> BookList { get; set; }
}