首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用XmlSerializer将空的xml属性值反序列化为可空的int属性

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

Stack Overflow用户
提问于 2009-08-18 18:35:26
回答 5查看 64.9K关注 0票数 81

我从第三方得到一个xml,我需要将它反序列化为C#对象。此xml可能包含整型或空值的属性:attr=“11”或attr=“”。我希望将此属性值反序列化为可为空的整数类型的属性。但是XmlSerializer不支持反序列化为可空类型。以下测试代码在使用InvalidOperationException {“反映类型'TestConsoleApplication.SerializeMe'."}创建XmlSerializer时失败。

代码语言:javascript
复制
[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:

文档(%1,% 16)中存在错误。

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

来自ahsteele的评论后更新:

  1. Xsi:nil attribute

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

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

public类元素{XmlAttribute(“}

我试着采用这篇博客文章中的类来解决我的问题:

XmlAttribute("attr")公共NullableInt值{ get;set;}

但使用InvalidOperationException时,XmlSerializer构造函数会失败:

无法序列化类型为TestConsoleApplication.NullableInt的成员“Value”。

XmlAttribute/XmlText不能用于编码实现IXmlSerializable }的类型

  1. 丑陋的代理解决方案(很遗憾我在这里写了这段代码:) ):

公共类元素{ XmlAttribute("attr")公共字符串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;}}

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

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

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2009-08-20 09:18:27

我通过实现IXmlSerializable接口解决了这个问题。我没有找到更简单的方法。

下面是测试代码示例:

代码语言:javascript
复制
[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);
    }
}
票数 23
EN

Stack Overflow用户

发布于 2009-09-25 19:36:52

这应该是可行的:

代码语言:javascript
复制
[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?); }
}
票数 69
EN

Stack Overflow用户

发布于 2009-08-18 18:57:23

最近我自己也花了很多时间处理序列化,我发现下面的文章和帖子对处理值类型的空数据很有帮助。

对的回答详细描述了XmlSerializer的一个非常巧妙的技巧。具体地说,XmlSerialier查找XXXSpecified布尔值属性,以确定是否应包含该属性,从而允许您忽略空值。

Alex Scordellis问了一个收到a good answer的StackOverflow问题。Alex还在他的博客上写了一篇关于他试图解决的问题的文章。

Xsi:nil Attribute Binding Support上的MSDN文档也很有用。与IXmlSerializable Interface上的文档一样,编写自己的实现应该是您最后的选择。

票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1295697

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档