从XmlSerializer中获取XML中缺少的属性

时间:2015-06-02 08:30:09

标签: c# xmlserializer

当我从Xml反序列化一个Object时,如何检查xml中是否缺少某个属性或元素?

XmlSerializer使用默认值填充缺失值,但我怎么知道它是默认值还是Xml中缺少值?

我必须知道这一点,因为如果我发布了我的程序的新版本并为我的对象添加了值,我想向用户显示一个带有新(缺失)值的提示。他必须了解情况。

[Serializable]
public class Dummy
{
    public int MyInteger { get; set; }
    public string MyString { get; set; }
    public double MyDouble { get; set; }
    public bool MyBool { get; set; }
    public Dummy()
    {
        //Missing values in the xml would filled up with these values
        MyInteger = default(int);
        MyString = default(string);
        MyDouble = default(double);
        MyBool = default(bool);
    }
}
class Program
{

    static void Main(string[] args)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(Dummy));
        Dummy dummy = new Dummy(){ MyInteger = 1, MyBool = false, MyDouble = 3.4, MyString="dummy"};

        StringBuilder sb = new StringBuilder();
        using(StringWriter writer = new StringWriter(sb))
            serializer.Serialize(writer, dummy);
        /*sb contains:
         *  <?xml version="1.0" encoding="utf-16"?>
         *  <Dummy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
         *      <MyInteger>1</MyInteger>
         *      <MyString>dummy</MyString>
         *      <MyDouble>3.4</MyDouble>
         *      <MyBool>false</MyBool>
         *  </Dummy>
         */

        //xml without MyDouble
        string xml = @" <Dummy>
                    <MyInteger>1</MyInteger>
                    <MyString>dummy</MyString>
                    <MyBool>false</MyBool>
                </Dummy>";
        Dummy readDummy;
        using (StringReader reader = new StringReader(xml))
            readDummy = (Dummy)serializer.Deserialize(reader);

        /*readDummy contains:
         * MyInteger = 1,
         * MyString = "dummy",
         * MyDouble = 0,
         * MyBool = false
         */
    }
}

更新

感谢Yeldar Kurmangaliyev进行架构验证。 我当前的问题是Schema-Validator抛出的异常让我只访问MyBool而不是MyDouble缺失值。 Exception-Message包含属性MyDouble的名称,但是我应该从Exception-Message中提取属性名称吗?感觉很脏。

以下是更新后的代码:

[Serializable]
public class Dummy
{
    public int MyInteger { get; set; }
    public string MyString { get; set; }
    public double MyDouble { get; set; }
    public bool MyBool { get; set; }
    public Dummy()
    {
        //Missing values in the xml would filled up with these values
        MyInteger = default(int);
        MyString = default(string);
        MyDouble = default(double);
        MyBool = default(bool);
    }
}
class Program
{

    static void Main(string[] args)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(Dummy));
        string xml = @" <Dummy>
            <MyInteger>1</MyInteger>
            <MyString>dummy</MyString>
            <MyBool>false</MyBool>
        </Dummy>";
        Dummy readDummy;


        XmlReaderSettings settings = new XmlReaderSettings() { ValidationType = ValidationType.Schema };
        settings.Schemas.Add(GetXmlSchemas(typeof(Dummy)).First());
        settings.ValidationEventHandler += (s, e) =>
        {
            //I got an exception with the sender "MyBool". How I can reach the variable "MyDouble" which is missing?
        };

        using (StringReader reader = new StringReader(xml))
        using (XmlReader xmlReader = XmlReader.Create(reader, settings))
            readDummy = (Dummy)serializer.Deserialize(xmlReader);
    }
    public static XmlSchemas GetXmlSchemas(Type type)
    {
        var schemas = new XmlSchemas();
        var exporter = new XmlSchemaExporter(schemas);
        var mapping = new XmlReflectionImporter().ImportTypeMapping(type);
        exporter.ExportTypeMapping(mapping);
        return schemas;
    }
}

1 个答案:

答案 0 :(得分:1)

您可以使用XmlReaderSettings课程来初始化XmlReader并使用StringReader。但是,您将需要XSD架构。 这是在反序列化时验证XML的正确方法 看看XmlReaderSettings。也许,你会发现一种更简单的方法:)

string xml = @" <Dummy>
                <MyInteger>1</MyInteger>
                <MyString>dummy</MyString>
                <MyBool>false</MyBool>
            </Dummy>";
Dummy readDummy;

XmlSchemaSet schemas = null; // here is your schema
XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas.Add(schemas);
settings.ValidationType = ValidationType.Schema;
settings.ValidationEventHandler += (s, e) =>
{
    throw e.Exception; // Here you go
};

using (StringReader reader = new StringReader(xml))
   using (XmlReader xmlReader = XmlReader.Create(reader, settings))
       readDummy = (Dummy)serializer.Deserialize(xmlReader);