【问题标题】:get missing attributes in XML from XmlSerializer从 XmlSerializer 获取 XML 中缺少的属性
【发布时间】:2015-06-02 17:34:25
【问题描述】:

当我从 Xml 反序列化对象时,如何检查我的 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;
    }
}

【问题讨论】:

  • 如果没有MyDouble,您希望如何生成xml
  • Xml 是在旧版本的程序中生成的,其中不存在 MyDouble。在新版本中我添加了 MyDouble,但它在旧的 xml 文件中不存在。或者只是假设用户已经从 XML 文件中删除了一个元素。
  • 使元素NullableDeserialization 期间不应包含默认值。
  • “使元素可空”是什么意思?如果我将MyDouble 的定义更改为double? MyDouble 没有效果。默认值(在构造函数中)是必需的。

标签: c# xmlserializer


【解决方案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);

【讨论】:

  • 谢谢。我更新了我的问题,也许您对我的访问属性名称“MyDouble”的问题有解决方案?
猜你喜欢
  • 1970-01-01
  • 2019-12-23
  • 1970-01-01
  • 1970-01-01
  • 2012-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-05
相关资源
最近更新 更多