我将一个类序列化为XML。但是,启用模式验证后,对相同类类型的反序列化将失败。
这是我在做什么:
在第六步中,它失败了...
在此代码示例中,带有验证的方法失败:
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。
答案 0 :(得分:0)
您的问题在这里:
private static XmlSchema GetSchemaFromType(Type type)
{
var oSoapReflectionImporter = new SoapReflectionImporter();
SoapReflectionImporter
旨在为已标记为SOAP attributes的c#类型生成模式。这样的模式可用于生成定制的XmlSerializer
以使用这些属性,如 How to: Serialize an Object as a SOAP-Encoded XML Stream 中所示:
XmlTypeMapping myTypeMapping = new SoapReflectionImporter().ImportTypeMapping(type);
XmlSerializer mySerializer = new XmlSerializer(myTypeMapping);
但是,您没有使用SOAP属性。您正在使用常规XmlSerializer
attributes ,例如在您的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;
}
相关: How do I programmatically generate an xml schema from a type?
修复了示例演示here。