在 nil xml 元素上指定属性
Posted
技术标签:
【中文标题】在 nil xml 元素上指定属性【英文标题】:specify attributes on a nil xml element 【发布时间】:2015-02-17 17:48:21 【问题描述】:这是一个很长的...
我有一个 xsd,它指定了一个复杂类型,它可以有一个可空元素,但该元素有一个必需的属性。这是一个简化的例子:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified" >
<xs:element name="Test">
<xs:complexType>
<xs:sequence>
<xs:element name="NillableElementTest" type="MyNillableElement" nillable="true" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="MyNillableElement">
<xs:sequence>
<xs:element name="id" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="RequredAttribute" use="required"/>
</xs:complexType>
</xs:schema>
基于上述架构,以下xml文档是有效的:
<Test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<NillableElementTest RequredAttribute="test" xsi:nil="true"></NillableElementTest>
</Test>
<Test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
</Test>
如果有一个没有 RequredAttribute 值的 NillableElementTest 元素是无效的:
<Test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<NillableElementTest xsi:nil="true"></NillableElementTest>
</Test>
我有一个代表上述模式的对象模型(类)。对象模型是由 .net 框架工具从 xsd 生成的。
如果我将 xml 反序列化为对象实例,只要 xml 指定 xsi:nil="true",NillableTestElement 属性始终为 null。通常这对我来说是有意义的,除了 NillableTestElement 属性不会代表 xml 中指定的 RequredAttribute 值。
xml schema primer 声明 nil 机制仅适用于元素值,而不适用于属性值。 xsi:nil="true" 的元素可能没有任何元素内容,但仍可能带有属性。
元素为 nil 而属性不为 nil 的场景似乎无法用生成的对象模型来表示。
所以现在如果我获取对象实例并尝试将其序列化为 xml,如果针对架构进行验证,我将得到无效的 xml,因为该对象将 MyNillableElement 序列化为:
<Test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<NillableElementTest xsi:nil="true"></NillableElementTest>
</Test>
...显然 xsd 声明 NillableELementTest 元素必须具有 RequredAttribute 属性。
这是我的问题:
那么如何(或者有可能)指定元素为空,同时在对象中指定属性值以便正确序列化?
【问题讨论】:
【参考方案1】:你在你的问题中说得最好:
元素为 nil 但属性不是的场景不会 似乎可以用生成的对象模型来表示。
在 C# 中,子元素 NillableElementTest
表示为对另一个对象的引用。如果元素为 nil 值,则将其解释为 null 引用,如您所知,它不可能携带其他属性的值。
在 XML 中,正如您所展示的,可能有一个元素为 nil-valued,但仍带有其他属性。这种范式不能很好地转移到对象上。
允许MyNillableElement
包含0 个或多个id
实例而不是至少1 个实例对您有用吗?这样,您就有可能拥有一个空的,它能够携带其他属性,而不是 null/nil。
【讨论】:
不幸的是,xml 架构是一个无法更改的规范。 这可以通过对象实现。例如,对于包含可选属性的元素,相应的对象既包含属性的属性,也包含相应的“指定”属性,以指示是否提供了该属性。为什么该对象没有“IsNil”属性,以便您可以实例化该属性并提供属性,但也表明它在 xml 中被指定为 nil。 默认序列化程序将xsi:nil = true
视为空对象引用。见这里:msdn.microsoft.com/en-us/library/ybce7f69(v=vs.85).aspx
您可能必须构建自己的类来实现 IXmlSerializable。见这里:msdn.microsoft.com/en-us/library/…【参考方案2】:
我遇到了类似的问题。 也许我的解决方案不会在所有情况下都解决问题,但我希望它对某人有所帮助。
我的解决方案是修改对象模型中NillableElementTest
属性的XmlElement
属性。
我有属性[XmlElement(IsNullable = true)]
的属性。在我将属性更改为[XmlElement]
后,当属性值为null时,该属性不再添加到生成的xml中。
基于架构生成的 xml 仍然有效 (minOccurs="0"
)。
【讨论】:
以上是关于在 nil xml 元素上指定属性的主要内容,如果未能解决你的问题,请参考以下文章
如何指定一个元素以具有一个属性,该属性说明它在 XML 模式中包含多少个子元素?