How to make a schema for an unordered list where some occur once, some many times

自作多情 提交于 2019-12-29 08:06:45

问题


This is a similar question to How to create a schema for an unordered list of XML nodes, with occurrence constraints, but actually slightly simpler. However I am having great trouble understanding the logic behind sequences and choices (and especially when they are nested into sequences of choices or choices of sequences), and although I've studied it for a long time I can't understand how the example above works.

What I need is schema for a list of nodes, ChildA and ChildB, whereby ChildA can occur 0-n times, but ChildB only 0-1 times. (Actually I need several nodes of each type, but if I can do it for ChildA and ChildB, extending it to ChildX etc. and ChildY etc. should be simple). There should be no order constraint. I'd appreciate any help. Any links that explain schema indicators in depth would also be helpful.


回答1:


This would be the simplest solution that quickly came to my mind. The key point here is to use another sequence inside the "main" sequence. The schema is kept deterministic by setting the inner sequence to start with <ChildB> and <ChildB> is kept optional by setting the cardinality of that sequence to 0-1.

This is an XMLSchema 1.0 solution.

<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <!-- Schema for elements ChildA and ChildB
      The requirements are as follows:
          * ChildA and ChildB may occur in any order.
          * ChildA is optional and may occur multiple times.
          * ChildB is optional and may occur once only.
  -->

  <xs:element name="root">
    <xs:complexType>
      <xs:sequence>
        <xs:element maxOccurs="unbounded" name="AB-container" type="AB-type" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:complexType name="AB-type">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="unbounded" name="ChildA" type="xs:string" />
      <xs:sequence minOccurs="0">
        <xs:element name="ChildB" type="xs:string" />
        <xs:element minOccurs="0" maxOccurs="unbounded" name="ChildA" type="xs:string" />
      </xs:sequence>
    </xs:sequence>
  </xs:complexType>

</xs:schema>



回答2:


Short answer is that it cannot be done in XSD 1.0; in XSD 1.1 you could use an xsd:all compositor (since the restriction from XSD 1.0 of having only maxOccurs = 1 has been removed) - however, XSD 1.1 's problems are that i) it is only available freely as a beta Xerces version - as far as I know, and at this time; ii) there's a SAXON edition supporting it, last time I saw references to it you would have to pay for that and iii) you would have a hard time interoperating with other folks since most of them are still on XSD 1.0.

IF you can use Schematron - definitely more accessible than XSD 1.1 since it is just XSLT 1.0/2.0, then it should be easy to code it such that the count of particular element particles meets a specified criteria; it would augment an XSD where the compositor would be a repeating xsd:choice, where the choice options are elements from your allowed set.

Some people try to explain XSD compositors by making a parallel with constructs from regular expressions. If you are familiar with that, then xsd:all in XSD 1.0 is similar to square brackets (much simpler though, no concept of a range or negation), xsd:choice is like | (pipe, alternation) and xsd:sequence is the rest (where it matters the order in which you write your stuff).

I see that other people on SO recommend W3Schools. I didn't try it myself, hence me passing this on to you with the disclaimer.




回答3:


@Dave is adding some dumb attribute to ChildB okay? Since your requirement on childB is 0-1 we can achieve the desired solution by adding a fixed attribute to childB and enforcing unique constraint on the attribute.

<complexType name="childAType">
 <simpleContent>
   <extension base="string"></extension>
 </simpleContent>
</complexType>


<complexType name="childBType">
 <simpleContent>
   <extension base="string">
     <attribute name="value" type="string" fixed="123"></attribute>
   </extension>
 </simpleContent>
</complexType>


<element name="root">
 <complexType>
   <choice minOccurs="0" maxOccurs="unbounded">
        <element name="childA" type="tns:childAType" minOccurs="0" maxOccurs="unbounded"></element>
        <element name="childB" type="tns:childBType" minOccurs="0" maxOccurs="unbounded"></element>
   </choice>
 </complexType>
 <unique name="childB.max.once">
   <selector xpath="./tns:childB"></selector>
   <field xpath="@value"></field>
 </unique>
</element>

Below is one of valid XML (order of B doesn't matter or B can be excluded)

<tns:root xmlns:tns=" ">
 <tns:childA></tns:childA>
 <tns:childB></tns:childB>
 <tns:childA></tns:childA>
 <tns:childA></tns:childA>
</tns:root>

However the below one is invalid

<tns:root xmlns:tns=" ">
 <tns:childB></tns:childB>
 <tns:childA></tns:childA>
 <tns:childB></tns:childB>
 <tns:childA></tns:childA>
 <tns:childA></tns:childA>
</tns:root>


来源:https://stackoverflow.com/questions/14321579/how-to-make-a-schema-for-an-unordered-list-where-some-occur-once-some-many-time

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!