【问题标题】:Middle way between XSD all and XSD sequenceXSD all 和 XSD 序列之间的中间方式
【发布时间】:2009-05-08 09:52:19
【问题描述】:

我正在使用 XSD 定义用户元素。对于此示例,用户具有姓名、电子邮件和一个或多个国籍。我试过了:

<xs:all>
  <xs:element name="name" blabla />
  <xs:element name="email" blabla />
  <xs:element name="nationality" minOccurs="1" maxOccurs="unbounded" />
</xs:all>

但是,这是非法的。显然,“全部”中的元素只能出现一次(或根本不出现)。 我可以通过将 All 更改为 Sequence 来解决这个问题,但是人们必须按照确切的顺序输入属性,而我实际上并不关心。

有没有这两者的组合?不是根据http://www.w3schools.com/Schema/schema_complex_indicators.asp,但可能它被隐藏了(或者我没有经验的眼睛看不到它)。

凭直觉,我也试过:

<xs:all>
  <xs:element name="name" blabla />
  <xs:element name="email" blabla />
  <xs:sequence>
    <xs:element name="nationality" minOccurs="1" maxOccurs="unbounded" />
  </xs:sequence>
</xs:all>

但不幸的是,这是无效的。


这是当前的、真实的 XSD:

  <!-- user -->
  <xs:complexType name="user">
    <xs:sequence>
      <xs:element name="firstname" type="xs:string" minOccurs="1" maxOccurs="1" />
      <xs:element name="appendix" type="xs:string" minOccurs="0" maxOccurs="1" />
      <xs:element name="lastname" type="xs:string" minOccurs="1" maxOccurs="1" />
      <xs:element name="address" type="xs:string" minOccurs="1" maxOccurs="1" />
      <xs:element name="zipcode" type="xs:string" minOccurs="1" maxOccurs="1" />
      <xs:element name="city" type="xs:string" minOccurs="1" maxOccurs="1"/>
      <xs:element name="username" type="xs:string" minOccurs="1" maxOccurs="1"/>
      <xs:element name="email" type="xs:string" minOccurs="1" maxOccurs="1"/>
      <xs:element name="country" type="country" minOccurs="1" maxOccurs="1"/>
      <xs:element name="nationality" type="xs:string" minOccurs="1" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>

