带有命名空间的C#XML反序列化

本文关键字:C#XML 反序列化 命名空间 | 更新日期: 2023-09-27 18:27:19

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

以下是用于反序列化的代码:

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

带有命名空间的C#XML反序列化

您有几个问题:

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

  2. 您的XML有一个默认的名称空间声明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; }
        }
    }
}