Posts tagged ‘XML Serialization’

Handling a custom name space (xmlns) in an XML with Xml Serialization

I have an xml that has a name space. This gave me to problems I had to resolve.

  1. How do I deserialize this xml with that name space value?
  2. How do I serialize the object to only have this one name space?

Deserializing an Xml with a Name Space

Below is an Xml file. Notice that the PrimaryNode has a name space that isn’t the default.

[sourcecode language=”xml”]
<?xml version="1.0" encoding="utf-8"?>
<PrimaryNode xmlns="http://some/random/namespace/example>
<SecondaryNode>
<TertiaryNode />
<TertiaryNode />
</SecondaryNode>
</PrimaryNode>
[/sourcecode]

I had an object created as follows.

[sourcecode language=”csharp”]
using System;
using System.Xml.Serialization;
using System.Collections.ObjectModel;

namespace XmlNameSpaceTest.Model
{
[Serializable()]
public class PrimaryNode
{
private ObservableCollection<SecondaryNode> _Children;

public PrimaryNode() { }

[XmlElement("SecondaryNode")]
public ObservableCollection<SecondaryNode> Children
{
get
{
if (_Children == null)
_Children = new ObservableCollection<SecondaryNode>();
return _Children;
}
}
}
}
[/sourcecode]

I used this static class for the serialization

[sourcecode language=”csharp”]
using System;
using System.IO;
using System.Xml.Serialization;

namespace XmlNameSpaceTest.Model
{
public class Serializer
{
#region Functions
public static void SerializeToXML<T>(T t, String inFilename)
{
XmlSerializer serializer = new XmlSerializer(t.GetType());
TextWriter textWriter = new StreamWriter(inFilename);
serializer.Serialize(textWriter, t);
textWriter.Close();
}

public static T DeserializeFromXML<T>(String inFilename)
{
XmlSerializer deserializer = new XmlSerializer(typeof(T));
TextReader textReader = new StreamReader(inFilename);
T retVal = (T)deserializer.Deserialize(textReader);
textReader.Close();
return retVal;
}
#endregion
}
}
[/sourcecode]

But it failed to deserialize because of the name space. It gave me this exception (which I trimmed to only show the important parts as it was very long).

[sourcecode language=”text”]
System.InvalidOperationException was unhandled
Message=There is an error in XML document (2, 2).
Source=System.Xml
StackTrace:
<– snipped –>
InnerException: System.InvalidOperationException
Message=<PrimaryNode xmlns=’http://some/random/namespace/example’> was not expected.
Source=bgwwvhdx
StackTrace:
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderPrimaryNode.Read7_PrimaryNode()
[/sourcecode]

The solution was simple. I had to add the XmlRoot tag above the class.

[sourcecode language=”csharp”]
[Serializable()]
[XmlRoot(Namespace="http://some/random/namespace/example")]
public class PrimaryNode
{
… snipped…
}
[/sourcecode]

This solved problem 1. The Xml now deserialized just fine.

Serializing an Xml so it only contains a single Name Space

When I serialized the object, there were two default name spaces, but neither were the custom name space that the Xml needed.

[sourcecode language=”xml”]
<?xml version="1.0" encoding="utf-8"?>
<PrimaryNode xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SecondaryNode>
<TertiaryNode />
<TertiaryNode />
</SecondaryNode>
</PrimaryNode>
[/sourcecode]

Here is what I had to do.

1. Add a XmlSerializerNamespaces property with only the one name space added.
[sourcecode language=”csharp”]
[Serializable()]
[XmlRoot(Namespace="http://some/random/namespace/example")]
public class PrimaryNode
{
… snipped…

private XmlSerializerNamespaces _Namespaces;

public XmlSerializerNamespaces NameSpaces
{
get
{
if (_Namespaces == null)
{
_Namespaces = new XmlSerializerNamespaces();
_Namespaces.Add("", "http://schemas.microsoft.com/wix/2006/wi");
}
return _Namespaces;
}
}
}
[/sourcecode]

2. Then I had to change my Serializer class. I needed to overload the Serialize function by adding a version of it that accepts the XmlSerializerNamespaces object as the third parameter.
[sourcecode language=”csharp”]
public static void SerializeToXML<T>(T t, String inFilename, XmlSerializerNamespaces namespaces)
{
XmlSerializer serializer = new XmlSerializer(t.GetType());
TextWriter textWriter = new StreamWriter(inFilename);
serializer.Serialize(textWriter, t, namespaces);
textWriter.Close();
}
[/sourcecode]

3. Then, you’ve probably realized already, when serializing the object to Xml, we use this new function and pass it the PrimaryNode.NameSpaces as the third parameter.

This solved the second problem.

I hope this post helps you.