Search code examples
c#.netxmlxml-namespacesxmlserializer

Create XML element without namespace prefix inside element with namespace prefix


Using XmlSerializer class I want to achieve the following result XML:

<n:root xmlns:n="http://foo.bar">
    <child/>
</n:root>

Notice the root has the namespace defined and the prefix, but the child does not. I managed to do that with the following XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">

        <xsl:element name="n:root" xmlns:n="http://foo.bar">
            <xsl:element name="child" />
        </xsl:element >

    </xsl:template>
</xsl:stylesheet>

...however I want to use .NET XmlSerializer and the System.Xml.Serialization attributes over classes instead. I created two following classes:

[XmlRoot(ElementName = "root", ElementNamespace = "http://foo.bar")]
public class Root
{
    [XmlElement(ElementName = "child")]
    public Child Child { get; set; }
}

public class Child {}

And then I tried to add the namespace to XmlSerializer and serialize it by using XmlSerializerNamespaces class:

public string Foo()
{
    var root = new Root { Child = new Child() };

    var ns = new XmlSerializerNamespaces();
    ns.Add("n", "http://foo.bar");

    var s = new XmlSerializer(typeof(Root));
    var sb = new StringBuilder();
    var xml = XmlWriter.Create(sb);
    s.Serialize(xml, root, ns);
    return sb.ToString();
}

However the method returns the following XML:

<n:root xmlns:n="http://foo.bar">
    <n:child/>
</n:root>

How to make XmlSerializer avoid adding namespace prefix to the inner element?

inb4: I know it looks weird that the child element won't have the namespace of its parent, but that's the shape of the message I receive from client and I need to create a mock web service that imitates the same behaviour.


Solution

  • Changing your Root class like this should do it:

    [XmlRoot(ElementName = "root", Namespace = "http://foo.bar")]
    public class Root
    {
        // note empty namespace here
        [XmlElement(ElementName = "child", Namespace = "")]
        public Child Child { get; set; }
    }