1

我有这种情况:

    [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.33440")]
    [System.SerializableAttribute()]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
    public class Response
    {
        public string RetKey { get; set; }
        public string RetType { get; set; }
    }

    [Test]
    public void Test3()
    {
        {
            var s = @"<Response  CommandID=""57b48ae28f484ab4b3cc2e841cddd02a"">
    <RetKey>5</RetKey>
    <RetType>152</RetType>
    </Response>";

            var xmlSerializer = new XmlSerializer(typeof(Response));
            var deserialize = (Response)xmlSerializer.Deserialize(new StringReader(s));

            Assert.AreEqual("5", deserialize.RetKey, "no namespace");
        }

        {
            var s = @"<Response xmlns=""http://www.sap.com/SBO/DIS"" CommandID=""57b48ae28f484ab4b3cc2e841cddd02a"">
    <RetKey>5</RetKey>
    <RetType>152</RetType>
    </Response>";

            var xRoot = new XmlRootAttribute
            {
                ElementName = typeof(Response).Name,
                Namespace = "http://www.sap.com/SBO/DIS",
                IsNullable = true
            };

            var xmlSerializer = new XmlSerializer(typeof(Response), xRoot);
            var deserialize = (Response)xmlSerializer.Deserialize(new StringReader(s));

            Assert.AreEqual("5", deserialize.RetKey, "try to declare namespaces");
        }
    }

第二次尝试失败(使用命名空间)。所以我坚持在 xml 反序列化中正确使用命名空间。让我感到困惑的是,反序列化过程没有错误,但返回空对象。

我错过了什么?

4

1 回答 1

5

第二个版本的xml完全不同,所以失败是正确的。命名空间是xml 节点标识的基础。如果您希望第二个版本工作,您需要Namespace="http://www.sap.com/SBO/DIS"在所有相关[Xml...]属性中告诉它,注意这xmlns="..."是由子元素继承的。这意味着您还需要告诉它RetKey并且RetType位于该名称空间中。

如果你想在运行时定义它,那么:

var xRoot = new XmlRootAttribute
{
    ElementName = nameof(Response),
    Namespace = "http://www.sap.com/SBO/DIS",
    IsNullable = true
};
var xor = new XmlAttributeOverrides();
xor.Add(typeof(Response), nameof(Response.RetKey), new XmlAttributes
{
    XmlElements = { new XmlElementAttribute(nameof(Response.RetKey))
        { Namespace = xRoot.Namespace } }
});
xor.Add(typeof(Response), nameof(Response.RetType), new XmlAttributes
{
    XmlElements = { new XmlElementAttribute(nameof(Response.RetType))
        { Namespace = xRoot.Namespace } }
});
var xmlSerializer = new XmlSerializer(typeof(Response),
    xor, Type.EmptyTypes, xRoot, xRoot.Namespace);

但是,请注意,当您XmlSerializer以这种方式创建时,您必须缓存并重用它 -每次您new XmlSerializer(...)喜欢它时都会生成一个新的程序集,这很快就会变得非常昂贵。所以:把它存放在某个地方!或者只使用属性(使用简单构造函数时它会在内部缓存)。

于 2019-02-04T16:29:35.593 回答