Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove q1 and all namespaces from xml

Tags:

namespaces

c#

xml

I'm given a xsd generated C# POCO object that I need to convert to xml. The expected payload however doesn't match the xsds I was given. Specifically, I need to omit the declaration and remove all namespaces from the xml object so that the company in question accepts the API request.

Problem

Given an object of type T, I want to serialize it without declaration and namespace.

I've gotten rid of most of it but q1 has been added to each element for some reason. How do I remove that?

Attempt

After some research, I saw several posts provide a solution that creates an empty xml serializer namespace and calls serializer with that object. That only got me half way there.

Usage

        var ns = new XmlSerializerNamespaces();
        ns.Add("", "");
        var body = payload.SerializeObject(false, true, ns);

Extension Method

    public static string SerializeObject<T>(this T obj, bool indented, bool omitDeclaration, XmlSerializerNamespaces ns)
    {
        var utf8NoBom = new UTF8Encoding(false);
        var settings = new XmlWriterSettings
        {
            OmitXmlDeclaration = omitDeclaration,
            Indent = indented,
            Encoding = utf8NoBom
        };
        using (MemoryStream ms = new MemoryStream())
        {
            using (var xmlWriter = XmlWriter.Create(ms, settings))
            {
                XmlSerializer xmlSer = new XmlSerializer(typeof(T));
                xmlSer.Serialize(xmlWriter, obj, ns);
                byte[] bytes = ms.ToArray();
                return utf8NoBom.GetString(bytes);
            }
        }
    }

Unfortunately the results looks like this.

<q1:InventoryFeed xmlns:q1=\"http://thecompany.com/\">
    <q1:InventoryHeader>
        <q1:version>1.4</q1:version>
    </q1:InventoryHeader>
    <q1:inventory>
        <q1:sku>WMSkuCap0180</q1:sku>
        <q1:quantity>
            <q1:unit>EACH</q1:unit>
            <q1:amount>3</q1:amount>
        </q1:quantity>
        <q1:fulfillmentLagTime>1</q1:fulfillmentLagTime>
    </q1:inventory>
</q1:InventoryFeed>

How do I remove the namespace completely?

like image 760
Brantley Blanchard Avatar asked Aug 11 '15 15:08

Brantley Blanchard


People also ask

How to remove namespace information from an XML document?

You can use XSLT style sheets to remove or manipulate the namespace information in the documents. The following examples show how to use XSLT to remove namespace information from an XML document.

Why do we still have to use XML namespaces?

The only reason we're still forced to use such garbage is because people keep saying, "yes", when they need to say "no" a bit more often. The standards are over 10 years old! Why else do we still have software that doesn't understand XML Namespaces, except that we continue to enable it to exist?

What if XElement attributes are only unique to a namespace?

Also note that this also could throw an exception, if you had an XElement attributes that are only unique with the namespace, like: <root xmlns:ns1="a" xmlns:ns2="b"> <elem ns1:dupAttrib="" ns2:dupAttrib="" /> </root>


2 Answers

The simplest way is to 'post-process' the XML:

var doc = XDocument.Parse(xml);

doc.Descendants().Attributes().Where(a => a.IsNamespaceDeclaration).Remove();

foreach (var element in doc.Descendants())
{
    element.Name = element.Name.LocalName;
}

var xmlWithoutNamespaces = doc.ToString();

The other option (as you can't amend the source class XML attributes) is to implement a decorator for XmlWriter that ignores all namespaces, but it's quite a large class so there'd be a lot of boilerplate delegation.

like image 196
Charles Mager Avatar answered Oct 07 '22 12:10

Charles Mager


This is another solution:

XmlWriterSettings settings = new XmlWriterSettings();
//If you wish Encoding
settings.Encoding = Encoding.GetEncoding("ISO-8859-1");

using (XmlWriter xmlWriter = XmlWriter.Create(tempFilePath, settings))
{
     var ns = new XmlSerializerNamespaces();
     ns.Add("", "http://thecompany.com");
     XmlSerializer s = new XmlSerializer(YOUROBJECT.GetType(), "http://thecompany.com");    
     s.Serialize(xmlWriter, YOUROBJECT, ns);

}
like image 6
Gonzalo Bustamante Avatar answered Oct 07 '22 11:10

Gonzalo Bustamante