web-dev-qa-db-fra.com

XSD - Comment autoriser les éléments dans n'importe quel ordre, plusieurs fois?

J'essaie de créer un fichier XSD et d'écrire la définition avec la condition suivante:

  • Autoriser l'élément enfant spécifié à apparaître autant de fois que nécessaire (0 à illimité)
  • Autoriser les éléments enfants à être dans n'importe quel ordre

J'ai regardé autour de moi et trouvé diverses solutions comme this :

<xs:element name="foo">
  <xsl:complexType>
    <xs:choice minOccurs="0" maxOccurs="unbounded">
      <xs:element name="child1" type="xs:int"/>
      <xs:element name="child2" type="xs:string"/>
    </xs:choice>
  </xs:complexType>
</xs:element>

Mais de ce que je comprends, xs: choix ne permet toujours que la sélection d’un seul élément. Par conséquent, si vous définissez MaxOccurs sur non limité comme ceci, cela ne devrait signifier que "n'importe lequel" des éléments enfants peut apparaître plusieurs fois. Est-ce exact?

Si la solution ci-dessus est incorrecte, comment puis-je obtenir ce que j'ai indiqué ci-dessus dans mon exigence?

[~ # ~] modifier [~ # ~] : Que se passe-t-il si l'exigence est la suivante?

  • L'élément child1 child2 peut apparaître autant de fois que vous le souhaitez (0 à illimité)
  • Les éléments doivent être dans n'importe quel ordre
  • Les éléments child3 et child4 doivent apparaître exactement une fois.

Par exemple, ce XML est valide:

<foo>
<child1> value </child1>
<child1> value </child1>
<child3> value </child3>
<child2> value </child2>
<child4> value </child4>
<child1> value </child1>
</foo>

mais ce n'est pas (child3 manquant)

<foo>
<child1> value </child1>
<child1> value </child1>
<child2> value </child2>
<child4> value </child4>
<child1> value </child1>
</foo>
101
jvtech

Dans le schéma que vous avez dans votre question, child1 ou child2 peut apparaître dans n'importe quel ordre, n'importe quel nombre de fois. Cela ressemble donc à ce que vous recherchez.

Edit: Si vous ne voulez qu'une seule d'entre elles à apparaître un nombre illimité de fois, les illimités devront plutôt aller sur les éléments:

Edit: Type fixe en XML.

Edit: O majuscule dans maxOccurs

<xs:element name="foo">
   <xs:complexType>
     <xs:choice maxOccurs="unbounded">
       <xs:element name="child1" type="xs:int" maxOccurs="unbounded"/>
       <xs:element name="child2" type="xs:string" maxOccurs="unbounded"/>
     </xs:choice>
   </xs:complexType>
</xs:element>
57
xcut

La formulation alternative de la question ajoutée dans une édition ultérieure semble encore sans réponse: comment spécifier que parmi les enfants d'un élément, il doit y en avoir un nommé child3, un nommé child4, et tout nombre nommé child1 ou child2, sans contrainte sur l’ordre dans lequel les enfants apparaissent.

Il s’agit d’un langage ordinaire directement définissable, et le modèle de contenu dont vous avez besoin est isomorphe à une expression régulière définissant l’ensemble des chaînes dans lesquelles les chiffres "3" et "4" apparaissent chacun une fois et les chiffres "1" et "2". 'se produire un nombre quelconque de fois. Si ce n'est pas évident de savoir écrire cela, il peut être utile de penser au type de machine à états finis que vous construiriez pour reconnaître un tel langage. Il aurait au moins quatre états distincts:

  • un état initial dans lequel ni '3' ni '4' n'ont été vus
  • un état intermédiaire dans lequel '3' a été vu mais pas '4'
  • un état intermédiaire dans lequel '4' a été vu mais pas '3'
  • un état final dans lequel les deux '3' et '4' ont été vus

Quel que soit l'état dans lequel se trouve l'automate, "1" et "2" peuvent être lus; ils ne changent pas l'état de la machine. Dans l'état initial, "3" ou "4" sera également accepté; dans les états intermédiaires, seuls "4" ou "3" sont acceptés; dans l'état final, ni '3' ni '4' ne sont acceptés. La structure de l'expression régulière est plus facile à comprendre si nous définissons d'abord un regex pour le sous-ensemble de notre langue dans lequel seuls les symboles "3" et "4" apparaissent:

(34)|(43)

Pour permettre à '1' ou à '2' de se produire autant de fois qu’à un endroit donné, on peut insérer (1|2)* (ou [12]* _ si notre langage regex accepte cette notation). En insérant cette expression à tous les emplacements disponibles, nous obtenons

(1|2)*((3(1|2)*4)|(4(1|2)*3))(1|2)*

Traduire cela en un modèle de contenu est simple. La structure de base est équivalente à la regex (34)|(43):

<xsd:complexType name="paul0">
  <xsd:choice>
    <xsd:sequence>
      <xsd:element ref="child3"/>
      <xsd:element ref="child4"/>
    </xsd:sequence>
    <xsd:sequence>
      <xsd:element ref="child4"/>
      <xsd:element ref="child3"/>
    </xsd:sequence>
  </xsd:choice>
</xsd:complexType>

Insérer un choix de zéro ou plus de child1 et child2 est simple:

<xsd:complexType name="paul1">
  <xsd:sequence>
    <xsd:choice minOccurs="0" maxOccurs="unbounded">
      <xsd:element ref="child1"/>
      <xsd:element ref="child2"/>
    </xsd:choice>      
    <xsd:choice>
      <xsd:sequence>
        <xsd:element ref="child3"/>
        <xsd:choice minOccurs="0" maxOccurs="unbounded">
          <xsd:element ref="child1"/>
          <xsd:element ref="child2"/>
        </xsd:choice>      
        <xsd:element ref="child4"/>
      </xsd:sequence>
      <xsd:sequence>
        <xsd:element ref="child4"/>
        <xsd:choice minOccurs="0" maxOccurs="unbounded">
          <xsd:element ref="child1"/>
          <xsd:element ref="child2"/>
        </xsd:choice>      
        <xsd:element ref="child3"/>
      </xsd:sequence>
    </xsd:choice>
    <xsd:choice minOccurs="0" maxOccurs="unbounded">
      <xsd:element ref="child1"/>
      <xsd:element ref="child2"/>
    </xsd:choice>      
  </xsd:sequence>
</xsd:complexType>

Si nous voulons minimiser un peu le volume, nous pouvons définir un groupe nommé pour les choix répétés de child1 et child2:

<xsd:group name="onetwo">
  <xsd:choice>
    <xsd:element ref="child1"/>
    <xsd:element ref="child2"/>
  </xsd:choice>   
</xsd:group>

<xsd:complexType name="paul2">
  <xsd:sequence>
    <xsd:group ref="onetwo" minOccurs="0" maxOccurs="unbounded"/>
    <xsd:choice>
      <xsd:sequence>
        <xsd:element ref="child3"/>
        <xsd:group ref="onetwo" minOccurs="0" maxOccurs="unbounded"/>
        <xsd:element ref="child4"/>
      </xsd:sequence>
      <xsd:sequence>
        <xsd:element ref="child4"/>
        <xsd:group ref="onetwo" minOccurs="0" maxOccurs="unbounded"/>
        <xsd:element ref="child3"/>
      </xsd:sequence>
    </xsd:choice>  
    <xsd:group ref="onetwo" minOccurs="0" maxOccurs="unbounded"/>
  </xsd:sequence>
</xsd:complexType>

Dans XSD 1.1, certaines des contraintes sur les groupes all- ont été levées. Il est donc possible de définir ce modèle de contenu de manière plus précise:

<xsd:complexType name="paul3">
  <xsd:all>
    <xsd:element ref="child1" minOccurs="0" maxOccurs="unbounded"/>
    <xsd:element ref="child2" minOccurs="0" maxOccurs="unbounded"/>
    <xsd:element ref="child3"/>
    <xsd:element ref="child4"/>      
  </xsd:all>
</xsd:complexType>

Mais comme le montrent les exemples donnés précédemment, ces modifications apportées aux groupes all- ne modifient en réalité pas le pouvoir d'expression du langage; ils ne font que rendre la définition de certains types de langues plus succincte.

99

C'est ce qui a finalement fonctionné pour moi:

<xsd:element name="bar">
  <xsd:complexType>
    <xsd:sequence>
      <!--  Permit any of these tags in any order in any number     -->
      <xsd:choice minOccurs="0" maxOccurs="unbounded">
        <xsd:element name="child1" type="xsd:string" />
        <xsd:element name="child2" type="xsd:string" />
        <xsd:element name="child3" type="xsd:string" />
      </xsd:choice>
    </xsd:sequence>
  </xsd:complexType>
</xsd:element>
47
Alan

Mais de ce que je comprends, xs: choix ne permet toujours que la sélection d’un seul élément. Par conséquent, si vous définissez MaxOccurs sur non limité comme ceci, cela ne devrait signifier que "n'importe lequel" des éléments enfants peut apparaître plusieurs fois. Est-ce exact?

Non. Le choix est fait individuellement pour chaque "répétition" de xs:choice qui se produit en raison de maxOccurs="unbounded". Par conséquent, le code que vous avez posté est correct et fera réellement ce que vous voulez tel qu'écrit.

8
Pavel Minaev

Vous devriez trouver que le schéma suivant permet ce que vous avez proposé.

  <xs:element name="foo">
    <xs:complexType>
      <xs:sequence minOccurs="0" maxOccurs="unbounded">
        <xs:choice>
          <xs:element maxOccurs="unbounded" name="child1" type="xs:unsignedByte" />
          <xs:element maxOccurs="unbounded" name="child2" type="xs:string" />
        </xs:choice>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

Cela vous permettra de créer un fichier tel que:

<?xml version="1.0" encoding="utf-8" ?>
<foo>
  <child1>2</child1>
  <child1>3</child1>
  <child2>test</child2>
  <child2>another-test</child2>
</foo>

Ce qui semble correspondre à votre question.

3
Steven_W

Si rien de ce qui précède ne fonctionne, vous travaillez probablement sur EDI) une transaction où vous devez valider votre résultat par rapport à un schéma HIPPA ou à tout autre xsd complexe, pour le reste. il existe 8 segments REF et chacun d'entre eux doit apparaître dans n'importe quel ordre et tous ne sont pas obligatoires, ce qui signifie que vous pouvez les avoir dans l'ordre suivant: 1re REF, 3e REF, 2e REF, 9ème REF, sous Situation par défaut EDI réception échouera, car le type complexe par défaut est

