C# Ignoring Namespaces in XML when Deserializing

Namespaces in XML are hard to understand, I’ll admit that. But even I have learned that namespaces in XML documents matter. These elements are not the same:

<item>
    <title>Brian Caos</title>
    <description>A blog on C# coding</description>
    <link>https://briancaos.wordpress.com/</link>
</item>

<item xmlns:g="http://base.google.com/ns/1.0" version="2.0">
    <g:title>Brian Caos</g:title>
    <g:description>A blog on C# coding</g:description>
    <g:link>https://briancaos.wordpress.com/</g:link>
</item>

These 2 set of elements need to be mapped differently when deserialized in C#:

// This will map the <title> element in XML
[XmlElement("title"]
public string Title { get; set; }

// ... and this will map the <g:title> element in XML
[XmlElement("title", Namespace = "http://base.google.com/ns/1.0")]
public string Title { get; set; }

Unfortunately it is extremely common that businesses completely ignore the namespacing rules and send elements with or without namespaces. And we developers have to deal with it.

SO HOW DO WE FIX IT?

There is a class though, the XmlTextReader, that allows to be overwritten to ignore namespaces. Microsoft discourages us from using the class though. But it’s our only chance to ignore the namespace when deserializing.

STEP 1: CREATE A IgnoreNamespaceXmlTextReader CLASS

using System.Xml;

namespace MyCode
{
  public class IgnoreNamespaceXmlTextReader : XmlTextReader
  {
    public IgnoreNamespaceXmlTextReader(TextReader reader) : base(reader) 
    { 
    }

    public override string NamespaceURI => "";
  }
}

STEP 2: DO NOT SPECIFY ANY NAMESPACES IN THE C# MODEL CLASS

This is an example of how to deserialize a simple XML into a simple model class. The model class does not define any namespaces in the class attributes:

using System.Xml.Serialization;

namespace MyCode
{
  [XmlRoot(ElementName = "model")]
  [XmlType("model")]
  public class XmlModel
  {
    [XmlElement("name")]
    public string Name { get; set; }  

    [XmlElement("value")]
    public string Value { get; set; } 
  }
}

STEP 3: USE THE IgnoreNamespaceXmlTextReader WHEN DESERIALIZING XML

Now we can deserialize any XML we receive, namespace or no namespace:

// We can now import 
// an xml without namespaces
string s = @"<model>
               <name>hello</name>
               <value>world</value>
             </model>";

var sr = new StringReader(s);
var xmlSerializer = new XmlSerializer(typeof(XmlModel));
var xmlModel = (XmlModel)xmlSerializer.Deserialize(new IgnoreNamespaceXmlTextReader(sr));
// xmlModel.Name = "hello" and xmlModel.Value = "world"

// ---------------------------------------------------

// And we can also import 
// an xml with namespaces
// because the IgnoreNamespaceXmlTextReader ignores 
// any namespaces in the receiving XML
string s = @"<model xmlns:g=""http://base.google.com/ns/1.0"">
               <g:name>hello</g:name>
               <g:value>world</g:value>
             </model>";

var sr = new StringReader(s);
var xmlSerializer = new XmlSerializer(typeof(XmlModel));
var xmlModel = (XmlModel)xmlSerializer.Deserialize(new IgnoreNamespaceXmlTextReader(sr));
// xmlModel.Name = "hello" and xmlModel.Value = "world"

MORE TO READ:

About briancaos

Developer at Pentia A/S since 2003. Have developed Web Applications using Sitecore Since Sitecore 4.1.
This entry was posted in .net, .NET Core, c#, General .NET and tagged , , , . Bookmark the permalink.

2 Responses to C# Ignoring Namespaces in XML when Deserializing

  1. How does this solution differ from XmlTextReader reader.Namespaces = false setting?

    Like

  2. briancaos says:

    It’s doesn’t really. The XmlTextReader.Namespaces is also a great weapon of choice.

    Like

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.