18

如果我有一个标记为 a 的类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但我希望有一个更简单的解决方案。

最简单的方法是什么?

4

3 回答 3

39

您可以使用 DataContractSerializer 执行此操作 - 答案是通过实现 IXmlSerializable 接口自己接管 Xml 序列化。对于只写支持 - 您可以将 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 属性 - DataContractSerializer 将仅在编写 Xml 时使用 IXmlSerializable 接口实现。

我在这里写了一篇博客。

于 2009-08-17T11:25:14.073 回答
17

你不能用DataContractSerializer; 如果你想要属性,你需要使用XmlSerializer。使用DataContractSerializer该类,允许使用限制性更强的 XML 规范子集,这可以提高性能,并提高已发布服务的互操作性,但对 XML 格式的控制却相当少。

如果您使用的是 WCF 服务,请查看XmlSerializerFormatAttribute哪些允许您使用XmlSerializer用于序列化。

于 2009-02-26T18:50:01.367 回答
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();
    }
于 2012-05-20T21:35:52.407 回答