简体   繁体   中英

Unknown attribute xsi:type in XmlSerializer

I am learning XML Serialization and meet an issue, I have two claess

[System.Xml.Serialization.XmlInclude(typeof(SubClass))]
public class BaseClass
{

}

public class SubClass : BaseClass
{
}

I am trying to serialize a SubClass object into XML file, I use blow code

XmlSerializer xs = new XmlSerializer(typeof(Base));
xs.Serialize(fs, SubClassObject);

I noticed Serialization succeed, but the XML file is kind of like

<?xml version="1.0"?>
<BaseClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="SubClass">
...
</Employee>

If I use

XmlSerializer xs = new XmlSerializer(typeof(Base));
SubClassObject = xs.Deserialize(fs) as SubClass;

I noticed it will complain xsi:type is unknown attribute(I registered an event), although all information embedded in the XML was parsed successfully and members in SubClassObject was restored correctly.

Anyone has any idea why there is error in parsing xsi:type and anything I did wrong?

Thanks

Here is the program that I wrote

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

namespace XmlIncludeExample
{
    [XmlInclude(typeof(DerivedClass))]
    public class BaseClass
    {
        public string ClassName = "Base Class";
    }

    public class DerivedClass : BaseClass
    {
        public string InheritedName = "Derived Class";
    }

    class Program
    {
        static void Main(string[] args)
        {
            string fileName = "Test.xml";
            string fileFullPath = Path.Combine(Path.GetTempPath(), fileName);

            try
            {
                DerivedClass dc = new DerivedClass();

                using (FileStream fs = new FileStream(fileFullPath, FileMode.CreateNew))
                {
                    XmlSerializer xs = new XmlSerializer(typeof(BaseClass));
                    xs.Serialize(fs, dc);
                }

                using (FileStream fs = new FileStream(fileFullPath, FileMode.Open))
                {
                    XmlSerializer xs = new XmlSerializer(typeof(BaseClass));
                    DerivedClass dc2 = xs.Deserialize(fs) as DerivedClass;
                }
            }
            finally
            {
                if (File.Exists(fileFullPath))
                {
                    File.Delete(fileFullPath);
                }
            }
        }
    }
}

This produced the following xml

<?xml version="1.0" ?> 
- <BaseClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="DerivedClass">
  <ClassName>Base Class</ClassName> 
  <InheritedName>Derived Class</InheritedName> 
  </BaseClass>

And it worked

I got the same error. I have not a great answer but this is what I have done:

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

namespace HQ.Util.General
{
    /// <summary>
    /// Save by default as User Data Preferences
    /// </summary>
    public class XmlPersistence
    {
        // ******************************************************************
        public static void Save<T>(T obj, string path = null) where T : class
        {
            if (path == null)
            {
                path = GetDefaultPath(typeof(T));
            }

            var serializer = new XmlSerializer(typeof(T));
            using (TextWriter writer = new StreamWriter(path))
            {
                serializer.Serialize(writer, obj);
                writer.Close();
            }
        }

        // ******************************************************************
        public static T Load<T>(string path = null,
            Action<object, XmlNodeEventArgs> actionUnknownNode = null,
            Action<object, XmlAttributeEventArgs> actionUnknownAttribute = null) where T : class
        {
            T obj = null;

            if (path == null)
            {
                path = GetDefaultPath(typeof(T));
            }

            if (File.Exists(path))
            {
                var serializer = new XmlSerializer(typeof(T));

                if (actionUnknownAttribute == null)
                {
                    actionUnknownAttribute = UnknownAttribute;
                }

                if (actionUnknownNode == null)
                {
                    actionUnknownNode = UnknownNode;
                }

                serializer.UnknownAttribute += new XmlAttributeEventHandler(actionUnknownAttribute);
                serializer.UnknownNode += new XmlNodeEventHandler(actionUnknownNode);

                using (var fs = new FileStream(path, FileMode.Open))
                {
                    // Declares an object variable of the type to be deserialized.
                    // Uses the Deserialize method to restore the object's state 
                    // with data from the XML document. */
                    obj = (T)serializer.Deserialize(fs);
                }
            }

            return obj;
        }

        // ******************************************************************
        private static string GetDefaultPath(Type typeOfObjectToSerialize)
        {
            return Path.Combine(AppInfo.AppDataFolder, typeOfObjectToSerialize.Name + ".xml");
        }

        // ******************************************************************
        private static void UnknownAttribute(object sender, XmlAttributeEventArgs xmlAttributeEventArgs)
        {
            // Correction according to: https://stackoverflow.com/questions/42342875/xmlserializer-warns-about-unknown-nodes-attributes-when-deserializing-derived-ty/42407193#42407193
            if (xmlAttributeEventArgs.Attr.Name == "xsi:type")
            {

            }
            else
            {
                throw new XmlException("UnknownAttribute" + xmlAttributeEventArgs.ToString());
            }
        }

        // ******************************************************************
        private static void UnknownNode(object sender, XmlNodeEventArgs xmlNodeEventArgs)
        {
            // Correction according to: https://stackoverflow.com/questions/42342875/xmlserializer-warns-about-unknown-nodes-attributes-when-deserializing-derived-ty/42407193#42407193
            if (xmlNodeEventArgs.Name == "xsi:type")
            {

            }
            else
            {
                throw new XmlException("UnknownNode" + xmlNodeEventArgs.ToString());
            }

        }

        // ******************************************************************



    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM