簡體   English   中英

啟用架構驗證時C#反序列化失敗

[英]C# Deserialization failure on enabling schema validation

我將一個類序列化為XML。 但是,啟用架構驗證后,反序列化到相同類類型的操作將失敗。

這是我在做什么:

  1. 從可序列化類創建對象
  2. 將該對象序列化為XML
  3. 從該對象獲取模式
  4. 將該架構添加到驗證
  5. 未經驗證反序列化
  6. 使用XMLschema驗證反序列化

在第六步中,它失敗了……

在此代碼示例中,帶有驗證的方法失敗:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;

namespace Deserialize
{
    public class Program
    {
        static string filepath = "TestSerilize.xml";
        private static object oSchema;
        private static XmlReaderSettings oXmlReaderSettings;

        static void Main(string[] args)
        {
            MyObject oMyobject = new MyObject();
            oMyobject.MyObjectType = "MyCustomType";
            List<Items> olistItems = new List<Items>();
            Items oItems = new Items();
            oItems.key = "test123";
            oItems.value = "testvalue";
            olistItems.Add(oItems);
            oMyobject.Items = olistItems;
            Saveobjecttofile(oMyobject, filepath);
            dynamic objDeserialized = null;
            objDeserialized = GetObjFormfileWithoutValidation(filepath, oMyobject.GetType());
            objDeserialized = GetObjFormfileWithValidation(filepath, oMyobject.GetType());

        }

        private static dynamic GetObjFormfileWithValidation(string filepath, Type type)
        {
            XmlReaderSettings oXmlReaderSettings = new XmlReaderSettings();
            oXmlReaderSettings.ValidationType = ValidationType.Schema;
            dynamic oSchema = GetSchemaFromType(type);
            oXmlReaderSettings.Schemas.Add(oSchema);
            XmlReader oXmlReader = null;
            if (oSchema != null)
            {
                oXmlReader = XmlReader.Create(filepath, oXmlReaderSettings);
            }
            else
            {
                oXmlReader = XmlReader.Create(filepath);
            }
            object obj = null;
            try
            {
                XmlSerializer oXmlSerializer = new XmlSerializer(type);
                obj = oXmlSerializer.Deserialize(oXmlReader);
            }
            finally
            {
                oXmlReader.Close();
            }
            return obj;
        }

        private static XmlSchema GetSchemaFromType(Type type)
        {
            var oSoapReflectionImporter = new SoapReflectionImporter();
            var oXmlTypeMapping = oSoapReflectionImporter.ImportTypeMapping(type);
            var oXmlSchemas = new XmlSchemas();
            var oXmlSchema = new XmlSchema();
            oXmlSchemas.Add(oXmlSchema);
            var oXMLSchemaExporter = new XmlSchemaExporter(oXmlSchemas);
            oXMLSchemaExporter.ExportTypeMapping(oXmlTypeMapping);
            return oXmlSchema;
        }

        private static dynamic GetObjFormfileWithoutValidation(string filepath, Type type)
        {
            XmlReader oXmlReader = null;
            oXmlReader = XmlReader.Create(filepath);
            object obj = null;
            try
            {
                XmlSerializer oXmlSerializer = new XmlSerializer(type);
                obj = oXmlSerializer.Deserialize(oXmlReader);
            }
            finally
            {
                oXmlReader.Close();
            }
            return obj;

        }

        private static void Saveobjecttofile(object objectToSave, string filepath)
        {
            try
            {
                System.Xml.Serialization.XmlSerializer oXmlSerializer = new System.Xml.Serialization.XmlSerializer(objectToSave.GetType());
                using (System.Xml.XmlTextWriter oXmlTextWriter = new System.Xml.XmlTextWriter(filepath, System.Text.Encoding.UTF8))
                {
                    oXmlTextWriter.Indentation = 2;
                    oXmlTextWriter.Formatting = System.Xml.Formatting.Indented;
                    oXmlSerializer.Serialize(oXmlTextWriter, objectToSave);
                    oXmlTextWriter.Flush();
                    oXmlTextWriter.Close();
                }
            }
            catch (Exception)
            { throw; }
        }
    }
    [XmlType("Items")]
    public class Items
    {
        [XmlAttribute("key")]
        public string key { get; set; }
        [XmlText()]
        public string value { get; set; }
    }

