【问题标题】:Unknown attribute xsi:type in XmlSerializerXmlSerializer 中的未知属性 xsi:type
【发布时间】:2019-10-19 04:03:49
【问题描述】:

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

[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 is unknown attribute(我注册了一个事件),尽管嵌入在 XML 中的所有信息都已成功解析并且 SubClassObject 中的成员已正确恢复。

有人知道为什么在解析 xsi:type 时会出错以及我做错了什么吗?

谢谢

【问题讨论】:

    标签: c# xml-serialization xmlserializer


    【解决方案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>
    

    成功了

    【讨论】:

    • 这个问题有点难读,但它说“我注册了一个活动”。这时候麻烦就来了。将此添加到您的 XmlSerializer:“xs.UnknownNode += XsUnknownNode;”以及以下事件处理程序:" static void XsUnknownNode(object sender, XmlNodeEventArgs e) { Debug.WriteLine("Unknown {0}\tName: {1}\tValue: {2}\tLine: {3}\tPosition:{4} \tObjectBeingDeserialized: {5}", e.NodeType, e.Name, e.Text, e.LineNumber, e.LinePosition, e.ObjectBeingDeserialized); } " 现在出现错误。我也会修改问题以使其完整。
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-10
      • 1970-01-01
      • 2015-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多