【问题标题】:Is it possible to define an attribute of an XML element to be required only if another element's attribute is set to a particular value?是否可以仅在另一个元素的属性设置为特定值时才定义需要的 XML 元素的属性?
【发布时间】:2014-07-31 19:58:03
【问题描述】:

我想问一下这是否可行,如果可以,如何实现:

例如,如果我在 XML 模式定义中有一个带有 complexType 的元素定义,如下所示:

<xsd:element name="tag" type="tag"/>
<xs:complexType name="tag">
    <xs:choice maxOccurs="unbounded">
        <xs:element name="subtag" type="subtag"/>
        <xs:element name="another_subtag" type="another_subtag"/>
        <xs:element name="another_subtag_2" type="another_subtag_2"/>
    </xs:choice>
    <xs:attribute name="type" type="attr_type"/>
    <xs:attribute name="an_attr" type="an_attr"/>
    <xs:attribute name="another_attr" type="another_attr"/>
</xs:complexType name="attr_type">
    <xsd:restriction base="xsd:string">
         <xsd:enumeration value="type_1"/>
         <xsd:enumeration value="type_2"/>
         <xsd:enumeration value="type_3"/>
    </xsd:restriction>
<xsd:simpleType/>

1) 如果标签元素的属性“attr_type”设置为“type_2”,是否可以将标签元素的属性“an_attr”设为必需?

还有一个问题: 2)是否有可能使 complexType 'tag' 包含 不同 子元素再次基于例如关于“attr_type”的值?例如:

<tag attr_type="type_1">

只有这个孩子:

<xs:element name="subtag" type="subtag"/>

对于:

<tag attr_type="type_2">

只有孩子:

 <xs:element name="another_subtag" type="another_subtag"/>
OR
 <xs:element name="another_subtag_2" type="another_subtag_2"/>

?

如果可能,我该如何实现?

感谢关注!

编辑:正如我在这里看到的 -> https://blogs.oracle.com/rammenon/entry/xml_schema_11_what_you_need_to 在示例编号 22 中(在条件类型分配中),是否可以以这种方式完成?

<!--inline alternative type definitions --> 
<element name="TimeTravel" type="TravelType"> 
      <alternative test="@direction='Future'"> 
          <complexType> 
              <complexContent> 
              <restriction base="TravelType" 
                         .... 
<!--        some past travel related elements go here --> 
            </complexType> 
       </alternative> 
      <alternative test="@direction='Past'"> 
          <complexType> 
              <complexContent> 
              <restriction base="TravelType" 
                         .... 
   <!--        some future travel related elements go here --> 
            </complexType> 
       </alternative> 
  </element> 
                          OR 
<!--Named alternative type definitions --> 
<element name="TimeTravel" type="TravelType"> 
   <alternative test="@direction='Future' type="FutureTravelType"/> 
   <alternative test="@direction='Past' type="PastTravelType"/> 
</element>

据我了解,TimeTravel 元素可以根据方向属性值具有不同的复杂类型,对吗?但它说必须使用 XSD 1.1。我可以在我的 XML Schema 中使用这个规则吗?

【问题讨论】:

  • 所以我想我的生活很复杂,对吗?
  • 也许但不要难过。从我在上一条评论中发布的链接可以看出,我们中的许多人都希望 XML Schema 能够以这种方式验证元素和属性。
  • 是的,你是对的(如果我理解正确的话)。请记住,确定所有这些的属性(示例中的“方向”属性)必须是同一元素 TimeTravel 的属性。
  • 一如既往地保留它。不需要用版本标记它。

标签: xml xsd xsd-validation


【解决方案1】:

让我们再试一次,因为我的答案有争议,最好再详细一点。编辑我的原始答案会使后续的 cmets 难以理解,只会增加混乱。

问题1:是否可以仅当标签元素的属性'attr_type'设置为'type_2'时才需要标签元素的属性'an_attr'?

答案 1:是的。您可以这样做(经过测试;从原始版本修改以避免引用不相关和未定义的类型):

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="tag" type="tagType">
      <xs:alternative test="@attr_type='type_2'" type="tagTypeWithMandatoryAttr"/>
    </xs:element>

    <xs:complexType name="tagType">
        <xs:choice maxOccurs="unbounded">
            <xs:element name="subtag" type="xs:anyType"/>
            <xs:element name="another_subtag" type="xs:anyType"/>
            <xs:element name="another_subtag_2" type="xs:anyType"/>
        </xs:choice>
        <xs:attribute name="type" type="xs:string"/>
        <xs:attribute name="an_attr" type="xs:string"/>
        <xs:attribute name="another_attr" type="xs:string"/>
    </xs:complexType>

    <xs:complexType name="tagTypeWithMandatoryAttr">
     <xs:complexContent>
      <xs:restriction base="tagType">
          <xs:choice maxOccurs="unbounded">
            <xs:element name="subtag" type="xs:anyType"/>
            <xs:element name="another_subtag" type="xs:anyType"/>
            <xs:element name="another_subtag_2" type="xs:anyType"/>
          </xs:choice>
          <xs:attribute name="type" type="xs:string"/>
          <xs:attribute name="an_attr" type="xs:string" use="required"/>
          <xs:attribute name="another_attr" type="xs:string"/>
      </xs:restriction>
     </xs:complexContent>
    </xs:complexType>
</xs:schema>

问题 2:

是否有可能使 complexType 'tag' 再次包含不同的子元素,例如关于“attr_type”的值?

答案 2:

