2016-06-01 8 views
-1

Ich mag eine Beziehung implementieren, wo „Rate“ Element nur existiert sollte, wenn „ComponentInstId und‚ComponentInstIdServ‘nicht vorhanden ist und umgekehrt. Wie kann ich das unter XSD-Code zu tun in?Unvereinbare Elemente in XSD

<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified"> 
<xs:element name="Request"> 
    <xs:complexType> 
     <xs:sequence> 
      <xs:element name="Component"> 
       <xs:complexType> 
        <xs:all> 
         <xs:element name="ComponentId" nillable="false"> 
          <xs:simpleType> 
           <xs:restriction base="xs:integer"> 
            <xs:whiteSpace value="collapse"/> 
           </xs:restriction> 
          </xs:simpleType> 
         </xs:element> 
         <xs:element name="ComponentInstId" nillable="true" minOccurs="0"> 
          <xs:simpleType> 
           <xs:restriction base="xs:integer"> 
            <xs:whiteSpace value="collapse"/> 
           </xs:restriction> 
          </xs:simpleType> 
         </xs:element> 
         <xs:element name="ComponentInstIdServ" nillable="true" minOccurs="0"> 
          <xs:simpleType> 
           <xs:restriction base="xs:int"> 
            <xs:whiteSpace value="collapse"/> 
           </xs:restriction> 
          </xs:simpleType> 
         </xs:element> 
         <xs:element name="Rate" nillable="true" minOccurs="0"> 
          <xs:simpleType> 
           <xs:restriction base="xs:int"> 
            <xs:whiteSpace value="collapse"/> 
            <xs:minInclusive value="0"/> 
           </xs:restriction> 
          </xs:simpleType> 
         </xs:element> 
        </xs:all> 
       </xs:complexType> 
      </xs:element> 
     </xs:sequence> 
    </xs:complexType> 
</xs:element> 

Antwort

1

Warum nicht das Äquivalent von (ComponentId, (Rate | (ComponentInstId, ComponentInstIdServ?)?))?

wie wichtig ist es, dass die Reihenfolge der Sequenz von Kindern nützliche Informationen zu variieren erlaubt zu sein? Gibt es? Wenn nicht, die Reihenfolge beheben, so wie HTML erfordert das head kommen vor body statt nach. Wenn die Sequenz Informationen bereitstellt, können Sie die Möglichkeiten entweder multiplizieren oder das XML restrukturieren. Wenn Sie ComponentId für Component und Attribute für Id und IdServ für ComponentInst zu einem erforderlichen Attribut machen, kann das Inhaltsmodell von Component nur (Rate | ComponentInst)? lauten.

Sie sagen, dass "Sequenz spielt keine Rolle." Wenn dies bedeutet, dass "Sequenz keine Informationen übermittelt", stellt eine Deklaration des folgenden Formulars sicher, dass Sie immer die ID der Komponente und entweder Tarifinformation oder ComponentInst-Information oder keine von beiden haben.

<xs:element name="Component"> 
    <xs:complexType> 
    <xs:choice minOccurs="0"> 
     <xs:element name="Rate" nillable="true"> 
     <xs:simpleType> 
      <xs:restriction base="xs:int"> 
      <xs:whiteSpace value="collapse"/> 
      <xs:minInclusive value="0"/> 
      </xs:restriction> 
     </xs:simpleType> 
     </ 
     <xs:element name="ComponentInst" nillable="true"> 
     <xs:complexType> 
     <xs:sequence/> 
     <xs:attribute name="Id" type="xs:int"/> 
     <xs:attribute name="IdServ" type="xs:nonNegativeInteger"/> 
     </ 
     </ 
    </ 
    <xs:attribute name="Id" type="xs:int" use="required"/> 
    </ 
</ 

(nicht getestet, da das Fehlen einer vollständigen End-Tags soll vorzuschlagen.)

Wenn die von Ihnen „Sequence spielt keine Rolle“ bedeutet „es, dass alle möglichen Sequenzen der wesentlich ist, Informationen sind gültig ", dann muss Ihr Content-Modell komplizierter sein, aber es ist ein einfacher genug regulärer Ausdruck, um es auszuarbeiten.

