使用XmlSeriizer将空xml属性值反序列化为nullable int属性?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (59)

我从第三方获得一个XML,我需要将它反序列化为C#对象。这个XML可能包含整型值或空值的属性:ATTR=“11”或attr=“”。我希望将这个属性值反序列化为具有可空整数类型的属性。但是XmlSeriizer不支持将反序列化为可空类型。以下测试代码在创建带有InvalidOperationException{“有错误反映类型‘TestConsoleApplicationes.erializeMe’”的XmlSeriizer时失败。

[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)吗?这有什么窍门吗,所以我不需要手动对每个字段进行反序列化(实际上有很多这样的字段)?

提问于
用户回答回答于

我通过实现IXmlSerialable接口解决了这个问题。我没有找到更容易的方法。

下面是测试代码示例:

[XmlRoot("root")]
public class DeserializeMe {
    [XmlArray("elements"), XmlArrayItem("element")]
    public List<Element> Element { get; set; }
}

public class Element : IXmlSerializable {
    public int? Value1 { get; private set; }
    public float? Value2 { get; private set; }

    public void ReadXml(XmlReader reader) {
        string attr1 = reader.GetAttribute("attr");
        string attr2 = reader.GetAttribute("attr2");
        reader.Read();

        Value1 = ConvertToNullable<int>(attr1);
        Value2 = ConvertToNullable<float>(attr2);
    }

    private static T? ConvertToNullable<T>(string inputValue) where T : struct {
        if ( string.IsNullOrEmpty(inputValue) || inputValue.Trim().Length == 0 ) {
            return null;
        }

        try {
            TypeConverter conv = TypeDescriptor.GetConverter(typeof(T));
            return (T)conv.ConvertFrom(inputValue);
        }
        catch ( NotSupportedException ) {
            // The conversion cannot be performed
            return null;
        }
    }

    public XmlSchema GetSchema() { return null; }
    public void WriteXml(XmlWriter writer) { throw new NotImplementedException(); }
}

class TestProgram {
    public static void Main(string[] args) {
        string xml = @"<root><elements><element attr='11' attr2='11.3'/><element attr='' attr2=''/></elements></root>";
        XmlSerializer deserializer = new XmlSerializer(typeof(DeserializeMe));
        Stream xmlStream = new MemoryStream(Encoding.ASCII.GetBytes(xml));
        var result = (DeserializeMe)deserializer.Deserialize(xmlStream);
    }
}
用户回答回答于

这样做应该可行:

[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?); }
}

扫码关注云+社区