Как заставить 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>

сказав это, я задаюсь вопросом, являются ли элементы медленнее атрибутов, особенно при отправке через линию.