[Addendum] Da einige Leser von Stack Overflow anscheinend Schwierigkeiten haben, Probleme wie diese zu lösen, ist hier eine Lösung, die Elemente A (think: ComponentId), B (think: Rate), C (ComponentInstId), und D (ComponentInstIdServ), um in einer beliebigen Reihenfolge zu erscheinen, mit A erforderlich, die anderen optional, und mit der Einschränkung, dass, wenn B auftritt, weder C noch D auftreten können.

Lassen Sie uns zunächst nur eine Auswahl aller möglichen Sequenzen schreiben, in einer kompakten Schreibweise wie die von DTDs oder Relax NG kompakte Syntax:

((A, B?) 
| (A, C?, D?) 
| (A, D?, C?) 
| (B?, A) 
| (C?, A, D?) 
| (C?, D, A) 
| (D?, A, C?) 
| (D?, C, A) 
) 

Dieses (oder besser gesagt seine XSD equivaslent) ist nicht legal, Es steht jedoch wegen der "Unique Particle Attribution" -Regel von XSD, also müssen wir die verschiedenen linken Präfixe aus dem Weg räumen und den Ausdruck im Allgemeinen deterministisch machen. Eine Instanz kann mit A, B, C oder D beginnen, also machen wir zuerst vier deterministische Ausdrücke für diese Fälle, die wir dann in einer Auswahl zusammensetzen können.Wenn A zuerst:

(A, ((B) | (C, D?) | (D, C?))?) 

wenn B zuerst:

(B, A?) 

Wenn C erste ist:

(C ((A, D?) | (D, A))) 

Wenn D erste ist:

(D ((A, C?) | (C, A))) 

Oder alle zusammen jetzt:

((A, ((B) | (C, D?) | (D, C?))?) 
| (B, A?) 
| (C ((A, D?) | (D, A))) 
| (D ((A, C?) | (C, A))) 
) 

Oder in der äquivalenten XSD:

<xs:complexType name="demo"> 
    <xs:choice> 
    <!--* we can start with A *--> 
    <xs:sequence> 
     <xs:element ref="A"/> 
     <xs:choice minOccurs="0"> 
     <xs:element ref="B" minOccurs="0"/> 
     <xs:sequence> 
      <xs:element ref="C"/> 
      <xs:element ref="D" minOccurs="0"/> 
     </xs:sequence> 
     <xs:sequence> 
      <xs:element ref="D"/> 
      <xs:element ref="C" minOccurs="0"/> 
     </xs:sequence> 
     </xs:choice> 
    </xs:sequence> 
    <!--* or we can start with B *--> 
    <xs:sequence> 
     <xs:element ref="B"/> 
     <xs:element ref="A" minOccurs="0"/> 
    </xs:sequence> 
    <!--* or we can start with C *--> 
    <xs:sequence> 
     <xs:element ref="C"/> 
     <xs:choice> 
     <xs:sequence> 
      <xs:element ref="A"/> 
      <xs:element ref="D" minOccurs="0"/> 
     </xs:sequence> 
     <xs:sequence> 
      <xs:element ref="D"/> 
      <xs:element ref="A"/> 
     </xs:sequence> 
     </xs:choice> 
    </xs:sequence> 
    <!--* or we can start with D *--> 
    <xs:sequence> 
     <xs:element ref="D"/> 
     <xs:choice> 
     <xs:sequence> 
      <xs:element ref="A"/> 
      <xs:element ref="C" minOccurs="0"/> 
     </xs:sequence> 
     <xs:sequence> 
      <xs:element ref="C"/> 
      <xs:element ref="A"/> 
     </xs:sequence> 
     </xs:choice> 
    </xs:sequence> 
    </xs:choice> 
</xs:complexType> 
+0

bitte ein bisschen mehr erklären. Reihenfolge spielt keine Rolle. Modell für Komponente ist Alle. Kann ComponentId nicht optional machen. – user3366906

+0

Entschuldigung; das vorhandene Schema falsch gelesen. Habe die Antwort überarbeitet. –

+0

1. Elemente ComponentId, ComponentInstId, ComponentInstIdServ und Rate können in beliebiger Reihenfolge stehen. Nur ComponentId ist hier zwingend. Die einzige erforderliche Abhängigkeit besteht darin, dass, wenn Rate vorhanden ist, ComponentInstId und ComponentInstIdServ nicht vorhanden sein sollten. Im Folgenden finden Sie Beispiel xmls. – user3366906