是的,例如(类似测试):

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="tag" type="xs:anyType">
      <xs:alternative test="@attr_type='type_2'" type="tagType1"/>
      <xs:alternative type="tagType2"/>
    </xs:element>

    <xs:complexType name="tagType1">
        <xs:choice maxOccurs="unbounded">
            <xs:element name="subtag" type="xs:anyType"/>
            <xs:element name="another_subtag" type="xs:anyType"/>
            <xs:element name="another_subtag_2" type="xs:anyType"/>
        </xs:choice> 
    </xs:complexType>

    <xs:complexType name="tagType2">
        <xs:choice maxOccurs="unbounded">
            <xs:element name="subtag" type="xs:anyType"/>
            <xs:element name="another_subtag" type="xs:anyType"/>
            <xs:element name="another_subtag_2" type="xs:anyType"/>
        </xs:choice> 
    </xs:complexType>
</xs:schema>

问题 0:是否可以定义一个 XML 元素 (E) 的属性仅在另一个元素 (F) 的属性设置为特定值时才需要?

答案 0:取决于两个元素 E 和 F 的关系。如果 F 是 E 的祖先,则可以在 F 的声明中使用条件类型赋值来完成。如果 E 和 F 是兄弟姐妹或更多远程相关,则不能使用条件类型赋值来完成,但可以使用附加到 E 和 F 的共同祖先的断言来完成。

【讨论】:

  • 就像我说的,你把条件类型赋值给祖先元素F。它允许引用它自己的属性。
  • @MichaelKay 您是如何测试 XSD 的有效性的?您知道在线 XSD 1.1 验证器吗?
  • @MichaelKay 抱歉,我还有一个问题。在您的答案 1 示例中,您展示了标记元素如何根据 attr_type 值的值更改其类型,从而包含不同的元素,但是您在哪里定义 attr_type属性???例如。如果 attr_type 属性有一个带限制和枚举的 simpleType,你把它放在哪里?
  • 测试:作为 Saxon XSD 1.1 处理器的开发人员,我在寻找处理器进行测试时没有任何问题!声明 attr_type:它可以像任何其他属性一样声明。我真的应该包括声明,抱歉。
  • 感谢您的回复,哇!我不知道!那么你能建议我使用什么样的工具呢? 'attr_type' 属性应该放在哪里?在 'tagType' complexType 内部还是在 'tagTypeWithMandatoryAttr' complexType 内部或两者内部?对不起,也许我是在用这个问题打扰你,但我不是故意的,我只是想学习! :)
【解决方案2】:

在 XSD 1.1 中可以使用“条件类型分配”的新特性。这允许您将元素的类型定义为其属性值的函数。

XSD 1.1 在 Altova、Saxon 和 Xerces 中实现。

【讨论】:

  • 感谢您的回复,能否请您发送处理此参数的参考或链接?
  • 我找到了这个 -> blogs.oracle.com/rammenon/entry/… 还没有找到如何实现它的示例...
  • 这里有一些很好的例子:datypic.com/books/defxmlschema/chapter14.html。有关示例的说明,请购买此书!
  • 因为这是 XSD 1.1,我是否应该在我的 .xsd 文件中添加一些内容以使用这种功能?还是 xml 版本仍然是 1.0 而 xsd:schema 始终是具有其 targetNamespace 和其他属性的根元素?
  • 您需要做两件事:更改架构以调用条件类型分配(它将具有 xs:alternative 元素),并使用 XSD 1.1 处理器运行它。您还可以使用 vc:version 属性表明该架构需要 XSD 1.1,但这是可选的并且主要是记录性的。
【解决方案3】:

不,因为条件类型分配(在另一个答案中提到)仅将类型分配给元素。因此,名称,条件类型分配。此外,当使用条件类型赋值时,元素的类型由它自己的属性决定,而不是由其他元素的属性决定。

即使使用带有条件类型分配的 XPATH 表达式,您也只能访问正在验证的元素的属性。它无法访问其父级或祖先,甚至无法像断言一样访问其子级或后代。

[编辑] 发布的主要问题是,是否可以根据另一个元素的属性要求第一个属性,答案是否定的。

这需要比 XML Schema 1.1 更高级别的验证。也许是 Schematron ???我不知道。有时答案不是你想听到的。

参考:Priscilla Walmsley 撰写的 Definitive XML Schema,第 2 版,第 378-379 页。

a great post 总结了无数次关于 XML 验证的此类问题。 Schema 1.1 中的新增功能范围非常有限。

【讨论】:

  • 注意* 以“否”开头的答案会使您获得赞成票的机会降低 65%(注意:互联网上发布的 87% 的统计数据是当场制作的)。
  • 我不确定哪个问题的答案是“否”,但答案对我来说似乎是错误的。要么,要么我误解了这个问题。条件类型分配允许您根据元素的属性值为其分配不同的类型(即验证规则)。不同的类型在他们允许的属性和他们允许的孩子(或其他后代)方面可能有所不同,在我的阅读中,这意味着答案是肯定的。所以我不赞成这个答案。
  • @JasonEnochs:你知道迈克尔·凯是谁吗?如果您还不知道,请查看他的个人资料。如果您确实已经知道,那么祝您好运。
  • @JohnSaunders 是的,我阅读了他的个人资料,但我不会根据事实改变我的观点。凭证并不能使您正确。任何花时间阅读问题并为自己研究条件类型作业的人都会确定,虽然 Kay 的答案实际上是正确的,但不适用于提出的问题。问题的答案是“否”。
  • 我说“我不确定哪个问题被'否'回答”,我认为这可以解释问题;我在回答你的另一个问题。这里有三个问题;在我最新的回答中,我试图回答所有三个问题。顺便说一句,称人们为混蛋同样令人反感,无论他们是成熟的专家还是初学者。
猜你喜欢
  • 2022-11-28
  • 1970-01-01
  • 1970-01-01
  • 2017-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多