Reputation: 11686
If I have a class marked as a DataContract
and a few properties on it marked with DataMember
attributes I can serialize it out to XML easily, but it would create output like:
<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 DataMember
attribute 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 DataContractFormat
and IXmlSerializable
but I am hoping there is there an easier solution.
What is the easiest way to do this?
Upvotes: 20
Views: 30516
Reputation: 4548
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();
}
Upvotes: 0
Reputation: 42363
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:
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.
I blogged about this here.
Upvotes: 41
Reputation: 136717
You can't do this with the DataContractSerializer
; if you want attributes you need to use the XmlSerializer
instead. With the DataContractSerializer
class 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.
If you're using WCF services then take a look at XmlSerializerFormatAttribute
which allows you to use the XmlSerializer
for serialization.
Upvotes: 17