【问题标题】:The same element name with different attributes具有不同属性的相同元素名称
【发布时间】:2014-07-16 15:57:44
【问题描述】:

在 XSD 中是否有可能具有不同属性的相同元素?

我尝试过这样的事情:

<xsd:complexType name="Type1">
    <xsd:attribute name="id" type="xsd:integer" use="required"/>
    <xsd:attribute name="attribute1" type="xsd:integer" use="required"/>
</xsd:complexType>

<xsd:complexType name="Type2">
    <xsd:attribute name="id" type="xsd:integer" use="required"/>
    <xsd:attribute name="attribute2" type="xsd:string" use="optional"/>
</xsd:complexType>

<xsd:element name="address">
    <xsd:complexType>
        <xsd:choice>
            <xsd:choice>
                <xsd:element name="elementName" type="Type1"/>
                <xsd:element name="elementName" type="Type2"/>
            </xsd:choice>
        </xsd:choice>
    </xsd:complexType>
</xsd:element>

怎么做? address 元素应该是 Type1Type2。每种类型都有不同的属性。

【问题讨论】:

  • 那么,您的实际要求是elementName一个一个attribute1 或一个attribute2 但不是两者都有?
  • 实际上,重新检查了您的模式(没有注意到可选的) - 任何 XML 处理器如何区分产生“type2”elementName 没有属性和“type1”的东西" elementName 其中attribute1 是强制性的——作为人类,我不知道如何识别这种情况。您希望计算机如何执行验证?
  • 计算机可以检查第一个选项是否适合或第二个。检查是type1还是type2。

标签: xml xsd


【解决方案1】:

不,那是行不通的

3.8.6.3 Element Declarations Consistent in the specs

用我的话来说:同一组中的两个元素必须具有相同的结构,XSD 中没有签名重载。

您必须使用元素名称(或命名空间)来区分这两种变体。如果您可能希望在 XML 语言中使用绑定框架(JAXB 或 XmlSerializer),这也是一个好主意。这些很可能无法处理您的构造。

编辑:这里是我们讨论之后的继承示例:

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
    <xsd:complexType name="Base" abstract="true">
        <xsd:attribute name="id" type="xsd:integer" use="required"/>
    </xsd:complexType>
    <xsd:complexType name="Type1">
        <xsd:complexContent>
            <xsd:extension base="Base">
                <xsd:attribute name="attribute1" type="xsd:integer" use="required"/>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <xsd:complexType name="Type2">
        <xsd:complexContent>
            <xsd:extension base="Base">
                <xsd:attribute name="attribute2" type="xsd:string" use="optional"/>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <xsd:element name="address" >
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="elementName" type="Base" maxOccurs="unbounded"/>
            </xsd:sequence>            
        </xsd:complexType>
    </xsd:element>
</xsd:schema>


<?xml version="1.0" encoding="UTF-8"?>
<address xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Untitled1.xsd">
    <elementName id="1" attribute1="123" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Type1"/>
    <elementName id="1" attribute2="123" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Type2"/>
</address>

这或多或少符合您的描述,但需要您添加 xxi:type 属性。我没有看到好处。

【讨论】:

  • 继承在这里有帮助吗?一个基本的公共元素,然后将其扩展为 2 种类型。
  • 是的,这基本上就是我使用不同元素名称的意思。使用常见复杂类型的两个不同扩展将“记录”意图,但不会阻止(正确实现的)模式处理器拒绝具有相同名称和不同结构的两个元素。
  • 您也许可以将 xsi:type 属性与继承(抽象类型)一起使用。但这基本上与使用不同的名称非常相似,我也没有看到优势。
  • 所以不可能按照我的意愿去做?我尝试了继承,它通过了验证,但一切都被标记为错误。
  • 你能发布你所做的吗?如果您为 Type1 和 Type2 声明一个通用的抽象基类型并使用此基类型声明一个新元素来替换您的 xdd:choice,那么您仍然必须以某种方式让架构处理器识别其中可以出现的具体类型。
【解决方案2】:
<xsd:complexType name="Base">
    <xsd:attribute name="id" type="xsd:integer" use="required"/>
</xsd:complexType>

<xsd:complexType name="Type1">
    <xsd:complexContent>
        <xsd:extension base="Base">
            <xsd:attribute name="attribute1" type="xsd:integer" use="required"/>
        </xsd:extension>
    </xsd:complexContent>
</xsd:complexType>

<xsd:complexType name="Type2">
    <xsd:complexContent>
        <xsd:extension base="Base">
            <xsd:attribute name="attribute2" type="xsd:string" use="optional"/>
        </xsd:extension>
    </xsd:complexContent>
</xsd:complexType>

<xsd:element name="address">
    <xsd:complexType>
        <xsd:choice>
            <xsd:choice>
                <xsd:element name="elementName" xml:base="Base"/>
            </xsd:choice>
        </xsd:choice>
    </xsd:complexType>
</xsd:element>

通过验证的代码。

【讨论】:

    【解决方案3】:

    “元素声明一致”约束(在 XSD 1.0 和 1.1 中都存在)表示如果两个同级元素具有相同的名称,那么它们必须具有相同的类型。所以简单的答案是否定的。但是,在 XSD 1.1 中,您可以通过为两个元素提供相同类型(允许您的任一属性集的类型)然后使用断言定义附加约束(在父元素上)来处理它。

    【讨论】:

    • 怎么做?你能举个例子吗?
    • 例如,您可以使用type="xs:anyType" 定义子元素,并在父元素上有一个断言,例如xs:assert test="childElem[1]/@att1 and not(childElem[1]/@att2 and childElem[2]/@att2 and not(childElem[2]/@att1)"
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多