【发布时间】:2018-10-17 03:55:37
【问题描述】:
我将一个类序列化为 XML。但是启用模式验证后,反序列化到相同的类类型会失败。
这是我正在做的事情:
- 从可序列化类创建对象
- 将该对象序列化为 XML
- 从该对象获取架构
- 将该架构添加到验证中
- 不经验证反序列化
- 使用 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()
演示小提琴here.
【问题讨论】:
-
这是失败的生产代码的精确副本。我正在模拟失败场景。
-
您是否将
GetSchemaFromType的代码从this answer 复制到How do I programmatically generate an xml schema from a type??如果是这样,请参阅stackoverflow.com/help/referencing。
标签: c# xml deserialization xmlserializer