gpt4 book ai didi

c# - C# 中具有属性的可空元素的 XML 序列化

转载 作者:行者123 更新时间:2023-11-30 23:26:15 25 4
gpt4 key购买 nike

我们使用属性 nilReason 来表达 XML 元素为空的原因。示例:

<dateOfDeath nilReason="noValue" xsi:nil="true"/>
<dateOfDeath nilReason="valueUnknown" xsi:nil="true"/>

在第一个例子中,这个人还活着,因为没有死亡日期。在第二个例子中,我们不知道死亡日期是多少。

此元素的 XSD 定义如下:

<xs:element name="dateOfDeath" type="DateOfDeath" nillable="true"/>
<xs:complexType name="DateOfDeath">
<xs:simpleContent>
<xs:extension base="xs:date">
<xs:attribute name="nilReason" type="NilReason"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:simpleType name="NilReason">
<xs:restriction base="xs:string">
<xs:enumeration value="noValue"/>
<xs:enumeration value="valueUnknown"/>
</xs:restriction>
</xs:simpleType>

我在使用 .net 框架提供的 XSD.exe 工具生成 C# 类时遇到问题。如何编写生成以下 XML 的代码?

<dateOfDeath nilReason="noValue" xsi:nil="true"/>

这是我能写出的最好的近似代码:

DateOfDeath dateOfDeath = new DateOfDeath();
dateOfDeath.nilReason = NilReason.noValue;
dateOfDeath.nilReasonSpecified = true;
XmlSerializer serializer = new XmlSerializer(typeof(DateOfDeath));
StreamWriter writer = new StreamWriter("dateofdeath.xml");
serializer.Serialize(writer, dateOfDeath);
writer.Close();

然而,不幸的是,这段代码产生了以下结果:

<dateOfDeath nilReason="noValue">0001-01-01</dateOfDeath>

这不是我想要的,因为它生成了一个虚拟日期值。看来这是序列化器的一个缺点。避免此问题的唯一方法似乎是应用一个函数,该函数删除虚拟值并在序列化后插入 xsi:nil="true"属性。然后还需要一个在反序列化之前删除 xsi:nil="true"属性的函数。否则nilReason-attribute的信息会在反序列化过程中被丢弃。

最佳答案

问题是属性是在同一个 DateOfDeath 类中与其值一起生成的(为简洁起见,我省略了一些代码):

public partial class DateOfDeath
{
private NilReason nilReasonField;
private bool nilReasonFieldSpecified;
private System.DateTime valueField;

[System.Xml.Serialization.XmlAttributeAttribute()]
public NilReason nilReason
{
get/set...
}

[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool nilReasonSpecified
{
get/set...
}

[System.Xml.Serialization.XmlText(DataType = "date")]
public System.DateTime Value
{
get/set...
}
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.81.0")]
[System.SerializableAttribute()]
public enum NilReason
{
noValue,
valueUnknown,
}

因此,为了序列化一个 nil 元素,您必须将父级设置为 null:

DateOfDeath dod = null;
serializer.Serialize(stream, dod);

产生类似的东西:

<dateOfDeath xmlns:xsi="..." xmlns:xsd="..." xsi:nil="true" />

这当然会导致您无法设置属性:

DateOfDeath dod = null;
dod.nilReason = noValue; // does not work with nullpointer

然而,该值呈现为 xml 元素的文本,如:

<dateOfDeath xmlns:xsi="..." xmlns:xsd="...">[value]</dateOfDeath>

其中 [value] 当然是您日期的文本表示。因此,即使您可以将值设置为 null - 因为您无法将复杂类型(例如 Nullable )呈现为 XmlText,所以您不能将其设置为 null - 您仍然无法将父 ( ) 元素设置为 nil无论如何。

因此,也许最接近您想要的是使值可为空并将其呈现为 XmlElement(注意添加的问号):

private System.DateTime? valueField;

[System.Xml.Serialization.XmlElement(DataType = "date", IsNullable = true)]
public System.DateTime? Value { get/set ...}

设置为空

DateOfDeath dod = new DateOfDeath();
dod.nilReason = NilReason.noValue;
dod.nilReasonSpecified = true;
dod.Value = null;

XmlSerializer serializer = new XmlSerializer(typeof(DateOfDeath));
serializer.Serialize(stream, dod);

给你:

<?xml version="1.0" encoding="utf-8"?>
<dateOfDeath xmlns:xsi="..." xmlns:xsd="..." nilReason="noValue">
<Value xsi:nil="true" />
</dateOfDeath>

这显然不是您想要的,但是除非有一种神奇的方法可以将外部类成员作为属性附加到空指针,或者反过来,使用您的类的另一个成员作为 nil 值指示符,否则没有使用给定的工具链实现这一目标的机会。

关于c# - C# 中具有属性的可空元素的 XML 序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36936661/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com