简体   繁体   English

使用空元素反序列化Xml

[英]Deserialize Xml with empty elements

Consider the following XML: 考虑以下XML:

<a>
    <b>2</b>
    <c></c>
</a>  

I need to deserialize this xml to an object. 我需要将这个xml反序列化为一个对象。 So, i wrote the following class. 所以,我写了下面的课。

public class A
{
    [XmlElement("b", Namespace = "")]
    public int? B { get; set; }

    [XmlElement("c", Namespace = "")]
    public int? C { get; set; }

}

Since i'm using nullables, i was expecting that, when deserialing the above xml, i would get an object A with a null C property. 因为我正在使用nullables,所以我期待在解析上面的xml时,我会得到一个带有null C属性的对象A.

Instead of this, i get an exception telling the document has an error. 而不是这个,我得到一个异常,告诉文档有错误。

There's a difference between a missing element and a null element. 缺少元素和null元素之间存在差异。

A missing element, <a><b>2</b></a> . 缺少元素<a><b>2</b></a> Here C would take whatever default value you specify, using the DefaultValue attribute, or null if there's no explicit default. 这里C将使用DefaultValue属性获取您指定的任何默认值,如果没有显式默认值,则为null。

A null element <a><b>2</b><c xs:Nil='true'/></a> . null元素<a><b>2</b><c xs:Nil='true'/></a> Here you will get null. 在这里你将得到null。

When you do <a><b>2</b><c></c><a/> the xml serializer will try to parse string.Empty as an integer an will correctly fail. 当您执行<a><b>2</b><c></c><a/> ,xml序列化程序将尝试将string.Empty解析为整数,将正确失败。

Since your provider is generating invalid xml you will need to do this, if using the XmlSerializer: 由于您的提供程序生成无效的xml,因此如果使用XmlSerializer,则需要执行此操作:

[XmlRoot(ElementName = "a")]
public class A
{
    [XmlElement(ElementName = "b")]
    public int? B { get; set; }

    [XmlElement(ElementName = "c")]
    public string _c { get; set; }

    public int? C
    {
        get
        {
            int retval;

            return !string.IsNullOrWhiteSpace(_c) && int.TryParse(_c, out retval) ? (int?) retval : null;
        }
    }
}

or slightly better using the DataContractSerializer 或使用DataContractSerializer略微好一些

[DataContract(Name="a")]
public class A1
{
    [DataMember(Name = "b")]
    public int? B { get; set; }

    [DataMember(Name = "c")]
    private string _c { get; set; }

    public int? C
    {
        get
        {
            int retval;

            return !string.IsNullOrWhiteSpace(_c) && int.TryParse(_c, out retval) ? (int?)retval : null;
        }
    }
}

although the DataContractSerializer doesn't support attributes if that's a problem. 虽然如果这是一个问题,DataContractSerializer不支持属性。

To deserialize empty tags like 'c' in your example: 要反序列化示例中的'c'之类的空标记:

    <foo>
        <b>2</b>
        <c></c>
    </foo>

I used this approach. 我用这种方法。 First it removes the null or empty elements from the XML file using LINQ and then it deserialize the new document without the null or empty tags to the Foo class. 首先,它使用LINQ从XML文件中删除null或空元素,然后将没有null或空标记的新文档反序列化到Foo类。

    public static Foo ReadXML(string file)
    {
            Foo foo = null;
            XDocument xdoc = XDocument.Load(file);
            xdoc.Descendants().Where(e => string.IsNullOrEmpty(e.Value)).Remove();

            XmlSerializer xmlSer = new XmlSerializer(typeof(Foo));
            using (var reader = xdoc.Root.CreateReader())
            {
                foo = (Foo)xmlSer.Deserialize(reader);
                reader.Close();
            }
            if (foo == null)
                foo = new Foo();

            return foo;
    }

Which will give you default values on the missing properties. 这将为您提供缺少的属性的默认值。

    foo.b = 2;
    foo.c = 0; //for example, if it's an integer

I joined information from this links : 我从这个链接加入了信息:

Remove empty XML tags 删除空XML标记

Use XDocument as the source for XmlSerializer.Deserialize? 使用XDocument作为XmlSerializer.Deserialize的源?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM