Как заставить XmlSerializer генерировать атрибуты вместо элементов по умолчанию
есть ли способ, чтобы вызвать XmlSerializer
сериализовать примитивные члены класса (например, строковые свойства) как атрибуты XML, а не как элементы XML, без написать [XmlAttribute]
перед каждой декларацией собственности?
Т. е. есть ли глобальный коммутатор, который сообщает XmlSerializer
сериализовать все примитивные члены класса как атрибуты XML?
предположим, что у нас есть следующий класс:
public class Person
{
public string FirstName
{
...
}
public string LastName
{
...
}
}
затем XmlSerializer
генерирует этот код по умолчанию:
<Person>
<FirstName>John</FirstName>
<LastName>Doe</LastName>
</Person>
что я хочу, однако, этот код:
<Person FirstName="John" LastName="Doe"/>
снова: я хочу сделать это без [XmlAttribute]
(или без XmlAttributeOverrides
, что бы еще больше работы).
одним из возможных решений было бы использовать общий шаг постобработки, который применяет преобразование XSLT для преобразования элементов в атрибуты. Но мне интересно, есть ли более простое решение.
2 ответов
один из способов достичь этого -реализуйте логику сериализации в базовом классе, реализующем IXmlSerializable интерфейс. Классы, которые должны быть сериализованы в XML, затем должны быть производными от этого базового класса для получения функциональности.
вот пример
public class XmlSerializableEntity : IXmlSerializable
{
public XmlSchema GetSchema()
{
// Implementation omitted for clarity
}
public void ReadXml(XmlReader reader)
{
// Implementation omitted for clarity
}
public void WriteXml(XmlWriter writer)
{
var properties = from property in this.GetType().GetProperties()
where property.PropertyType.IsPrimitive ||
property.PropertyType == typeof(string)
select property;
foreach (var property in properties)
{
var name = property.Name;
var value = property.GetValue(this, null).ToString();
writer.WriteAttributeString(name, value);
}
}
}
здесь мы используем отражение чтобы получить список свойств из текущего объекта, тип которого является примитивом или строка. Эти свойства затем записываются в XML-вывод как атрибуты с помощью предоставленного XmlWriter
Я думаю, что Xslt-самый стабильный, простой в обслуживании и элегантный способ. Это не требует повторного базирования всего, полагается на уже протестированную сериализацию, разрешает пользовательские атрибуты xml в классе, и может быть сделано в памяти, как в C ++ преобразовать.
вот некоторые общие xslt, которые должны это сделать:
<?xml version=’1.0′ encoding=’utf-8′?>
<xsl:stylesheet version=’1.0′ xmlns:xsl=’http://www.w3.org/1999/XSL/Transform’ xmlns:msxsl=’urn:schemas-microsoft-com:xslt’ exclude-result-prefixes=’msxsl’>
<xsl:template match=’*'>
<xsl:copy>
<xsl:for-each select=’@*|*[not(* or @*)]‘>
<xsl:attribute name=’{name(.)}’><xsl:value-of select=’.'/>
</xsl:attribute>
</xsl:for-each>
<xsl:apply-templates select=’*[* or @*]|text()’/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
сказав это, я задаюсь вопросом, являются ли элементы медленнее атрибутов, особенно при отправке через линию.