Remove q1 and all namespaces from xml

99封情书 提交于 2020-01-04 02:32:32

问题


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?


回答1:


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.




回答2:


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);

}



回答3:


I sometimes use RegEx or XML Linq

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string input =
                "<q1:InventoryFeed xmlns:q1=\"http://thecompany.com/\">\n" +
                    "<q1:InventoryHeader>\n" +
                        "<q1:version>1.4</q1:version>\n" +
                    "</q1:InventoryHeader>\n" +
                    "<q1:inventory>v" +
                        "<q1:sku>WMSkuCap0180</q1:sku>\n" +
                        "<q1:quantity>\n" +
                            "<q1:unit>EACH</q1:unit>\n" +
                            "<q1:amount>3</q1:amount>\n" +
                        "</q1:quantity>\n" +
                        "<q1:fulfillmentLagTime>1</q1:fulfillmentLagTime>\n" +
                    "</q1:inventory>\n" +
                "</q1:InventoryFeed>\n";

            string pattern1 = @"<[^/][^:]+:";
            string output = Regex.Replace(input, pattern1, "<");
            string pattern2 = @"</[^:]+:";
            output = Regex.Replace(output, pattern2, "</");

            //using xml linq
            XElement element = XElement.Parse(input);
            foreach (var node in element.DescendantNodesAndSelf())
            {
                if (node.NodeType == XmlNodeType.Element)
                {
                    ((XElement)node).Name = ((XElement)node).Name.LocalName;
                }
            }
        }
    }
}
​


来源:https://stackoverflow.com/questions/31946240/remove-q1-and-all-namespaces-from-xml

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!