使用命名空间的 C# XML 反序列化

标签 c# xml serialization

我有 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 中删除命名空间,它就会成功反序列化。我究竟做错了什么?我尝试在代码中向 CubeRootEl 添加空命名空间,但也没有成功。

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

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

最佳答案

你有几个问题:

  1. 您没有为属性 public List<CubeRoot> CubeRootEl 指定命名空间.当未指定属性的 namespace 时,XmlSerializer 假定它与包含元素位于同一命名空间,在本例中为 "http://www.gesmes.org/xml/2002-08-01" .但是 <Cube>元素不在此命名空间中,因为它们没有 "gesmes:"前缀。

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

  3. Sender不是简单的字符串值元素,它有一个嵌套元素 <gesmes:name>European Central Bank</gesmes:name> .

解决这三个问题可以让您的 XML 反序列化:

[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 反序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34331860/

相关文章:

android - 动画展示适用于 14 岁以上 Android 设备

java - 有没有办法跨机器序列化数据?

serialization - 在 clojure 中序列化持久数据结构

ios - 将 iOS objective-c 对象转换为 JSON 字符串

c# - 使用 MVVM 将矩形添加到 Canvas

c# - 网站项目中具有相对路径的 T4 组装指令?

c# - 对象的异构和同构集合

c# - 查找 GUID 的快速方法

java - 在哪里可以找到 Java XML 框架的详细比较?

xml - 如何使用VBScript对XML中的节点进行分组