如何控制.NET DataContract序列化,以便它使用XML属性而不是元素?

时间:2009-02-26 18:47:48

标签: .net serialization xml-serialization datacontract

如果我有一个标记为DataContract的类,并且有一些标有DataMember属性的属性,我可以轻松地将其序列化为XML,但它会创建如下输出:

<Person>
    <Name>John Smith</Name>
    <Email>john.smith@acme.com</Email>
    <Phone>123-123-1234</Phone>
</Person>

我更喜欢的是属性,比如......

<Person Name="John Smith" Email="john.smith@acme.com" Phone="123-123-1234" />

DataMember属性允许我控制名称和顺序,但不能控制它是否被序列化为元素或属性。我环顾四周找到DataContractFormatIXmlSerializable,但我希望有更简单的解决方案。

最简单的方法是什么?

3 个答案:

答案 0 :(得分:37)

你可以用 DataContractSerializer - 答案是 接管Xml序列化 你自己实施的 IXmlSerializable接口。对于 只写支持 - 你可以离开 ReadXml的实现为空,和 为GetSchema返回null,然后 编写WriteXml的实现 如下:

public class MyPerson : IXmlSerializable
{
  public string Name { get; set;}
  public string Email { get; set;}
  public string Phone { get; set;}

  public XmlSchema GetSchema() { return null; }
  public void ReadXml(XmlReader reader) { }
  public void WriteXml(XmlWriter writer)
  { 
    writer.WriteAttributeString("name", Name);
    writer.WriteAttributeString("email", Email);
    writer.WriteAttributeString("phone", Phone);
  } 
}

如果你也使用相同的类型,比如JSON序列化,那么你仍然可以自由添加DataContract和DataMember属性 - 只有在编写Xml时,DataContractSerializer才会使用IXmlSerializable接口实现。

我在博客上发表了这篇文章here

答案 1 :(得分:13)

您不能使用DataContractSerializer执行此操作;如果您需要属性,则需要使用XmlSerializer。对于DataContractSerializer类,允许使用更严格的XML规范子集,这样可以提高性能,并提高已发布服务的互操作性,但是对XML格式的控制较少。

如果您正在使用WCF服务,请查看XmlSerializerFormatAttribute,以便您使用XmlSerializer进行序列化。

答案 2 :(得分:0)

序列化/反序列化时,您可以在属性和元素之间来回转换。以下适用于后者。

    private XmlReader AttributesToElements( Stream stream )
    {
            var root = XElement.Load( stream );
            foreach ( var element in root.Descendants() ) {
                    foreach ( var attribute in element.Attributes() )
                            element.Add( new XElement( root.Name.Namespace + attribute.Name.LocalName, (string)attribute ) );
                    element.Attributes().Remove();
            }
            return root.CreateReader();
    }