Can you set the Namespace field in XmlRootAttribute at run time?

Viewed 168

Basically the issue is that I have a set of XML tags that exist in multiple namespaces but because XML namespaces are dumb, that's not allowed so I need to swap out the namespace at run time depending on where the data is going.

Suppose I have this class for serializing/deserializing XML.

[System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:foobar1")]
public class FooBar
{

    private string foo;

    public string Foo
    {
        get
        {
            return this.foo;
        }
        set
        {
            this.foo = value;
        }
    }
}

Then I'm sending this as XML by using HttpClient like

HttpClient client=new HttpClient();
XmlMediaTypeFormatter formatter = new XmlMediaTypeFormatter()
{
    UseXmlSerializer = true
};

Foobar content=new FooBar(){Foo="content"};
client.PostAsync<FooBar>("https://my.endpoint.com", content, formatter);

and the XML it sends is

<?xml version="1.0" encoding="utf-8"?>
<FooBar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="urn:foobar1">
  <Foo>foobartest</Foo>
</FooBar>

Some of the time that's what I need, but other times I need exactly the same thing except it has to be urn:foobar2 instead of urn:foobar1. Unfortunately XmlRootAttribute requires a const so I can't simply pass in a different namespace string. Is there an alternative approach that would let me do this without having two identical FooBar classes?

1 Answers

If you remove the XmlRootAttribute, You can instantiate a XML Serializer with the desired namespace and set it as your formatter's serializer:

    string sNS = "urn:foobar2";
    HttpClient client = new HttpClient();
    XmlMediaTypeFormatter formatter = new XmlMediaTypeFormatter() { UseXmlSerializer = true };
    System.Xml.Serialization.XmlSerializer xml = new System.Xml.Serialization.XmlSerializer(typeof(FooBar), sNS);
    formatter.SetSerializer(typeof(FooBar), xml);
    FooBar content = new FooBar() { Foo = "content" };
    client.PostAsync<FooBar>("https://my.endpoint.com", content, formatter);

Here is the XML it generates:

<?xml version="1.0" encoding="utf-16"?>
<FooBar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="urn:foobar2">
  <Foo>content</Foo>
</FooBar>
Related