c# XmlSerializer 反序列化器缺少默认命名空间

Posted

技术标签:

【中文标题】c# XmlSerializer 反序列化器缺少默认命名空间【英文标题】:c# XmlSerializer deserializer missing default namespace 【发布时间】:2021-11-03 01:56:03 【问题描述】:

以下是我目前正在处理的集成中的示例负载响应。响应没有设置默认命名空间(示例中的 xml2 变量),问题是 XmlSerializer 不假定默认命名空间是“d”。我尝试在 XMLSerializer 构造函数中设置默认命名空间,但这也不起作用。同样,我不能指望“服务”更新/修复他们的一面。我可以传递一些其他设置来正确填充类吗?

谢谢, 查克

using System;
using System.Xml;
using System.Xml.Serialization;
using System.IO;

namespace TestXmlNamespace

    [XmlRoot(ElementName = "root", Namespace = "my_test_ns1")]
    public class Test
    
        public string name  get; set; 
        public int age  get; set; 

        [XmlElement(Namespace = "my_test_ns2")]
        public int ageInMonths  get; set; 

        public override bool Equals(object obj)
        
            return obj is Test b && name == b.name && age == b.age && ageInMonths == b.ageInMonths;
        

        public void Run(string str, string name)
        
            XmlSerializer serializer = new XmlSerializer(typeof(Test));
            using (StringReader rStream = new StringReader(str))
            
                Test test = serializer.Deserialize(rStream) as Test;
                Console.Out.WriteLine(test.Equals(this) ? $"name equals expected" : $"name does not equal expected");
            
        
    

    class Program
    
        const string xml1 = @"<?xml version=""1.0"" encoding=""UTF-8"" ?>
<d:root xmlns:d=""my_test_ns1"" xmlns:v=""my_test_ns2"">
  <d:name>Bill</d:name>
  <d:age>32</d:age>
  <v:ageInMonths>384</v:ageInMonths>
</d:root>
";

        const string xml2 = @"<?xml version=""1.0"" encoding=""UTF-8"" ?>
<d:root xmlns:d=""my_test_ns1"" xmlns:v=""my_test_ns2"">
  <name>Bill</name>
  <age>32</age>
  <v:ageInMonths>384</v:ageInMonths>
</d:root>
";

        static void Main(string[] args)
        
            Test expected = new Test()
            
                name = "Bill",
                age = 32,
                ageInMonths = 384
            ;

            expected.Run(xml1, "xml1");
            expected.Run(xml2, "xml2");
        
    

【问题讨论】:

【参考方案1】:

我找到了解决方案,并将其发布给将来可能遇到此问题的人,希望我能帮助他们节省一些时间。

简单地说,当一个元素没有命名空间前缀时,XmlSerializer 认为它不是命名空间的一部分,因此在元素属性中指定一个空的命名空间来处理这个问题。请参阅下面的更新示例代码。

using System;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Serialization;
using System.IO;

namespace TestXmlNamespace

    public class CustomXmlTextReader : XmlTextReader
    
        private readonly string DefaultNamespace = String.Empty;

        public CustomXmlTextReader(StringReader reader, string defaultNamespace) : base(reader)
        
            DefaultNamespace = defaultNamespace;
        

        public override string NamespaceURI => String.IsNullOrEmpty(base.NamespaceURI) ? DefaultNamespace : base.NamespaceURI;
    ;

    [XmlRoot(ElementName = "root", Namespace = "my_test_ns1")]
    public class Test
    
        [XmlElement("name", Namespace = "")] // Set namespace to empty string when no namespace prefix specified in xml
        public string name  get; set; 

        [XmlElement("age", Namespace = "")] // Set namespace to empty string when no namespace prefix specified in xml
        public int age  get; set; 

        [XmlElement(Namespace = "my_test_ns2")]
        public int ageInMonths  get; set; 

        public override bool Equals(object obj)
        
            return obj is Test b && name == b.name && age == b.age && ageInMonths == b.ageInMonths;
        

        public void Run(string str, string name)
        
            using (StringReader rStream = new StringReader(str))
            
                //using (XmlTextReader tr = new CustomXmlTextReader(rStream, "my_test_ns1"))
                using (XmlTextReader tr = new XmlTextReader(rStream))
                
                    XmlSerializer serializer = new XmlSerializer(typeof(Test));
                    Test test = serializer.Deserialize(tr) as Test;
                    Console.Out.WriteLine(test.Equals(this) ? $"name equals expected" : $"name does not equal expected");
                
            
        
    

    class Program
    
        const string xml = @"<?xml version=""1.0"" encoding=""UTF-8"" ?>
<d:root xmlns:d=""my_test_ns1"" xmlns:v=""my_test_ns2"">
  <name>Bill</name>
  <age>32</age>
  <v:ageInMonths>384</v:ageInMonths>
</d:root>
";

        static void Main(string[] args)
        
            Test expected = new Test()
            
                name = "Bill",
                age = 32,
                ageInMonths = 384
            ;

            expected.Run(xml, "xml1");
        
    


【讨论】:

以上是关于c# XmlSerializer 反序列化器缺少默认命名空间的主要内容,如果未能解决你的问题,请参考以下文章

C# Xmlserializer 将列表反序列化为 0 而不是 null

C# XMLSerializer 将错误的类型反序列化为 List

C#中通过XmlSerializer类反序列化多个同名XML元素

C# XML序列化和反序列化(XmlSerializer)

XMLSerializer 不反序列化 XML

使用 XmlSerializer 将空 xml 属性值反序列化为可为空的 int 属性