在 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 模式中包含多少个子元素?

C#如何读取XML中指定的节点值?

XMLDTDSchemadom4j解析

Mybatis XML 映射配置文件 -- 熟悉配置

在Struts.xml中的result元素指的是:指定动作类的动作方法执行完后的结果视图.

2020/2/4学习总结