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?
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.
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?
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>
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.
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With