【问题讨论】:

    标签: xml xsd


    【解决方案1】:

    你能不能把你的“国籍”东西变成它自己的 complexType,然后在你的 xs:all 中使用这个新的复杂类型?

    <xs:complexType name="NationalityType">
      <xs:sequence>   
        <xs:element name="nationality" minOccurs="1" maxOccurs="unbounded" />
      </xs:sequence>
    </xs:complexType>
    
    <xs:all>
      <xs:element name="name" blabla />
      <xs:element name="email" blabla />
      <xs:element name="nationalities" type="NationalityType" />
    </xs:all>
    

    我手头没有任何东西可以测试这个,所以这真的只是我的想法.....试试吧!

    编辑:现在对其进行了测试 - 它可以工作,唯一需要付出的小代价是您的 XML 必须看起来像这样:

    <....>
      <email>......</email>
      <nationalities>
        <nationality>ABC</nationality>
        <nationality>CDE</nationality>
      </nationalities>
      <name>.....</name>
    </.....>
    

    因此,您将获得一个额外的节点,该节点将包含&lt;nationality&gt; 项目的任意长列表。

    马克

    【讨论】:

    • 这个答案是唯一正确的。您需要的是一系列国籍。所有其他方法都只是破坏 XML 原则的 hack。
    【解决方案2】:

    刚刚遇到了一个类似的问题(我想以任意顺序排列任意数量的每个元素)并通过一系列选择来解决它。使用上面的例子:

    <?xml version='1.0' encoding='UTF-8'?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
      <xs:element name='user'>
        <xs:complexType>
          <xs:sequence minOccurs="0" maxOccurs="unbounded">
            <xs:choice>
              <xs:element name="name" type="xs:string" />
              <xs:element name="email" type="xs:string" />
              <xs:element name="nationality" />
            </xs:choice>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:schema>
    

    这允许您以任意顺序拥有任意数量的姓名、电子邮件和国籍。

    【讨论】:

    • 但是这将允许 内有多个 元素?
    【解决方案3】:

    我认为您正在寻找的内容会违背 XML 的意图。有这样一个有效的 XML 片段似乎很奇怪:

    <user>
      <nationality/>
      <name/>
      <nationality/>
      <email/>
      <nationality/>
    </user>
    

    听起来你在要求类似 marc_s 提议的东西:

    <user>
      <name/>
      <email/>
      <nationality/>
      <nationality/>
      <nationality/>
    <user>
    

    需要推入:

    <user>
      <name/>
      <email/>
      <nationalities>
         <nationality/>
         <nationality/>
         <nationality/>
      </nationalities>
    <user>
    

    【讨论】:

      【解决方案4】:

      您的代码应该在 XSD 1.1 中有效。对于 XSD 1.0,您必须找到一种解决方法。

      【讨论】:

      • 如何使用、制定、选择加入、创建、隐藏、迁移、实例化、查找或执行 XSD 1.1?
      • 您能否列举一下 XSD 1.1 和 XSD 1.0 之间的区别,使其在 1.1 中有效而在 1.0 中无效?
      • 在 1.1 规范中,我没有看到任何使 OP 的 XML 非法的约束。可悲的是,我找不到可以比较的 1.0 规范。我的猜测是,您必须检查将解析 XML/XSD 的库上的版本,以了解您是否需要以下任何技巧。
      • 好的,找到了,在这里引用太长了,但请参阅w3.org/TR/xmlschema-1/#Model_Group_details 下的(全部)与w3.org/TR/xmlschema11-1/#Model_Group_details 下的更短且限制更少的(全部)
      • @Ian Boyd - 1.1 是向后兼容的,尽管 1.0 解析器将使用 1.1 模式报告误报。所以我认为这是 XML lib/validator 作者更新到 1.1 的情况。这并没有像我希望的那样迅速发生。截至 2014 年 2 月,甚至 MarkLogic 都缺乏支持。
      【解决方案5】:

      对于 XSD 1.0,leppie 的建议有效。

      XSD

      <?xml version='1.0' encoding='UTF-8'?>
      <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
        <xs:element name='user'>
          <xs:complexType>
            <xs:sequence>
              <xs:element name="name" type="xs:string" />
              <xs:element name="email" type="xs:string" />
              <xs:choice minOccurs='0' maxOccurs='unbounded'>
                <xs:element name="nationality" />
              </xs:choice>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:schema>
      

      根据架构验证的示例 XML 文档

      <user>
        <name>Name</name>
        <email>name@name.com</email>
        <nationality>Italian</nationality>
        <nationality>Japanese</nationality>
        <nationality>Alien</nationality>
      </user>
      

      和验证,例如使用 xmllint

      xmllint --noout --schema test.xsd test.xml
      test.xml validate
      

      【讨论】:

      • 在您提供的示例中,“选择”中不需要。只要您在其中使用“序列”元素,它就可以具有 maxOccurs="unbounded"。但是序列强加了内部元素的顺序 - 这是最初问题中的问题。
      • 积极的一面是,这个答案确实表明模型组元素allsequencechoice 可以嵌套。同样,至少在 1.1 中,可以定义和引用组,请参阅w3.org/TR/xmlschema11-1/#cModel_Group_Definitions,这将避免像 marc_s 答案那样添加新的“容器”元素。
      【解决方案6】:

      或者,既然“USER”将设置多个子元素,为什么不将其设置为复杂类型呢?这样的事情应该可以工作。

      <xs:complexType>
        <xs:sequence>
          <xs:element name="Name" type="xs:string" />
          <xs:element name="Password" type="xs:string" />
          <xs:element minOccurs="1" maxOccurs="unbounded" name="Nationality" type="xs:string" />
        </xs:sequence>
      </xs:complexType>
      

      【讨论】:

      • 已经是复杂类型了。我已经在问题中添加了真正的 XSD,所以你也可以看到它:)
      【解决方案7】:

      xs:choice 不会工作?如果没有,只需将其包装在一个序列中,反之亦然。

      【讨论】:

      • 嗯?那会有什么帮助?请举个例子。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-18
      • 1970-01-01
      • 2011-01-24
      相关资源
      最近更新 更多