我从第三方获得XML,需要将其列为C#对象。此XML可能包含具有整数类型或空值的值的属性:attr =“ 11”或attr =“”。我想通过可随机整数的类型将此属性值列为属性。但是XMLSerializer不支持避难所化为无效类型。以下测试代码在使用InvalidOperationException创建XMLSerializer期间失败{“存在反映类型'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而言,避难所失败:
XML文档(1,16)中存在错误。
任何人都可以建议如何将属性带入空属性类型(作为零)(作为零),同时应将非空属性值归为整数?有什么技巧,所以我不必手动对每个字段进行挑选(实际上有很多)?
在Ahsteele的评论后更新:
-
据我所知,此属性仅适用于xmlelementAttribute-此属性指定该元素没有内容,无论是子元素还是身体文本。但是我需要找到Xmlattributeattribute的解决方案。无论如何,我无法更改XML,因为我无法控制它。
-
bool *指定的属性
仅在属性值不空时或丢失属性时,此属性才起作用。当atter具有空值(attr ='')时,xmlSerializer构造函数失败(如预期)。
公共类元素
{
[xmlattribute(“ attr”)]
public int value {get;放; }
[xmlignore]
公共布尔值规定;
}
-
我试图通过此博客文章将课程采用到我的问题:
[xmlattribute(“ attr”)]
公共nullableInt值{get;放; }
但是xmlSerializer构造函数失败了InvalidOperationException:
不能序列化testConsoLeApplication.nullableInt类型的成员“值”。
xmlattribute/xmlText不能用于编码实现IxmlSerializable}
的类型
-
丑陋的替代解决方案的类型(对我感到羞耻,我在此处写了此代码:)):
公共类元素
{
[xmlattribute(“ attr”)]
公共字符串setValue {get;放; }
公共INT? getValue()
{
if(string.isnullorenty(setValue)|| setValue.trim()。长度&lt; = 0)
返回null;
int结果;
if(int.tryparse(setValue,out结果))
返回结果;
返回null;
}
}
,但我不想提出这样的解决方案,因为它为消费者打破了我的班级的接口。我最好手动地实现IXMLSerializable界面。
目前,我似乎必须为整个元素类实现IXMLSerializizizizizable(这很大),而且没有简单的解决方法…
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);
}
}
When I change type of 'Value' property to int, deserialization fails with InvalidOperationException:
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)?
Update after comment from ahsteele:
-
Xsi:nil attribute
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.
-
bool *Specified property
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;
}
-
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; }
But XmlSerializer constructor fails with InvalidOperationException:
Cannot serialize member 'Value' of type TestConsoleApplication.NullableInt.
XmlAttribute/XmlText cannot be used to encode types implementing IXmlSerializable }
-
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;
}
}
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.
Currently it looks like I have to implement IXmlSerializable for the whole Element class (it is big) and there are no simple workaround…
发布评论
评论(8)
这应该有效:
This should work:
我通过实现IXMLSerializable接口解决了这个问题。我没有找到更轻松的方法。
这是测试代码样本:
I solved this problem by implementing IXmlSerializable interface. I did not found easier way.
Here is the test code sample:
我最近一直在处理很多序列化,并在处理值类型的无数据数据时发现了以下文章和帖子。
如何使c#中的xmlSerializer在c# - serialization 中详细介绍XMLSerialializer的漂亮技巧。具体而言,XMLSerialier寻找XXXSPEFIFIED BOOLEAN属性以确定是否应包括在内,这使您可以忽略nulls。
亚历克斯·斯科德利(Alex Scordellis)问了一个stackoverflow问题,该问题收到一个很好的答案。亚历克斯还在他的博客上做了很好的文章,他试图解决 使用XmlSerializer将其验证为无效的&lt; int&gt; 。
I've been messing around with serialization a lot myself of late and have found the following articles and posts helpful when dealing with null data for value types.
The answer to How to make a value type nullable with XmlSerializer in C# - serialization details a pretty nifty trick of the XmlSerializer. Specifically, the XmlSerialier looks for a XXXSpecified boolean property to determine if it should be included which allows you to ignore nulls.
Alex Scordellis asked a StackOverflow question which received a good answer. Alex also did a good writeup on his blog about the problem he was trying to solve Using XmlSerializer to deserialize into a Nullable<int>.
The MSDN documentation on Xsi:nil Attribute Binding Support is also useful. As is the documentation on IXmlSerializable Interface, though writing your own implementation should be your last resort.
以为我最好把答案扔到帽子上:
通过创建实现IXMLSerializable界面的自定义类型来解决此问题:
假设您有一个带有以下节点的XML对象:
表示它们的对象:
动态无效的struct,以表示任何潜在的无效条目以及转换的转换
Thought I might as well throw my answer into the hat:
Solved this issue by creating a custom type that implements the IXmlSerializable interface:
Say you have a an XML object with the following nodes:
The object to represent them:
Dynamic nullable struct to represent any potential nullable entries along with conversion
您也可以通过将
XML
加载到xmldocument
中,然后将其列为JSON
以获取对象t 您正在寻找的。
You can also do this by loading the
xml
into anXmlDocument
and then deserializing this intoJson
to get the objectT
that you are looking for.您需要两个课。头等舱是您的挑选性课程。任何无效的属性都应是字符串。
您这样装饰它:
它处理您的避难所。
您的第二堂课适合您的项目/DB。
它的属性看起来像这样:
您使用汽车应用程序或其他策略映射:
这可以使您的逻辑限制,并且您的课程专门用于他们应该做的事情。
这是.tonullableBool()的一个示例:
显然,您可以忽略此建议,使用Xmlignore,一个setter和getter分配字段/属性,然后在设置为字段时将此扩展类称为...但这完全取决于您。
You need two classes. The first class is your deserialization class. Any nullable properties should be strings.
You decorate it like this:
It handles your deserialization.
Your second class is for your project/db.
It's property looks something like this:
You map with automapper or with another strategy doing this:
This keeps your logic confined and your classes dedicated to what they should do.
Here's an example for .ToNullableBool():
Obviously, you can ignore this advice, assign a field/property with XmlIgnore, a setter and a getter and just call this extension class when setting to the field... but that's entirely up to you.
我需要进行无法修改的XML,缺少某些属性,我需要使它们无效。
很长一段时间以来,我一直在寻找一种简单而有效的解决方案,但不幸的是没有这样的解决方案。我不得不为具有无效字段的课程编写自己的IXMLSerializizizizizizizizizizizizizallizized。
然后,您只需从xmlnullableserializable即可继承您的类。
这仅适用于绝对化,您的类可以包含类型结构的可随机字段。
例子:
I needed to deserialize xml that could not be modified, it lacked some attributes, I needed to make them nullable.
I have been looking for a simple and working solution for a long time, but unfortunately there is no such solution. I had to write my own implementation of IXmlSerializable for a class with nullable fields.
Then you just inherit your class from XmlNullableSerializable.
This only works for deserialization, your class can contain nullable fields of type struct.
Example:
提供一个非常简单的解决方案,该解决方案适用于双打或其他价值类型,以使用可能的值之一(double.nan)为代价。它仅需要内置的序列化*()属性(无需额外的备份字段)。
到达上述情况,因为无效的价值类型在序列化到[XMLATTRIBUTES]时会引起异常,并且添加额外的属性似乎太多了。 XMLSerializer支持公共字段或属性,属性确实支持初始化器,因此当然,如果这是您的最佳实践,请使用属性。因为整数可以使用int.maxvalue如果您的域不需要。
Offering a very simple solution that works for doubles or other value types at the cost of using one of the possible values (double.NaN). It only requires the built-in ShouldSerialize*() property (no extra backing field needed).
Arrived at the above because nullable value types raise an exception when serializing to [XmlAttributes] and adding an extra property seems like too much complexity. XmlSerializer supports public fields or properties and properties do support initializers so of course use properties if that is your best practice. For integer could use int.MaxValue if your domain doesn't require it.