bowserm
bowserm

Reputation: 1056

How do you deserialize XML when you don't know the namespace?

I am dealing with an API that occasionally changes the namespaces on the XML that I receive. The XML structure remains the same. I need to deserialize the XML into a strongly typed model.

How do I perform the deserialization regardless of what namespace is on the XML?

I was using a model like this:

[Serializable, XmlRoot(ElementName = "TestModel", Namespace = "http://schemas.datacontract.org/UnknownNamespace1")]
public class TestModel
{
    public TestModel()
    {
        TestElements = new List<TestModelChildren>();
    }

    [XmlElement("TestModelChildren")]
    public List<TestModelChildren> TestElements { get; set; }
}

I try to deserialize some XML into that model with code like this:

public TestModel DeserializeIt(XDocument xDoc)
{
    TestModel result;
    var serializer = new XmlSerializer(typeof(TestModel));

    using(var sr = new StringReader(xDoc.ToString()))
    {
        result = (TestModel)serializer.Deserialize(sr);
    }

    return result;
}

My problem is that every so often, the namespace on the XML I am receiving changes. I might start getting XML like this:

<TestModel xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/UnknownNamespace2">
    <TestModelChildren>
        ...
    </TestModelChildren>
</TestModel>

I don't want to have to recompile my code every time this namespace change happens. How do I deal with it?

Upvotes: 3

Views: 152

Answers (1)

bowserm
bowserm

Reputation: 1056

I was able to solve the problem by passing the namespace in to the XmlSerializer as a default namespace. I can pluck the namespace off of the XDocument to do this.

My new model would look like this without a namespace specified:

[Serializable, XmlRoot(ElementName = "TestModel")]
public class TestModel
{
    public TestModel()
    {
        TestElements = new List<TestModelChildren>();
    }

    [XmlElement("TestModelChildren")]
    public List<TestModelChildren> TestElements { get; set; }
}

My code to deserialize the XML would look like this:

public TestModel DeserializeIt(XDocument xDoc)
{
    TestModel result;
    var serializer = new XmlSerializer(typeof(TestModel), xDoc.Root.Name.Namespace.ToString());

    using(var sr = new StringReader(xDoc.ToString()))
    {
        result = (TestModel)serializer.Deserialize(sr);
    }

    return result;
}

This has been working for me.

Upvotes: 3

Related Questions