未知属性xsi:在XmlSerializer中输入

时间:2010-04-30 22:54:50

标签: c# xml-serialization xmlserializer

我正在学习XML序列化并遇到问题,我有两个claess

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

}

public class SubClass : BaseClass
{
}

我正在尝试将SubClass对象序列化为XML文件,我使用打击代码

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

我注意到序列化成功,但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="SubClass">
...
</Employee>

如果我使用

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

我注意到它会抱怨xsi:type是未知属性(我注册了一个事件),尽管XML中嵌入的所有信息都已成功解析,并且SubClassObject中的成员已正确恢复。

任何人都知道为什么在解析xsi:type和我做错的任何事情时都会出错?

由于

2 个答案:

答案 0 :(得分:1)

这是我写的程序

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);
                }
            }
        }
    }
}

这产生了以下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>

它有效

答案 1 :(得分:0)

我遇到了同样的错误。 我没有一个很好的答案,但这就是我所做的:

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());
            }

        }

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



    }
}