【问题标题】:XML Schema - child elements dependent on existence of optional attributeXML Schema - 子元素依赖于可选属性的存在
【发布时间】:2010-01-15 08:36:32
【问题描述】:

是否可以在 XSD 中定义如下场景:

  1. 父元素有一个属性

    是可选的。

  2. 如果属性不是

    present in XML, at least one child
    
    element must exists.
    
  3. 如果

    attribute is present, there can be
    
    zero or more child elements.
    

例子:

有效

<parent externel-source="some_name" />



<parent externel-source="some_name">

  <child>some value</child>

</parent>



<parent>

  <child> some value</child>

</parent>

无效

<parent />

【问题讨论】:

    标签: xml validation xsd


    【解决方案1】:

    不..原因是:在您的情况下,您试图根据其他一些标签/属性的值来验证元素/标签的存在..(XSD基本上是一组声明)需要多个声明相同的元素..
    XSD 中不允许对同一元素进行多次声明 .. :-(
    查看 stackOverFlow 成员发布的similar problem (click here)

    【讨论】:

      【解决方案2】:

      很抱歉复活这条消息,但我想我可以添加一些关于“为什么”的内容。 W3C XML Schema 要求它的所有序列都是完全确定的。出于性能/简单性的原因,它不是为向前看或向后看而设计的,仅适用于当前元素。我也相信这是从 SGML 继承的。

      您想做的事情需要这样的功能。你可能想看看 Schematron;它支持你想要的。

      【讨论】:

        【解决方案3】:

        是的,绝对可以,使用 xsi:type (这可能不是你想要的!)。 比如下面的xsd;

        <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <xs:element name="data">
            <xs:complexType>
                <xs:choice>
                    <xs:element ref="elemParent" minOccurs="1"  maxOccurs="unbounded"/> 
                </xs:choice>
            </xs:complexType>
        </xs:element>
        <xs:element name="elemParent" type="ctBase"></xs:element>
        <xs:complexType name="ctNoAttChildReq">
            <xs:complexContent>
                <xs:extension base="ctBase">
                    <xs:sequence>
                        <xs:element name="elemKid" type="xs:string"></xs:element>
                        <xs:element name="elemKidAdditional" type="xs:string" minOccurs="0"></xs:element>
                    </xs:sequence>              
                </xs:extension>
            </xs:complexContent>    
        </xs:complexType>
        <xs:complexType name="ctAttNoChild">
            <xs:complexContent>
                <xs:extension base="ctBase">
                    <xs:attribute name="attReq" use="required"/>
                </xs:extension>
            </xs:complexContent>        
        </xs:complexType>       
        <xs:complexType name="ctBase" abstract="true">
            <xs:sequence/>
        </xs:complexType>       
        

        您会得到一个实例,该实例具有一个属性或一个或多个孩子,但您必须在实例中具有 xsi:type,这可能是也可能不是显示停止器。

        <data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="file:///C:/Xsds/StackOverflow_2070316_WIP.xsd">
        <elemParent  attReq="Yo!" xsi:type="ctAttNoChild"/>
        <elemParent xsi:type="ctNoAttChildReq">
            <elemKid>Adam</elemKid>
        </elemParent>
        <elemParent xsi:type="ctNoAttChildReq">
            <elemKid>Eve</elemKid>
            <elemKidAdditional>Sid</elemKidAdditional>
        </elemParent>   
        

        【讨论】:

          【解决方案4】:

          不,我认为不是。

          【讨论】:

          • 这种类型的答案对我来说并不令人满意。你的说法背后的原因是什么?
          • XML 模式类型与您的 OO 编程类型非常相似。您可以创建复杂类型,并且可以限制元素类型和属性的元素顺序以及可以分配的值类型。这就是 xsd 可以为您做的所有事情。您想要的是跨越多个元素/属性的约束,这对于 xsd 来说是不可能的。您必须编写自己的代码来验证这一点。
          • 我也认为这是不可能的,那是一个很好的答案(如果它是正确的):-)
          • 非常感谢您的评论。现在我得到了图片:)
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-12-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-12-29
          相关资源
          最近更新 更多