【问题标题】:XML attribute with namespace other than its parent's is deserialized as null名称空间不是其父名称的 XML 属性被反序列化为 null
【发布时间】:2017-12-18 14:28:15
【问题描述】:

我正在尝试反序列化以下 XML:

<nsMain:Parent xmlns:nsMain="http://main.com">
    <nsMain:Child xmlns:nsSub="http://sub.com" nsSub:value="foobar" />
</nsMain:Parent>

注意属性的命名空间与两个元素的命名空间不同。

我有两个班级:

[XmlRoot(ElementName = "Parent", Namespace = "http://main.com")]
public class Parent
{
    [XmlElement(ElementName = "Child")]
    public Child Child{ get; set; }
}

[XmlType(Namespace = "http://sub.com")]
public class Child
{
    [XmlAttribute(AttributeName = "value")]
    public string Value { get; set; }
}

XML 作为 HTTP POST 请求的正文出现在 HttpRequestMessage 对象中。反序列化的函数是:

private Parent ExtractModel(HttpRequestMessage request)
{
    var serializer = new XmlSerializer(typeof(Parent));
    var model = (Parent)serializer.Deserialize(request.Content.ReadAsStreamAsync().Result);
    return model;
}

但是,在调用此函数后,model.Child.Value == null.

我尝试在类和属性上使用 C# 属性的 Namespace 参数进行一些试验(例如,将其移至 [XmlAttribute],或同时放入 [XmlType] 和 [XmlAttribute]),但它没有改变任何东西。我似乎无法做到这一点。如果我根本不使用命名空间(无论是在请求中还是在模型定义中),那么值就可以读取。

我错过了什么?

【问题讨论】:

    标签: c# xml serialization xml-namespaces xml-deserialization


    【解决方案1】:

    您正在应用您的命名空间"http://sub.com" 元素 Child,而不是其value 属性。在您的 XML 中,您专门将"http://main.com" 应用于ParentChild。你可以像这样修复你的命名空间:

    [XmlRoot(ElementName = "Parent", Namespace = "http://main.com")]
    public class Parent
    {
        [XmlElement(ElementName = "Child")]
        public Child Child{ get; set; }
    }
    
    [XmlType(Namespace = "http://main.com")]
    public class Child
    {
        [XmlAttribute(AttributeName = "value", Namespace = "http://sub.com")]
        public string Value { get; set; }
    }
    

    【讨论】:

    • 谢谢,它成功了。不知何故,我对它的工作原理有一个错误的想法。我的意思是......如果你把一个命名空间放在整个类上,它就会成为它所有成员的默认值。这样,我认为父命名空间是其子命名空间的默认值,而子命名空间实际上是值的默认值......但显然情况并非如此。主要的困惑是......在哪些情况下应该将命名空间放在成员上,哪些放在类上?
    • 您将命名空间放在 XML 中的位置。
    • 这是否意味着我可以将 http://main.com 命名空间放在 Child 类或 Parent 中的 Child 属性上(这无关紧要)?它们有点代表相同。
    • 这是一个非常具体的答案,我无法从头顶回答。也许你试试看?
    • @Sushi271 - 默认情况下,XML 元素位于其父级的命名空间中,但默认情况下 XML 属性不在命名空间中。这在 [XML 标准] 中有解释:无前缀属性名称的命名空间名称始终没有值。 XmlSerializer 默认情况下尊重这一点,因此您需要显式设置属性的命名空间。虽然如果您这样做可能会出现问题,请参阅here
    猜你喜欢
    • 2019-11-02
    • 2013-10-09
    • 1970-01-01
    • 1970-01-01
    • 2012-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-16
    相关资源
    最近更新 更多