webentwicklung-frage-antwort-db.com.de

XSD - wie kann man Elemente beliebig oft in beliebiger Reihenfolge zulassen?

Ich versuche, eine XSD zu erstellen und die Definition mit der folgenden Anforderung zu schreiben:

  • Zulassen, dass das angegebene untergeordnete Element beliebig oft angezeigt wird (0 bis unbegrenzt)
  • Zulassen, dass untergeordnete Elemente in einer beliebigen Reihenfolge vorliegen

Ich sah mich um und fand verschiedene Lösungen wie 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>

Aber nach meinem Verständnis erlaubt xs: choice immer noch nur die Auswahl einzelner Elemente. Daher sollte das Festlegen von "MaxOccurs" auf "unbounded" nur bedeuten, dass "eines" der untergeordneten Elemente mehrmals auftreten kann. Ist das genau?

Wenn die obige Lösung falsch ist, wie kann ich das erreichen, was ich oben in meiner Anforderung angegeben habe?

[~ # ~] edit [~ # ~] : Was ist, wenn die Anforderung wie folgt lautet?

  • Element child1 child2 kann beliebig oft vorkommen (0 bis unbegrenzt)
  • Elemente in beliebiger Reihenfolge
  • Die Elemente child3 und child4 sollten genau einmal vorkommen.

Diese XML ist zum Beispiel gültig:

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

aber das ist nicht (vermisst child3)

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

In dem Schema, das Sie in Ihrer Frage haben, child1 oder child2 kann in beliebiger Reihenfolge und beliebig oft vorkommen. Das klingt nach dem, wonach Sie suchen.

Edit: Wenn nur einer von ihnen beliebig oft vorkommen soll, muss der Unbegrenzte stattdessen auf die Elemente klicken:

Edit: Feste Eingabe in XML.

Edit: Großgeschriebenes O in 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

Die alternative Formulierung der in einer späteren Bearbeitung hinzugefügten Frage scheint noch unbeantwortet zu sein: Wie kann angegeben werden, dass unter den untergeordneten Elementen eines Elements eines mit dem Namen child3, eines mit dem Namen child4 vorhanden sein muss? und eine beliebige Nummer mit dem Namen child1 oder child2, ohne Einschränkung für die Reihenfolge, in der die untergeordneten Elemente angezeigt werden.

Dies ist eine direkt definierbare reguläre Sprache, und das von Ihnen benötigte Inhaltsmodell ist isomorph zu einem regulären Ausdruck, der den Satz von Zeichenfolgen definiert, in denen die Ziffern '3' und '4' jeweils genau einmal vorkommen, sowie die Ziffern '1' und '2 'beliebig oft vorkommen. Wenn es nicht offensichtlich ist, wie man das schreibt, kann es hilfreich sein, darüber nachzudenken, welche Art von Finite-State-Maschine Sie erstellen würden, um eine solche Sprache zu erkennen. Es hätte mindestens vier verschiedene Zustände:

  • ein Ausgangszustand, in dem weder '3' noch '4' gesehen wurde
  • ein Zwischenzustand, in dem '3' gesehen wurde, aber nicht '4'
  • ein Zwischenzustand, in dem '4' gesehen wurde, aber nicht '3'
  • ein Endzustand, in dem sowohl '3' als auch '4' gesehen wurden

Unabhängig davon, in welchem ​​Zustand sich der Automat befindet, können "1" und "2" gelesen werden. Sie ändern den Status der Maschine nicht. Im Ausgangszustand wird auch '3' oder '4' akzeptiert; in den Zwischenzuständen wird nur '4' oder '3' akzeptiert; Im Endzustand wird weder '3' noch '4' akzeptiert. Die Struktur des regulären Ausdrucks ist am einfachsten zu verstehen, wenn wir zuerst einen regulären Ausdruck für die Teilmenge unserer Sprache definieren, in der nur '3' und '4' vorkommen:

(34)|(43)

Damit "1" oder "2" an einem bestimmten Ort beliebig oft vorkommen kann, können wir (1|2)* (oder [12]*) einfügen, wenn unsere Regex-Sprache diese Notation akzeptiert. Wenn wir diesen Ausdruck an allen verfügbaren Stellen einfügen, erhalten wir

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

Die Übersetzung in ein Inhaltsmodell ist unkompliziert. Die Grundstruktur entspricht dem regulären Ausdruck (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>

Das Einfügen einer Null-oder-Mehr-Auswahl von child1 und child2 ist einfach:

<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>

Wenn wir den Umfang ein wenig minimieren möchten, können wir eine benannte Gruppe für die wiederholten Auswahlmöglichkeiten von child1 und child2 definieren:

<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>

In XSD 1.1 wurden einige Einschränkungen für all- Gruppen aufgehoben, sodass dieses Inhaltsmodell präziser definiert werden kann:

<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>

Wie jedoch aus den oben angegebenen Beispielen hervorgeht, ändern diese Änderungen an all-Gruppen nicht die Ausdruckskraft der Sprache. Sie machen nur die Definition bestimmter Arten von Sprachen prägnanter.

Das hat bei mir endlich geklappt:

<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

Aber nach meinem Verständnis erlaubt xs: choice immer noch nur die Auswahl einzelner Elemente. Daher sollte das Festlegen von "MaxOccurs" auf "unbounded" nur bedeuten, dass "eines" der untergeordneten Elemente mehrmals auftreten kann. Ist das genau?

Nein. Die Auswahl erfolgt individuell für jede "Wiederholung" von xs:choice das kommt vor wegen maxOccurs="unbounded". Daher ist der von Ihnen veröffentlichte Code korrekt und wird tatsächlich das tun, was Sie geschrieben haben möchten.

8
Pavel Minaev

Sie sollten feststellen, dass das folgende Schema das zulässt, was Sie vorgeschlagen haben.

  <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>

Auf diese Weise können Sie eine Datei wie die folgenden erstellen:

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

Welches scheint zu Ihrer Frage zu passen.

3
Steven_W

Wenn keines der oben genannten Verfahren funktioniert, arbeiten Sie wahrscheinlich an einer EDI) - Transaktion, bei der Sie Ihr Ergebnis anhand eines HIPPA-Schemas oder eines anderen komplexen xsd validieren müssen Dort müssen 8 REF-Segmente und eines von ihnen in einer beliebigen Reihenfolge erscheinen und es sind auch nicht alle erforderlich. Dies bedeutet, dass Sie diese in der folgenden Reihenfolge haben können: 1. REF, 3. REF, 2. REF, 9. REF. Unter Standardbedingungen EDI Receive schlägt fehl, da der komplexe Standardtyp ist

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

Die Situation ist sogar komplex, wenn Sie Ihr Element durch eine Abkühlung aufrufen und dieses Element dann an seiner ursprünglichen Stelle selbst ziemlich komplex ist. beispielsweise:

<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>

Lösung:

Hier funktioniert es nicht, einfach "Sequenz" durch "Alle" zu ersetzen oder "Auswahl" mit Min/Max-Kombinationen zu verwenden!

Ersetzen Sie als erstes "xs:sequence" with "<xs:all>" Nun müssen Sie einige Änderungen an der Stelle vornehmen, an der Sie auf das Element verweisen. Gehen Sie zu:

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

*** Fügen Sie nun im obigen Segment den Triggerpunkt am Ende wie folgt hinzu. Trigger_field = "REF01 _... complete name .." trigger_value = "38" Machen Sie dasselbe für andere REF-Segmente, bei denen der Triggerwert unterschiedlich ist, wie z. B. "18 "," XX "," YY "usw., so dass Ihre Datensatzinformationen jetzt wie folgt aussehen: b:recordinfo structure="delimited" field.........Biztalk/2003" trigger_field="REF01_...complete name.." trigger_value="38">


Dies macht jedes Element einzigartig. Grund dafür ist, dass alle REF-Segmente (obiges Beispiel) dieselbe Struktur wie REF01, REF02, REF03 haben. Und während der Validierung ist die Strukturvalidierung in Ordnung, lässt die Werte jedoch nicht wiederholen, da versucht wird, im ersten REF selbst nach verbleibenden Werten zu suchen. Das Hinzufügen von Triggern macht sie alle einzigartig und sie werden in jeder Reihenfolge und in situativen Fällen bestanden (z. B. verwenden Sie 5 von 9 und nicht alle 9/9).

Hoffe es hilft dir, denn ich habe fast 20 Stunden damit verbracht.

Viel Glück

1
Prabhdeep Gill