带有命名空间的 C# XML 反序列化 [英] C# XML deserialization with namespace

查看:47
本文介绍了带有命名空间的 C# XML 反序列化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有 XML:

<?xml version="1.0" encoding="UTF-8"?>
<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
    <gesmes:subject>Reference rates</gesmes:subject>
    <gesmes:Sender>
        <gesmes:name>European Central Bank</gesmes:name>
    </gesmes:Sender>
    <Cube>
        <Cube time='2015-12-16'>
            <Cube currency='USD' rate='1.0933'/>
            <Cube currency='JPY' rate='133.18'/>
        </Cube>
    </Cube>
</gesmes:Envelope>

我正在尝试反序列化:

[XmlRoot("Envelope", Namespace = EcbNameSpace)]
public class EcbEnvelope
{
    const string EcbNameSpace = "http://www.gesmes.org/xml/2002-08-01";

    [XmlElement("Sender", Namespace = EcbNameSpace)]
    public string EcbSender { get; set; }

    [XmlElement("subject", Namespace = EcbNameSpace)]
    public string EcbSubject { get; set; }

    [XmlArray("Cube")]
    [XmlArrayItem("Cube")]
    public List<CubeRoot> CubeRootEl { get; set; }

    public class CubeRoot
    {
        [XmlAttribute("time")]
        public string Time { get; set; }

        [XmlElement("Cube")]
        public List<CubeItem> CubeItems { get; set; }

        public class CubeItem
        {
            [XmlAttribute("rate")]
            public string RateStr { get; set; }

            [XmlIgnore]
            public decimal Rate
            {
                get { return decimal.Parse(RateStr); }
            }

            [XmlAttribute("currency")]
            public string Currency { get; set; }
        }
    }   
}

然而,它将 CubeRootEl 反序列化为空列表.如果我从 XML 中删除 namspaces,那么它反序列化成功.我究竟做错了什么?我尝试在代码中向 CubeRootEl 添加空命名空间,但也没有成功.

However, it deserializes CubeRootEl as empty list. If I remove namspaces from XML, then it deserializes successfully. What am I doing wrong? I tried adding empty namespaces to CubeRootEl in code, but also unsuccessfully.

这是用于反序列化的代码:

Here's the code used for deserialization:

var serializer = new XmlSerializer(typeof(EcbEnvelope)); 
using (var streamReader = new StreamReader(pathToFile)) 
    var a = serializer.Deserialize(streamReader) as EcbEnvelope; 
} 

推荐答案

你有几个问题:

  1. 您没有为属性public List指定命名空间.CubeRootEl.如果未指定属性的命名空间,XmlSerializer 假定它与包含元素位于同一命名空间,在这种情况下为 "http://www.gesmes.org/xml/2002-08-01".但是 元素不在这个命名空间中,因为它们没有 "gesmes:" 前缀.

  1. You do not specify a namespace for the property public List<CubeRoot> CubeRootEl. When a namespace for a property is not specified, XmlSerializer assumes it to be in the same namespace as the containing element, which would in this case be "http://www.gesmes.org/xml/2002-08-01". But the <Cube> elements are not in this namespace since they do not have the "gesmes:" prefix.

您的 XML 具有默认命名空间声明 xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref".因此 元素实际上在这个命名空间中.

Your XML has a default namespace declaration xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref". Thus the <Cube> elements are actually in this namespace.

Sender 不是一个简单的字符串值元素,它有一个嵌套元素 European Central Bank.

Sender is not a simple string-valued element, it has a nested element <gesmes:name>European Central Bank</gesmes:name>.

修复这三个问题可以反序列化您的 XML:

Fixing these three issues allows your XML to be deserialized:

[XmlRoot("Envelope", Namespace = GesmesNameSpace)]
public class EcbEnvelope
{
    public const string GesmesNameSpace = "http://www.gesmes.org/xml/2002-08-01";
    public const string EcbNameSpace = "http://www.ecb.int/vocabulary/2002-08-01/eurofxref";

    [XmlElement("Sender", Namespace = GesmesNameSpace)]
    public EcbSender Sender { get; set; }

    [XmlElement("subject", Namespace = GesmesNameSpace)]
    public string EcbSubject { get; set; }

    [XmlArray("Cube", Namespace = EcbNameSpace)]
    [XmlArrayItem("Cube")]
    public List<CubeRoot> CubeRootEl { get; set; }

    public class EcbSender
    {
        [XmlElement("name")]
        public string Name { get; set; }
    }

    public class CubeRoot
    {
        [XmlAttribute("time")]
        public string Time { get; set; }

        [XmlElement("Cube")]
        public List<CubeItem> CubeItems { get; set; }

        public class CubeItem
        {
            [XmlAttribute("rate")]
            public string RateStr { get; set; }

            [XmlIgnore]
            public decimal Rate
            {
                get { return decimal.Parse(RateStr); }
            }

            [XmlAttribute("currency")]
            public string Currency { get; set; }
        }
    }
}

这篇关于带有命名空间的 C# XML 反序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