2010-08-01 6 views
16

Étant donné une disposition XML comme celle-ci, j'essaie de créer un schéma XSD pour le valider.Comment créer un schéma pour une liste non ordonnée de nœuds XML, avec des contraintes d'occurrence

<RootNode> 
    <ChildA /> 
    <ChildC /> 
    <ChildB /> 
    <ChildB /> 
    <ChildA /> 
</RootNode> 

Les exigences sont les suivantes:

  • Childa, ChildB et ChildC peut se produire dans l'ordre. (<xs:sequence> inadapté)
  • ChildA est obligatoire mais peut apparaître plusieurs fois.
  • ChildB est optionnel et peut apparaître plusieurs fois.
  • ChildC est optionnel et peut apparaître une fois seulement.

La technique que je l'habitude d'utiliser pour créer une liste non ordonnée de nœuds est d'utiliser un <xs:choice maxOccurs="unbounded"> avec chaque nœud possible dans la liste, mais je suis incapable de créer la contrainte sur Childa et maxOccurs="1" contraint sur ChildC. (Le nombre d'occurrences du choix a préséance sur celles des éléments ici).

<xs:element name="RootNode"> 
    <xs:complexType> 
    <xs:choice minOccurs="1" maxOccurs="unbounded"> 
     <xs:element name="ChildA" minOccurs="1"/> 
     <xs:element name="ChildB" /> 
     <xs:element name="ChildC" maxOccurs="1"/> 
    </xs:choice> 
    </xs:complexType> 
</xs:element> 
+0

Je ne pense pas que le schéma XML actuel est capable de faire ce moment. Avez-vous vérifié dans d'autres systèmes de validation, comme RelaxNG (www.relaxng.org) peut-être? –

+0

Question connexe avec, au moment de l'écriture de ce, de meilleures réponses: https://stackoverflow.com/questions/2290360/xsd-how-to-allow-elements-in-any-order-any-number-of-times/12012599 – Flow

Répondre

10

Mise à jour: Dans XSD 1.1m certaines des contraintes qui pèsent sur all -groupes ont été levées. Voir les réponses here et here.

Pas simple mais cela semble faisable. La partie difficile ici est que les définitions de schéma doivent être déterministes. L'approche que j'ai utilisée était de visualiser le problème en dessinant un automate à états finis, puis d'écrire une expression régulière qui correspondait à cet automate. Ce n'est pas du tout aussi compliqué que cela puisse paraître. Pourtant, en utilisant un autre système de validation aurait probablement fourni une réponse plus simple.

J'ai fait quelques tests mais il est facile de passer à côté de cas spéciaux. S'il vous plaît commenter si vous repérez une erreur.

... et voici le code:

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" > 

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

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

    <xsd:complexType name="ABC"> 
     <xsd:sequence> 
      <xsd:element name="ChildB" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/> 
      <xsd:choice> 
       <xsd:sequence maxOccurs="1"> 
        <xsd:element name="ChildC" type="xsd:string"/> 
        <xsd:element name="ChildB" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/> 
        <xsd:element name="ChildA" type="xsd:string"/> 
        <xsd:sequence minOccurs="0" maxOccurs="unbounded"> 
         <xsd:element name="ChildA" type="xsd:string" minOccurs="0"/> 
         <xsd:element name="ChildB" type="xsd:string" minOccurs="0"/> 
        </xsd:sequence> 
       </xsd:sequence> 
       <xsd:sequence maxOccurs="1"> 
        <xsd:element name="ChildA" type="xsd:string" minOccurs="1"/> 
        <xsd:sequence minOccurs="0" maxOccurs="unbounded"> 
         <xsd:element name="ChildA" type="xsd:string" minOccurs="0"/> 
         <xsd:element name="ChildB" type="xsd:string" minOccurs="0"/> 
        </xsd:sequence> 
        <xsd:sequence minOccurs="0" maxOccurs="1"> 
         <xsd:element name="ChildC" type="xsd:string"/> 
         <xsd:sequence minOccurs="0" maxOccurs="unbounded"> 
          <xsd:element name="ChildA" type="xsd:string" minOccurs="0"/> 
          <xsd:element name="ChildB" type="xsd:string" minOccurs="0"/> 
         </xsd:sequence> 
        </xsd:sequence> 
       </xsd:sequence> 
      </xsd:choice> 
     </xsd:sequence> 
    </xsd:complexType> 

</xsd:schema> 
+5

"En combinant et en imbriquant les différents groupes fournis par XML Schema, et en définissant les valeurs de" minOccurs et maxOccurs ", il est possible de représenter n'importe quel modèle de contenu exprimable avec une DTD XML 1.0." Mais ils n'ont jamais dit que ce serait joli. – Will

+0

Jasso.C'est très intelligent. J'essaye de le modifier pour prévoir: aucun élément obligatoire (perdre ChildA); et beaucoup d'objets 0-ou-1-occurrence (comme ChildC). J'ai de vrais problèmes. J'ai posté la question à http://stackoverflow.com/questions/14321579/how-to-make-a-schema-for-an-unordered-list-where-some-occur-once-some-many-time . Vous semblez être un expert en la matière. Si vous pouviez regarder, je l'apprécierais. – Dave

+0

@Dave Merci d'avoir apprécié mes efforts. J'ai écrit une réponse à votre question. C'est arrivé un peu tard, parce que je ne m'étais pas connecté ici depuis quelques semaines. – jasso

1

Je viens de lire le relax-NG shortcut syntax.

Je devine que ce serait condensé à ce qui suit dans la syntaxe compacte de relax-ng:

head = element root { ChildA & ChildC? & ChildB* } 

qui ne manquera pas assez.

+0

Je suis désolé que ce soit faux ... puisque ChildA est au moins un, mais peut être plus ... – Texas

+0

'head = element root {ChildA + & ChildC? & ChildB *} 'peut-être? – Alan

2

Cela devrait faire ce que vous avez spécifié:

<xs:element name="RootNode"> 
    <xs:complexType>  
    <xs:all>  
     <xs:element name="ChildA" minOccurs="1"/>  
     <xs:element name="ChildB" />  
     <xs:element name="ChildC" minOccurs="0" maxOccurs="1"/>  
    </xs:all> 
    </xs:complexType> 
</xs:element> 
+0

Merci d'avoir essayé, mais cela ne correspond pas tout à fait. A et B peuvent apparaître plusieurs fois, mais l'élément '' spécifie que chaque élément peut apparaître zéro ou une seule fois. Ce serait bien s'il y avait une solution aussi simple que cela, mais je pense que la solution de jasso est probablement la meilleure que nous obtiendrons. –

+1

que se passe-t-il si vous définissez minOccurs = 1 et maxOccurs = 1 pour tous les éléments enfants? –

+0

Cette réponse est correcte (AFAIKT) si vous utilisez [XSD 1.1] (https://www.w3.org/TR/xmlschema11-1/). [G1.3 5.] (https://www.w3.org/TR/xmlschema11-1/#changes) explique la différence entre XSD 1.0 qui le permet. – Flow

Questions connexes