我需要将某些字段标记为在XML文件中写入,但没有成功。我有一个具有约30个属性的配置类,这就是为什么我不能包含所有这样的属性
public string SomeProp
{
get { return _someProp; }
set
{
if (_someProp == null)
throw new ArgumentNullException("value");
_someProp = value;
}
}
和null是代码中的有效值,但不是来自XML的有效值。我正在尝试使用XmlAttribute
,但它不会像我预期的那样影响(反序列化时的IOException)。
例如这段代码:
[XmlElement(IsNullable = true)]
public String Name { get; set; }
[XmlElement(IsNullable = true)]
public String Description { get; set; }
在缺少Name
和Description
标签时非常有效。
澄清:
类别:
public class MyClass
{
[XmlElement(IsNullable = true)]
public String Name { get; set; }
[XmlElement(IsNullable = true)]
public String Description { get; set; }
}
XML:
<?xml version="1.0"?>
<MyClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>hello</Name>
</MyClass>
代码:
MyClass deserialize = (MyClass)new XmlSerializer(my.GetType()).Deserialize(new FileStream("result.xml", FileMode.Open));
Console.WriteLine(deserialize.Name);
Console.WriteLine(deserialize.Description);
结果:deserialization is successful, Description is null
预期:exception, Description tag not found.
答案 0 :(得分:3)
我相信你可以采用两种方法。一种是使用一个使用模式的验证XmlReader,另一种是反序列化后的反射检查。最后一个选项是我在这里提供的解决方案:
这个帮助器获取一个流并将给定泛型类型的反序列化为该类型的实例。一旦该对象存在,就可以迭代并检查属性是否使用XmlElementAttribute进行修饰。如果找到该属性,则检查其IsNullable属性,如果为false且对象实例上的属性为false,则抛出异常。
public T ValidatingDeserializer<T>(Stream s)
{
T deserialize = (T)new XmlSerializer( typeof(T)).Deserialize(s);
foreach(var pi in typeof(T).GetProperties())
{
var xmlnull = pi.GetCustomAttribute(typeof(XmlElementAttribute));
if (xmlnull!=null)
{ var xmlnullInst = (XmlElementAttribute) xmlnull;
if (!xmlnullInst.IsNullable && pi.GetValue(deserialize)==null)
{
throw new Exception(String.Format("{0} is null", pi.Name));
}
}
}
return deserialize;
}
MyClass deserialize = ValidatingDeserializer<MyClass>(
new FileStream("result.xml", FileMode.Open));
Console.WriteLine(deserialize.Name);
Console.WriteLine(deserialize.Description);
通过使用架构,您可以针对给定架构verify if the supplied XML document is valid。
这需要一个xml流和一个模式流,钩住一个引发错误的事件,并返回一个XmlReader,它将是Deserialize
方法的输入。
public XmlReader ReaderFactory(Stream xml, Stream schema)
{
XmlSchemaSet sc = new XmlSchemaSet();
// Add the schema to the collection.
sc.Add(null, XmlReader.Create(schema));
// Set the validation settings.
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
settings.Schemas = sc;
settings.ValidationEventHandler += new ValidationEventHandler (ValidationCallBack);
return XmlReader.Create(xml, settings);
}
private static void ValidationCallBack(object sender, ValidationEventArgs e) {
Console.WriteLine(
"Validation Error: {0} near line: {1}, pos: {2}",
e.Message,
e.Exception.LineNumber,
e.Exception.LinePosition);
throw new Exception("illegal xml content");
}
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns=""
elementFormDefault="qualified">
<xsd:element name="MyClass" >
<xsd:complexType>
<xsd:sequence maxOccurs="1">
<xsd:element name="Name" type="xsd:string"/>
<xsd:element name="Description" type="xsd:string" minOccurs="1">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
答案 1 :(得分:3)
你必须使用XmlSerializer
吗? DataContractSerializer
提供以下选项:
[DataMember(IsRequired = true)]