首页 > 解决方案 > 从 DotNetXmlSerializer 中省略 xmlns 和 d4p1

问题描述

我使用发送 Webrequest

    var request = new RestRequest(string.Format(url, config.ApiLocale), Method.POST)
        {
            RequestFormat = DataFormat.Xml,
            XmlSerializer = new RestSharp.Serializers.DotNetXmlSerializer("")
        };

我的请求是这样构建的:

    List<RequestParam> listParams = new List<RequestParam>()
    {
        new RequestParam("Foo1"),
        new RequestParam("Foo2"),
        new RequestParam(12345)
    };

    request.AddBody(new XmlRequest
    {
        MethodName = "api.Testcall",
        ListParams = listParams
    });

我的课程:

    using RestSharp.Deserializers;
    using System;
    using System.Collections.Generic;
    using System.Xml.Serialization;

    namespace Testcall
    {
        [XmlRoot("methodCall")]
        public class XmlRequest
        {
            [XmlElement(ElementName = "methodName")]
            public string MethodName { get; set; }
            [XmlArray(ElementName = "params")]
            [XmlArrayItem("param")]
            public List <RequestParam> ListParams { get; set; }

        } 

        public class RequestParam
        {
            [XmlElement(ElementName = "value")]
            public ParamFather Value { get; set; }

            public RequestParam() { }
            public RequestParam(String PassValue)
            {
                Value = new StringParam(PassValue);
            }
            public RequestParam(int PassValue)
            {
                Value = new IntParam(PassValue);
            }
            public RequestParam(Boolean PassValue)
            {
                Value = new BoolParam(PassValue);
            }
        }

        [XmlInclude(typeof(StringParam))]
        [XmlInclude(typeof(BoolParam))]
        [XmlInclude(typeof(IntParam))]
        public class ParamFather
        {
            [XmlElement(ElementName = "father")]
            public String Content { get; set; }
        }

        public class StringParam : ParamFather
        {
            [XmlElement(ElementName = "string")]
            public String StringContent { get; set; }
            public StringParam() { }
            public StringParam(String Content)
            {
                StringContent = Content;
            }
        }
    }

但是序列化器返回一个包含 Strange d4p1 和 xmlns-Tags 的 XML。那些我想省略的!我只需要不带任何标签的普通 xml。

    <methodCall>
        <methodName>api.Testcall</methodName>
        <params>
            <param>
                <value d4p1:type=\"StringParam\" xmlns:d4p1=\"http://www.w3.org/2001/XMLSchema-instance\">
                    <string>Foo1</string>
                </value>
            </param>
            <param>
                <value d4p1:type=\"StringParam\" xmlns:d4p1=\"http://www.w3.org/2001/XMLSchema-instance\">
                    <string>Foo2</string>
                </value>
            </param>
            <param>
                <value d4p1:type=\"IntParam\" xmlns:d4p1=\"http://www.w3.org/2001/XMLSchema-instance\">
                    <int>12345</int>
                </value>
            </param>
        </params>
    </methodCall>

我尝试使用经典的 XMLSerializer 但失败了。完全可以使用 DotNetXmlSerializer 来做到这一点吗?

标签: xmlserializationxml-namespacesrestsharpxmlserializer

解决方案


最后我通过切换到标准的 XmlSerializer 解决了这个问题。

    [XmlRoot("methodCall")]
    public class XmlRequest
    {
        [XmlElement(ElementName = "methodName")]
        public string MethodName { get; set; }
        [XmlArray(ElementName = "params")]
        [XmlArrayItem("param")]
        public List <RequestParam> ListParams { get; set; }

        public string ToXML()
        {
            using (var stringwriter = new System.IO.StringWriter())
            {
                using (var xmlwriter = XmlWriter.Create(stringwriter, new XmlWriterSettings { OmitXmlDeclaration = true }))
                {
                    XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); ns.Add("", "");
                    new XmlSerializer(this.GetType()).Serialize(xmlwriter, this, ns);
                }
                return stringwriter.ToString();
            }
        }
    }

我这样称呼它:

    List<RequestParam> listParams = new List<RequestParam>()
    {
        new RequestParam("user"),
        new RequestParam("password"),
        new RequestParam(true),
        new RequestParam(123) 
    };
    request.Parameters.Clear();

    XmlRequest reqObject = new XmlRequest
    {
        MethodName = "api.Testcall",
        ListParams = listParams
    };
    string rawXml = reqObject.ToXML();
    request.AddParameter("application/xml", rawXml, ParameterType.RequestBody);

请注意,我现在使用的是 request.AddParameter 而不是我之前使用的 request.AddBody。所以我有更多的控制权,通过标准的 XmlSerializer 创建一个字符串。OmitXmlDeclaration 抑制 xml-Document 的编码和标准开始。我的课程也发生了变化:

    public class RequestParam
    {
        [XmlElement(ElementName = "value")]
        public Alterable Value { get; set; }

        public RequestParam() { }
        public RequestParam(int number)
        {
            Value = new Alterable(number);
        }
        public RequestParam(String str)
        {
            Value = new Alterable(str);
        }
        public RequestParam(Boolean boo)
        {
            Value = new Alterable(boo);
        }
    }

    public class Alterable
    {
        [XmlElement(DataType = "string",Type = typeof(string)),
         XmlElement(DataType = "int",Type = typeof(int)),
         XmlElement(DataType = "boolean",Type = typeof(Boolean))]
         public object Changeable { get; set; }
         public Alterable() { }
         public Alterable(int number)
         {
             Changeable = number;
         }
         public Alterable(string str)
         {
             Changeable = str;
         }
         public Alterable(Boolean boo)
         {
             Changeable = boo;
         }
    }

我的 Alterable 类可以接受字符串、整数和布尔值,并将它们正确地打印到 XML 中。希望这可以帮助遇到同样问题的人。

结果:

    <methodCall>
       <methodName>api.Testcall</methodName>
       <params>
          <param>
             <value>
                <string>user</string>
             </value>
          </param>
          <param>
             <value>
                <string>password</string>
             </value>
          </param>
          <param>
             <value>
                <boolean>true</boolean>
             </value>
          </param>
          <param>
             <value>
                <int>123</int>
             </value>
          </param>
       </params>
    </methodCall>

推荐阅读