    [Serializable, XmlRoot("MyObject")]
    public class MyObject
    {
        [XmlElement("MyObjectType", IsNullable = true)]
        public string MyObjectType { get; set; }
        [XmlElement("Items")]
        public List<Items> Items;
        public string this[string key]
        {
            get
            {
                return null != Items.Find(x => x.key == key) ? Items.Find(x => x.key == key).value : null;
            }
            set
            {
                if (Items == null) Items = new List<Items>();
                if (null != Items.Find(x => x.key == key))
                {
                    Items.Find(x => x.key == key).value = value;
                }
                else
                {
                    Items.Add(new Items { key = key, value = value });
                }
            }
        }
    }
}

異常詳細信息:

System.Xml.Schema.XmlSchemaException
Message:There is an error in XML document (3, 10).
Inner Exception message:The 'key' attribute is not declared.
StackTrace:    
at system.Xml.Schema.XmlSchemaValidator.SendValidationEvent(XmlSchemaValidationException e, XmlSeverityType severity)
at System.Xml.Schema.XmlSchemaValidator.SendValidationEvent(String code, String arg)
at System.Xml.Schema.XmlSchemaValidator.ValidateAttribute(String lName, String ns, XmlValueGetter attributeValueGetter, String attributeStringValue, XmlSchemaInfo schemaInfo)
at System.Xml.Schema.XmlSchemaValidator.ValidateAttribute(String localName, String namespaceUri, XmlValueGetter attributeValue, XmlSchemaInfo schemaInfo)
at System.Xml.XsdValidatingReader.ValidateAttributes()
at System.Xml.XsdValidatingReader.ProcessElementEvent()
at System.Xml.XsdValidatingReader.ProcessReaderEvent()
at System.Xml.XsdValidatingReader.Read()
at System.Xml.XmlReader.MoveToContent()
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderMyObject.Read3_MyObject(Boolean isNullable, Boolean checkType)
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderMyObject.Read4_MyObject()

演示在這里擺弄。

您的問題在這里:

private static XmlSchema GetSchemaFromType(Type type)
{
    var oSoapReflectionImporter = new SoapReflectionImporter();

SoapReflectionImporter旨在為已用SOAP屬性標記的ac#類型生成模式。 這樣的模式可以用來生成XmlSerializer ,該XmlSerializer定制為使用這樣的屬性,如如何:將對象序列化為SOAP編碼的XML流所示

XmlTypeMapping myTypeMapping = new SoapReflectionImporter().ImportTypeMapping(type);
XmlSerializer mySerializer = new XmlSerializer(myTypeMapping);  

但是,您沒有使用SOAP屬性 您正在使用常規的XmlSerializer屬性 ,例如可以在Items類中看到:

[XmlType("Items")]
public class Items
{
    [XmlAttribute("key")]
    public string key { get; set; }
    [XmlText()]
    public string value { get; set; }
}

因此,您應該改用XmlReflectionImporter

private static XmlSchema GetSchemaFromType(Type type)
{
    var oReflectionImporter = new XmlReflectionImporter();
    var oXmlTypeMapping = oReflectionImporter.ImportTypeMapping(type);
    var oXmlSchemas = new XmlSchemas();
    var oXmlSchema = new XmlSchema();
    oXmlSchemas.Add(oXmlSchema);
    var oXMLSchemaExporter = new XmlSchemaExporter(oXmlSchemas);
    oXMLSchemaExporter.ExportTypeMapping(oXmlTypeMapping);
    return oXmlSchema;
}

相關: 如何從類型中以編程方式生成xml模式?

固定樣本演示在這里

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM