[英]C# Serializing XmlElement with XmlText
我需要复制这种XML格式:
<item>
<attribute1>1</attribute1>
<attribute2 something="true">
2
</attribute2>
<attribute3 something="false">
3
</attribute3>
<!-- goes on until attribute25 -->
</item>
我目前正在使用这样的东西来实现我想要的东西:
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:
/// <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);
}
}
但是,在序列化我的Item
我得到:
<item>
<attribute1 />
<attribute2 />
<attribute3 />
</item>
如何修复我的CustomElement
类,以便不会丢失值?
你有几个问题:
您正在尝试将XmlValue
成员序列化为为CustomElement<T>
实例生成的元素的元素值,但您已将其定义为只读 表达式 - 身体成员 :
public T XmlValue => Value;
XmlSerializer
只会序列化公共读/写属性和字段,因此您必须添加setter和getter:
[XmlText] public T XmlValue { get => Value; set => Value = value; }
或者,为了简化模型,您可以完全消除XmlValue
并通过使用[XmlText]
标记来直接序列化Value
。 XML序列化属性可以应用于字段和属性。
您正在尝试使用{propertyName}Specified
模式在基础值为null
时禁止<something>
元素的序列化。 此模式主要用于跟踪是否遇到关联元素,因此必须使用[XmlIgnore]
标记xxxSpecified
属性:
[XmlIgnore] public bool XmlSomethingSpecified => Something.HasValue;
或者,由于您实际上不需要跟踪<something>
元素的存在,您可以通过切换到ShouldSerialize{PropertyName}()
模式来简化模型:
public bool ShouldSerializeXmlSomething() => Something.HasValue;
两个模式之间的差异在ShouldSerialize ()vs Specified Conditional Serialization Pattern中描述 。
如果您的Item
类型将是XML文档的根元素,则必须使用[XmlRoot("item")]
标记它以使根元素的名称为<item>
:
[XmlRoot("item")] [XmlType(TypeName = "ci")] public class Item { // Etc Etc }
在您的c#代码中,您已使用[XmlElement]
标记了XmlSomething
属性,但在XML中, something
内容显示为元素 : <something>true</something>
。
如果你真的希望它是一个元素,你必须用[XmlElement]
标记XmlSomething
:
[XmlElement("something")] public bool XmlSomething { get => Something != null && Something.Value; set => Something = value; }
在您的问题中,您将显示具有非布尔文本值的<something>
元素的示例:
<attribute3> 3 <something>text</something> </attribute3>
我认为这是问题中的拼写错误,但如果没有,您将需要重新设计您的CustomElement<T>
类型以使Something
成为string
。
样本工作Roslyn .Net小提琴 , 第二个用于CustomElement<T>
的建议简化, 第三个用 <something>
作为子元素出现。
来自第二小提琴的课程如下:
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.