Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serializing object with no namespaces using DataContractSerializer

How do I remove XML namespaces from an object's XML representation serialized using DataContractSerializer?

That object needs to be serialized to a very simple output XML.

  • Latest & greatest - using .Net 4 beta 2
  • The object will never need to be deserialized.
  • XML should not have any xmlns:... namespace refs
  • Any subtypes of Exception and ISubObject need to be supported.
  • It will be very difficult to change the original object.

Object:

 [Serializable]   class MyObj  {      string str;      Exception ex;      ISubObject subobj;  }  

Need to serialize into:

<xml>   <str>...</str>   <ex i:nil="true" />   <subobj i:type="Abc">      <AbcProp1>...</AbcProp1>      <AbcProp2>...</AbcProp2>   </subobj> </xml> 

I used this code:

private static string ObjectToXmlString(object obj) {     if (obj == null) throw new ArgumentNullException("obj");      var serializer =         new DataContractSerializer(             obj.GetType(), null, Int32.MaxValue, false, false, null,             new AllowAllContractResolver());      var sb = new StringBuilder();     using (var xw = XmlWriter.Create(sb, new XmlWriterSettings     {         OmitXmlDeclaration = true,         NamespaceHandling = NamespaceHandling.OmitDuplicates,         Indent = true     }))     {         serializer.WriteObject(xw, obj);         xw.Flush();          return sb.ToString();     } } 

From this article I adopted a DataContractResolver so that no subtypes have to be declared:

public class AllowAllContractResolver : DataContractResolver {     public override bool TryResolveType(Type dataContractType, Type declaredType, DataContractResolver knownTypeResolver, out XmlDictionaryString typeName, out XmlDictionaryString typeNamespace)     {         if (!knownTypeResolver.TryResolveType(dataContractType, declaredType, null, out typeName, out typeNamespace))         {             var dictionary = new XmlDictionary();             typeName = dictionary.Add(dataContractType.FullName);             typeNamespace = dictionary.Add(dataContractType.Assembly.FullName);         }         return true;     }      public override Type ResolveName(string typeName, string typeNamespace, Type declaredType, DataContractResolver knownTypeResolver)     {         return knownTypeResolver.ResolveName(typeName, typeNamespace, declaredType, null) ?? Type.GetType(typeName + ", " + typeNamespace);     } } 
like image 328
Yuri Astrakhan Avatar asked Dec 05 '09 08:12

Yuri Astrakhan


People also ask

Can I make XMLSerializer ignore the namespace on Deserialization?

Yes, you can tell the XmlSerializer to ignore namespaces during de-serialization.

How to serialize DataContract in c#?

To create a type that conforms to the contract, first apply the DataContractAttribute to the class. Then apply the DataMemberAttribute to every field or property that you want to serialize. You can apply the DataMemberAttribute to both private and public members. The final format of the XML need not be text.

Which namespace is used for serialization in WCF?

DataContractSerializer as the Default By default WCF uses the DataContractSerializer class to serialize data types.


2 Answers

You need to mark the classes you want to serialize with:

[DataContract(Namespace="")] 

In that case, the data contract serializer will not use any namespace for your serialized objects.

Marc

like image 137
marc_s Avatar answered Sep 21 '22 04:09

marc_s


If you have your heart set on bypassing the default behavior (as I currently do), you create a custom XmlWriter that bypasses writing the namespace.

using System.IO; using System.Xml;  public class MyXmlTextWriter : XmlTextWriter {   public MyXmlTextWriter(Stream stream)     : base(stream, null)   {   }    public override void WriteStartElement(string prefix, string localName, string ns)   {     base.WriteStartElement(null, localName, "");   } } 

Then in your writer consumer, something like the following:

var xmlDoc = new XmlDocument(); DataContractSerializer serializer = new DataContractSerializer(obj.GetType()); using (var ms = new MemoryStream()) {   using (var writer = new MyXmlTextWriter(ms))   {     serializer.WriteObject(writer, obj);     writer.Flush();     ms.Seek(0L, SeekOrigin.Begin);     xmlDoc.Load(ms);   } } 

And the output will have namespace declarations in it, but there will be no usages as such:

<TestObject xmlns:i="http://www.w3.org/2001/XMLSchema-instance">   <Items xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">     <string>Item1</string>     <string>Item2</string>   </Items> </TestObject> 
like image 26
leat Avatar answered Sep 18 '22 04:09

leat