如何控制 .NET DataContract 序列化,使其使用 XML 属性而不是元素?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/591907/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can you control .NET DataContract serialization so it uses XML attributes instead of elements?
提问by Brennan
If I have a class marked as a DataContractand a few properties on it marked with DataMemberattributes I can serialize it out to XML easily, but it would create output like:
如果我有一个标记为 a 的类,DataContract并且它的一些属性标记有DataMember属性,我可以轻松地将它序列化为 XML,但它会创建如下输出:
<Person>
<Name>John Smith</Name>
<Email>[email protected]</Email>
<Phone>123-123-1234</Phone>
</Person>
What I would prefer is attributes, like...
我更喜欢的是属性,比如......
<Person Name="John Smith" Email="[email protected]" Phone="123-123-1234" />
The DataMemberattribute allows me to control the Name and Order but not whether it is serialized as an element or attribute. I have looked around and found DataContractFormatand IXmlSerializablebut I am hoping there is there an easier solution.
该DataMember属性允许我控制名称和顺序,但不能控制它是否被序列化为元素或属性。我环顾四周并找到了DataContractFormat,IXmlSerializable但我希望有一个更简单的解决方案。
What is the easiest way to do this?
什么是最简单的方法来做到这一点?
采纳答案by Greg Beech
You can't do this with the DataContractSerializer; if you want attributes you need to use the XmlSerializerinstead. With the DataContractSerializerclass a more restrictive subset of the XML specification is permitted which improves performance, and improves the interoperability of published services, but gives you rather less control over the XML format.
你不能用DataContractSerializer; 如果你想要属性,你需要使用XmlSerializer代替。对于DataContractSerializer该类,允许使用更严格的 XML 规范子集,这可以提高性能并改进已发布服务的互操作性,但对 XML 格式的控制却较少。
If you're using WCF services then take a look at XmlSerializerFormatAttributewhich allows you to use the XmlSerializerfor serialization.
如果您使用的是 WCF 服务,请查看XmlSerializerFormatAttribute哪些允许您使用XmlSerializerfor 序列化。
回答by Andras Zoltan
You can do this with the DataContractSerializer - the answer is to take over the Xml serialization yourself by implementing the IXmlSerializable interface. For write-only support - you can leave the implementation of ReadXml empty, and return null for GetSchema, and then write the implementation of WriteXml as follows:
您可以使用 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);
}
}
If you're using the same type for, say, JSON serialization as well, then you are still free to add the DataContract and DataMember attributes - the DataContractSerializer will utilise the IXmlSerializable interface implementation only when writing Xml.
如果您也使用相同的类型进行 JSON 序列化,那么您仍然可以自由添加 DataContract 和 DataMember 属性 - DataContractSerializer 将仅在编写 Xml 时使用 IXmlSerializable 接口实现。
I blogged about this here.
我在这里写了关于这个的博客。
回答by HappyNomad
You could convert back and forth between attributes and elements when serializing/deserializing. The following works for the latter.
序列化/反序列化时,您可以在属性和元素之间来回转换。以下适用于后者。
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();
}