<xs:sequence>
  <xs:element.../>
</xs:sequence>

La situation est même complexe lorsque vous appelez votre élément par référence et que cet élément à son emplacement d'origine est lui-même assez complexe. par exemple:

<xs:element>
<xs:complexType>
<xs:sequence>
<element name="REF1"  ref= "REF1_Mycustomelment" minOccurs="0" maxOccurs="1">
<element name="REF2"  ref= "REF2_Mycustomelment" minOccurs="0" maxOccurs="1">
<element name="REF3"  ref= "REF3_Mycustomelment" minOccurs="0" maxOccurs="1">
</xs:sequence>
</xs:complexType>
</xs:element>

Solution:

Ici, remplacer simplement "séquence" par "tout" ou utiliser "choix" avec des combinaisons min/max ne fonctionnera pas!

La première chose à remplacer "xs:sequence" with "<xs:all>" Maintenant, vous devez faire quelques changements à l'endroit où vous référez l'élément, allez à:

<xs:annotation>
  <xs:appinfo>
    <b:recordinfo structure="delimited" field.........Biztalk/2003">

*** Maintenant, dans le segment ci-dessus, ajoutez un point de déclenchement à la fin, comme ceci: trigger_field = "REF01 _... nom complet .." trigger_value = "38" Faites de même pour les autres segments REF où la valeur de déclenchement sera différente, comme par exemple "18 "," XX "," YY "etc..so que vos informations d'enregistrement ressemblent maintenant à: b:recordinfo structure="delimited" field.........Biztalk/2003" trigger_field="REF01_...complete name.." trigger_value="38">


Cela rendra chaque élément unique, car tous les segments REF (exemple ci-dessus) ont la même structure que REF01, REF02, REF03. Et lors de la validation, la validation de la structure est correcte, mais elle ne laisse pas les valeurs se répéter, car elle essaie de rechercher les valeurs restantes dans la première référence elle-même. L'ajout de déclencheurs les rendra tous uniques et ils réussiront dans n'importe quel ordre et dans tous les cas (comme dans le cas des utilisateurs 5 sur 9 et non tous 9/9).

J'espère que cela vous aide, car j'ai passé presque 20 heures à ce sujet.

Bonne chance

1
Prabhdeep Gill