How to Deserialize XML into C# object ignoring xmlns?

42 Views Asked by At

Given the following XMLs, how could I deserialize them to the same C# object? Version 1.1 is essentially backward compatible to 1.0 so I don't really care about the xmlns value but C# thinks otherwise...

Example version 1.0:

<?xml version="1.0"?>
<HelloWorld xmlns="https://www.hello.ca/world/1.0">

Example version 1.1:

<?xml version="1.0"?>
<HelloWorld xmlns="https://www.hello.ca/world/1.1">

However, even if I don't specify the namespace in my class, when calling Deserialize it would still complaint about it. The code:

[Serializable()]
// other stuff I tried before
//[XmlType(AnonymousType = true, Namespace = "https://www.hello.ca/world/1.1")]
//[XmlRoot(Namespace = "https://www.hello.ca/world/1.1", IsNullable = false)]
[System.ComponentModel.DesignerCategory("code")]
[XmlType("HelloWorld")]
public class HelloWorld
{
   ...
}

Then in the code where I tried to Deserialize it into my object:

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.PreserveWhitespace = true;
xmlDoc.Load("somewhere.xml");

using (XmlReader xr = new XmlNodeReader(xmlDoc))
{
    XmlSerializer xs = new XmlSerializer(typeof(HelloWorld));
    blah = xs.Deserialize(xr) as HelloWorld;
    return blah  != null;
}

The error I get every single time is that, it doesn't like the xmlns in the node.

InvalidOperationException
 > There is an error in the XML document.
 > <HelloWorld xmlns='https://www.hello.ca/world/1.0'> was not expected.

What is the correct way to tell XmlSerializer to just ignore the xmlns? Or perhaps makes it such that the class is compatible for multiple xmlns?

1

There are 1 best solutions below

1
Suryateja KONDLA On
using System.Xml.Linq;
using System.Xml.Serialization;

namespace ConsoleApp1;

[Serializable]
public class HelloWorld
{
    // Add other properties that match your XML structure
    public string? Name { get; set; }
}

internal static class Program
{
    private static void Main()
    {
        // Your XML strings
        const string xmlV1 = """
                             <?xml version="1.0"?>
                                <HelloWorld xmlns="https://www.hello.ca/world/1.0">
                                    <Name>Robo1</Name>
                                </HelloWorld>
                             """;
        const string xmlV2 = """
                             <?xml version="1.0"?>
                                <HelloWorld xmlns="https://www.hello.ca/world/1.1">
                                    <Name>Robo2</Name>
                                </HelloWorld>
                             """;

        // Remove namespaces
        var cleanXmlV1 = RemoveNamespaces(xmlV1);
        var cleanXmlV2 = RemoveNamespaces(xmlV2);

        // Deserialize
        var hw1 = DeserializeXml<HelloWorld>(cleanXmlV1);
        var hw2 = DeserializeXml<HelloWorld>(cleanXmlV2);

        // Use the deserialized objects as needed
        Console.WriteLine(hw1.Name);
        Console.WriteLine(hw2.Name);
    }

    private static string RemoveNamespaces(string xml)
    {
        var doc = XDocument.Parse(xml);
        foreach (var node in doc.Descendants())
        {
            // Remove namespace
            node.Name = node.Name.LocalName;
            // Remove attributes that are namespaces
            node.Attributes().Where(a => a.IsNamespaceDeclaration || a.Name.Namespace != XNamespace.None).Remove();
        }

        return doc.ToString();
    }

    private static T DeserializeXml<T>(string xml)
    {
        var serializer = new XmlSerializer(typeof(T));
        using var reader = new StringReader(xml);
        return (T)serializer.Deserialize(reader)!;
    }
}

here i have created a small example to ignore namespaces hope this helps you.