反序列化空的xml属性值到使用XmlSerializer的可为空整型属性 [英] Deserializing empty xml attribute value into nullable int property using XmlSerializer

查看:1986
本文介绍了反序列化空的xml属性值到使用XmlSerializer的可为空整型属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从第三方的XML,我需要反序列化到C#对象。这个XML可能包含整型值或空值的价值属性:ATTR =11或ATTR =。我想这个属性值反序列化与空整数类型的属性。但是XmlSerializer的不支持反序列化到可空类型。 XmlSerializer的创造与InvalidOperationException异常在下面的测试code未能{有一个错误反映类型'TestConsoleApplication.SerializeMe'。}。

I get an xml from the 3rd party and I need to deserialize it into C# object. This xml may contain attributes with value of integer type or empty value: attr="11" or attr="". I want to deserialize this attribute value into the property with type of nullable integer. But XmlSerializer does not support deserialization into nullable types. The following test code fails during creation of XmlSerializer with InvalidOperationException {"There was an error reflecting type '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);
    }
}

当我改变的值属性为int型,反序列化失败,出现InvalidOperationException:

When I change type of 'Value' property to int, deserialization fails with InvalidOperationException:

有一个在XML文档(1,16)。

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

任何人都可以告知如何同时反序列化的非空属性值到整数反序列化的属性与空值转换成可空类型(空)?有没有什么诀窍这个,所以我就不必手动操作的每个字段的反序列化(实际上也有很多他们)?

Can anybody advise how to deserialize attribute with empty value into nullable type (as a null) at the same time deserializing non-empty attribute value into the integer? Is there any trick for this so I will not have to do deserialization of each field manually (actually there are a lot of them)?

从ahsteele意见后更新:

Update after comment from ahsteele:

  1. XSI的:无属性

据我所知,这个属性只适用于XmlElementAttribute - 这个属性指定元素没有内容,无论是子元素或正文。但我需要找到XmlAttributeAttribute的解决方案。反正我不能改变的XML,因为我有没有对其进行控制。

As far as I know, this attribute works only with XmlElementAttribute - this attribute specifies that the element has no content, whether child elements or body text. But I need to find the solution for XmlAttributeAttribute. Anyway I cannot change xml because I have no control over it.

<一个href="http://stackoverflow.com/questions/703137/how-to-make-a-value-type-nullable-with-xmlserializer-in-c-serialization/703257#703257">bool *指定属性

这个属性只在属性值不为空或者属性丢失。当ATTR具有空值(ATTR ='')XmlSerializer的构造失败(如预期)。

This property works only when attribute value is non-empty or when attribute is missing. When attr has empty value (attr='') the XmlSerializer constructor fails (as expected).

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

    [XmlIgnore]
    public bool ValueSpecified;
}

  • <一个href="http://alexscordellis.blogspot.com/2008/11/using-xmlserializer-to-deserialize-into.html">Custom可空类像亚历克斯Scordellis 这篇博客

  • Custom Nullable class like in this blog post by Alex Scordellis

    我试图从这个博客帖子我的问题采取类:

    I tried to adopt the class from this blog post to my problem:

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

    但XmlSerializer的构造失败,出现InvalidOperationException:

    But XmlSerializer constructor fails with InvalidOperationException:

    无法序列类型TestConsoleApplication.NullableInt成员值。

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

    XmlAttribute / XMLTEXT不能使用EN code两类实施的IXmlSerializable}

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

    丑陋的替代解决方案(可耻的是我,我在这里写这篇code :)):

  • Ugly surrogate solution (shame on me that I wrote this code here :) ):

    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;
        }
    }
    

    但我不想要的,因为它打破了我班的消费者接口拿出这样的解决方案。我会更好地手动实现的IXmlSerializable接口。

    But I don’t want to come up with the solution like this because it breaks interface of my class for its consumers. I would better manually implement IXmlSerializable interface.

    目前,它看起来像我要实现的IXmlSerializable整个元素类(这是很大的),并没有简单的解决办法...

    Currently it looks like I have to implement IXmlSerializable for the whole Element class (it is big) and there are no simple workaround…

    推荐答案

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

    I solved this problem by implementing IXmlSerializable interface. I did not found easier way.

    下面是测试code样品:<​​/ P>

    Here is the test code sample:

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

    这篇关于反序列化空的xml属性值到使用XmlSerializer的可为空整型属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