.net - 使用 XmlSerializer 将空的 xml 属性值反序列化为可为空的 int 属性

标签 .net xml serialization nullable

我从第 3 方获得了一个 xml,我需要将其反序列化为 C# 对象。此 xml 可能包含值为整数类型或空值的属性:attr=”11”或 attr=””。我想将此属性值反序列化为类型为可为 null 的整数的属性。但是 XmlSerializer 不支持反序列化为可为 null 的类型。以下测试代码在创建 XmlSerializer 期间失败并出现 InvalidOperationException {“反射(reflect)类型 'TestConsoleApplication.SerializeMe' 时出现错误。”}。

[XmlRoot("root")]
public class SerializeMe
{
    [XmlElement("element")]
    public Element Element { get; set; }
}

public class Element
{
    [XmlAttribute("attr")]
    public int? Value { get; set; }
}

class Program {
    static void Main(string[] args) {
        string xml = "<root><element attr=''>valE</element></root>";
        var deserializer = new XmlSerializer(typeof(SerializeMe));
        Stream xmlStream = new MemoryStream(Encoding.ASCII.GetBytes(xml));
        var result = (SerializeMe)deserializer.Deserialize(xmlStream);
    }
}

当我将“Value”属性的类型更改为 int 时,反序列化失败并出现 InvalidOperationException:

There is an error in XML document (1, 16).

有人可以建议如何将具有空值的属性反序列化为可空类型(作为 null),同时将非空属性值反序列化为整数吗?这有什么技巧吗,这样我就不必手动对每个字段进行反序列化(实际上有很多)?

根据 ahsteele 的评论更新:

  1. Xsi:nil attribute

    据我所知,此属性仅适用于 XmlElementAttribute - 此属性指定元素没有内容,无论是子元素还是正文。但我需要找到 XmlAttributeAttribute 的解决方案。无论如何,我无法更改 xml,因为我无法控制它。

  2. bool *Specified property

    此属性仅在属性值非空或属性缺失时有效。当 attr 具有空值 (attr='') 时,XmlSerializer 构造函数失败(如预期的那样)。

    public class Element
    {
        [XmlAttribute("attr")]
        public int Value { get; set; }
    
        [XmlIgnore]
        public bool ValueSpecified;
    }
    
  3. Custom Nullable class like in this blog post by Alex Scordellis

    我尝试采用这篇博文中的类(class)来解决我的问题:

    [XmlAttribute("attr")]
    public NullableInt Value { get; set; } 
    

    但是 XmlSerializer 构造函数因 InvalidOperationException 失败:

    Cannot serialize member 'Value' of type TestConsoleApplication.NullableInt.

    XmlAttribute/XmlText cannot be used to encode types implementing IXmlSerializable }

  4. 丑陋的代理解决方案(让我感到羞耻的是我在这里写了这段代码:)):

    public class Element
    {
        [XmlAttribute("attr")]
        public string SetValue { get; set; }
    
        public int? GetValue()
        {
            if ( string.IsNullOrEmpty(SetValue) || SetValue.Trim().Length <= 0 )
                return null;
    
            int result;
            if (int.TryParse(SetValue, out result))
                return result;
    
            return null;
        }
    }
    

    但我不想提出这样的解决方案,因为它会破坏我的类为其消费者提供的接口(interface)。我最好手动实现 IXmlSerializable 接口(interface)。

目前看来我必须为整个 Element 类(它很大)实现 IXmlSerializable 并且没有简单的解决方法......

最佳答案

这应该有效:

[XmlIgnore]
public int? Age { get; set; }

[XmlElement("Age")]
public string AgeAsText
{
  get { return (Age.HasValue) ? Age.ToString() : null; } 
  set { Age = !string.IsNullOrEmpty(value) ? int.Parse(value) : default(int?); }
}

关于.net - 使用 XmlSerializer 将空的 xml 属性值反序列化为可为空的 int 属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1295697/

相关文章:

c# - 按顺序使用数组获取文件

c# - 在 XAML 中查找打开的窗口

c# - 哪个更快地读取 XML 文件或查询数据库

c# - 直接从内存处理C#中的内存映射文件

jquery - 如何删除博客小部件的白边距?

Android常量值到常量名称(app :showAsAction ="2")

javascript - 使用 JavaScript 在 HTML 中搜索 XML

c# - 如何反序列化具有许多子节点的 XML

java - Parcelable 与 Serialized - 对于没有任何字段的类

java - 无法序列化 ArrayList