[英]C# Serializing XmlElement with XmlText
I have this XML format I need to replicate: 我需要复制这种XML格式:
<item>
<attribute1>1</attribute1>
<attribute2 something="true">
2
</attribute2>
<attribute3 something="false">
3
</attribute3>
<!-- goes on until attribute25 -->
</item>
I'm currently using something like this to achieve what I want: 我目前正在使用这样的东西来实现我想要的东西:
Item.cs: Item.cs:
[XmlType(TypeName = "item")]
public class Item {
[XmlElement("attribute1")]
public CustomElement<string> Attribute1 { get; set; }
[XmlElement("attribute2")]
public CustomElement<string> Attribute2 { get; set; }
[XmlElement("attribute3")]
public CustomElement<string> Attribute3 { get; set; }
// Etc Etc
}
CustomElement.cs: CustomElement.cs:
/// <summary>
/// Represents a CustomElement.
/// </summary>
/// <typeparam name="T">The type for the value of the element.</typeparam>
public class CustomElement<T>
{
[XmlIgnore] public T Value;
[XmlText]
public T XmlValue => Value;
public CustomElement()
{
}
public CustomElement(T value)
{
Value = value;
}
[XmlIgnore]
public bool? Something { get; set; }
[XmlAttribute("something")]
public bool XmlSomething
{
get => Something != null && Something.Value;
set => Something = value;
}
public bool XmlSomethingSpecified => Something.HasValue;
public static implicit operator CustomElement<T>(T x)
{
return new CustomElement<T>(x);
}
}
However, after serializing my Item
I get: 但是,在序列化我的Item
我得到:
<item>
<attribute1 />
<attribute2 />
<attribute3 />
</item>
How do I fix my CustomElement
class so the value doesn't get lost? 如何修复我的CustomElement
类,以便不会丢失值?
You have several problems here: 你有几个问题:
You are trying to serialize the XmlValue
member as the element value for the element generated for an instance of CustomElement<T>
, but you have defined it as a read-only expression-bodied member : 您正在尝试将XmlValue
成员序列化为为CustomElement<T>
实例生成的元素的元素值,但您已将其定义为只读 表达式 - 身体成员 :
public T XmlValue => Value;
XmlSerializer
will only serialize public read/write properties and fields, so you must add a setter as well as a getter: XmlSerializer
只会序列化公共读/写属性和字段,因此您必须添加setter和getter:
[XmlText] public T XmlValue { get => Value; set => Value = value; }
Alternatively, to simplify your model you could eliminate XmlValue
entirely and serialize Value
directly by marking it with [XmlText]
. 或者,为了简化模型,您可以完全消除XmlValue
并通过使用[XmlText]
标记来直接序列化Value
。 XML serialization attributes can be applied to fields as well as properties. XML序列化属性可以应用于字段和属性。
You are trying to suppress serialization of the <something>
element when the underlying value is null
using the {propertyName}Specified
pattern . 您正在尝试使用{propertyName}Specified
模式在基础值为null
时禁止<something>
元素的序列化。 This pattern is primarily used for tracking whether or not an associated element is encountered, and so the xxxSpecified
property must be marked with [XmlIgnore]
: 此模式主要用于跟踪是否遇到关联元素,因此必须使用[XmlIgnore]
标记xxxSpecified
属性:
[XmlIgnore] public bool XmlSomethingSpecified => Something.HasValue;
Or, since you don't actually need to track the presence of the <something>
element, you could simplify your model by switching to the ShouldSerialize{PropertyName}()
pattern: 或者,由于您实际上不需要跟踪<something>
元素的存在,您可以通过切换到ShouldSerialize{PropertyName}()
模式来简化模型:
public bool ShouldSerializeXmlSomething() => Something.HasValue;
The differences between the two patterns are described in ShouldSerialize () vs Specified Conditional Serialization Pattern . 两个模式之间的差异在ShouldSerialize ()vs Specified Conditional Serialization Pattern中描述 。
If your Item
type is going to be the root element of your XML document, you must mark it with [XmlRoot("item")]
to make the root element's name be <item>
: 如果您的Item
类型将是XML文档的根元素,则必须使用[XmlRoot("item")]
标记它以使根元素的名称为<item>
:
[XmlRoot("item")] [XmlType(TypeName = "ci")] public class Item { // Etc Etc }
In your c# code you have marked the XmlSomething
property with [XmlElement]
but in your XML something
is shown as an element : <something>true</something>
. 在您的c#代码中,您已使用[XmlElement]
标记了XmlSomething
属性,但在XML中, something
内容显示为元素 : <something>true</something>
。
If you really want it to be an element you must mark XmlSomething
with [XmlElement]
: 如果你真的希望它是一个元素,你必须用[XmlElement]
标记XmlSomething
:
[XmlElement("something")] public bool XmlSomething { get => Something != null && Something.Value; set => Something = value; }
In your question, you show an example of a <something>
element with a non-boolean textual value: 在您的问题中,您将显示具有非布尔文本值的<something>
元素的示例:
<attribute3> 3 <something>text</something> </attribute3>
I reckon this is a typo in the question, but if not, you will need to redesign your CustomElement<T>
type to make Something
be a string
. 我认为这是问题中的拼写错误,但如果没有,您将需要重新设计您的CustomElement<T>
类型以使Something
成为string
。
Sample working Roslyn .Net fiddle , and a second with the suggested simplifications for CustomElement<T>
, and a third where <something>
appears as a child element. 样本工作Roslyn .Net小提琴 , 第二个用于CustomElement<T>
的建议简化, 第三个用 <something>
作为子元素出现。
The classes from the second fiddle look like: 来自第二小提琴的课程如下:
public class CustomElement<T>
{
[XmlText]
public T Value;
public CustomElement()
{
}
public CustomElement(T value)
{
Value = value;
}
[XmlIgnore]
public bool? Something { get; set; }
[XmlAttribute("something")]
public bool XmlSomething
{
get => Something != null && Something.Value;
set => Something = value;
}
public bool ShouldSerializeXmlSomething() => Something.HasValue;
public static implicit operator CustomElement<T>(T x)
{
return new CustomElement<T>(x);
}
}
[XmlRoot("item")]
[XmlType(TypeName = "ci")]
public class Item
{
[XmlElement("attribute1")]
public CustomElement<string> Attribute1 { get; set; }
[XmlElement("attribute2")]
public CustomElement<string> Attribute2 { get; set; }
[XmlElement("attribute3")]
public CustomElement<string> Attribute3 { get; set; }
// Etc Etc
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.