Deserialize XML without namespaces but in a class expecting namespaces

前端 未结 4 1426
感动是毒
感动是毒 2021-01-02 10:55

Duplicate:
Omitting all xml namespaces when serializing an object? Not the same.. I want in the other way: Deserialize!


I

相关标签:
4条回答
  • 2021-01-02 11:03

    You could read the file in as text, remove the offending namespace text, then deserialize it.

    You may need to write the "good" text back into a [memory/string/etc] stream so that the XmlSerializer's Deserialize can be called.

    0 讨论(0)
  • 2021-01-02 11:05

    In order to deserialize XML without namespace add XmlRoot attribute to the class that represents the top of your hierarchy:

    [XmlRoot(ElementName="plugins", Namespace="")]
    

    In my example the Xml has no namespace and starts like

    <plugins><...
    

    The class that it deserializes to:

    [XmlRoot(ElementName="plugins", Namespace="")]
    public class Plugins
    {
       //...
    }
    

    Obviously, your situation may be a slightly different, but this code works for me:

    using (FileStream stream = File.Open(filePath, FileMode.Open))
    {
       XmlReader reader = new XmlTextReader(stream);                
       XmlSerializer serializer = new XmlSerializer(typeof(Plugins));
       var plugins = (Plugins)serializer.Deserialize(reader);
    }
    

    -Stan

    0 讨论(0)
  • 2021-01-02 11:08

    I had run into a similar challenge with a proxy class. For reasons that I won't go into, I needed to serialize the class manually using the XmlSerializer on web server and deserialize on client. I was not able to find an elegant solution online, so I just avoided the issue by removing the XmlTypeAttribute from the proxy class manually after I auto-generated it in Visual Studio.

    I kept coming back to see if there was a way to get the namespace to workout. Here is how I got it working without the need to modify the auto-generated classes. I ended up using an XmlTextReader to return the desired namespace on nodes matching a property name. There is room for improvement, but i hope it helps someone.

    class Program
    {
        static void Main(string[] args)
        {
            //create list to serialize
            Person personA = new Person() { Name = "Bob", Age = 10, StartDate = DateTime.Parse("1/1/1960"), Money = 123456m };
            List<Person> listA = new List<Person>();
            for (int i = 0; i < 10; i++)
            {
                listA.Add(personA);
            }
    
            //serialize list to file
            XmlSerializer serializer = new XmlSerializer(typeof(List<Person>));
            XmlTextWriter writer = new XmlTextWriter("Test.xml", Encoding.UTF8);
            serializer.Serialize(writer, listA);
            writer.Close();
    
            //deserialize list from file
            serializer = new XmlSerializer(typeof(List<ProxysNamespace.Person>));
            List<ProxysNamespace.Person> listB;
            using (FileStream file = new FileStream("Test.xml", FileMode.Open))
            {
                //configure proxy reader
                XmlSoapProxyReader reader = new XmlSoapProxyReader(file);
                reader.ProxyNamespace = "http://myappns.com/";      //the namespace of the XmlTypeAttribute 
                reader.ProxyType = typeof(ProxysNamespace.Person); //the type with the XmlTypeAttribute
    
                //deserialize
                listB = (List<ProxysNamespace.Person>)serializer.Deserialize(reader);
            }
    
            //display list
            foreach (ProxysNamespace.Person p in listB)
            {
                Console.WriteLine(p.ToString());
            }
    
            Console.ReadLine();
        }
    }
    
    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public DateTime StartDate { get; set; }
        public decimal Money { get; set; }
    }
    
    namespace ProxysNamespace
    {
        [XmlTypeAttribute(Namespace = "http://myappns.com/")]
        public class Person
        {
            public string Name { get; set; }
            public int Age { get; set; }
            public DateTime Birthday { get; set; }
            public decimal Money { get; set; }
    
            public override string ToString()
            {
                return string.Format("{0}:{1},{2:d}:{3:c2}", Name, Age, Birthday, Money);
            }
        }
    }
    
    public class XmlSoapProxyReader : XmlTextReader
    {
        List<object> propNames;
        public XmlSoapProxyReader(Stream input)
            : base(input)
        {
            propNames = new List<object>();
        }
    
        public string ProxyNamespace { get; set; }
    
        private Type proxyType;
        public Type ProxyType
        {
            get { return proxyType; }
            set
            {
                proxyType = value;
                PropertyInfo[] properties = proxyType.GetProperties();
                foreach (PropertyInfo p in properties)
                {
                    propNames.Add(p.Name);
                }
            }
        }
    
        public override string NamespaceURI
        {
            get
            {
                object localname = LocalName;
                if (propNames.Contains(localname))
                    return ProxyNamespace;
                else
                    return string.Empty;
            }
        }
    }
    
    0 讨论(0)
  • 2021-01-02 11:15

    You need to implement IXmlSerializable to improve your custom serialization.

    0 讨论(0)
提交回复
热议问题