2010-08-01 12 views
16

Dato un layout XML come questo, sto provando a creare uno schema XSD per convalidarlo.Come creare uno schema per un elenco non ordinato di nodi XML, con vincoli di occorrenza

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

I requisiti sono i seguenti:

  • Childa, ChildB e Childe possono verificarsi in qualsiasi ordine . (<xs:sequence> non idoneo)
  • ChildA è obbligatorio ma può verificarsi più volte.
  • ChildB è facoltativo e potrebbe verificarsi più volte.
  • ChildC è facoltativo e potrebbe verificarsi una volta solo.

La tecnica che di solito uso per creare una lista ordinata di nodi è usare un <xs:choice maxOccurs="unbounded"> con ogni possibile nodo della lista, tuttavia, sono in grado di creare il vincolo sul Childa e maxOccurs="1" contraint su Childe. (Il numero di occorrenze della scelta ha la precedenza su quelli degli elementi qui).

<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

non credo che lo schema XML corrente è in grado di fare questo al momento. Ti sei registrato in altri sistemi di validazione, come RelaxNG (www.relaxng.org) forse ?? –

+0

Domande correlate con, al momento della stesura di questo, risposte migliori: https://stackoverflow.com/questions/2290360/xsd-how-to-allow-elements-in-any-order-any-number-of-times/12012599 – Flow

risposta

10

Aggiornamento: In XSD 1.1m alcuni dei vincoli all -Gruppi sono state revocate. Vedere le risposte here e here.

Non è semplice ma sembra fattibile. La parte difficile qui è che le definizioni dello schema devono essere deterministiche. L'approccio che ho usato è stato quello di visualizzare il problema disegnando un automa a stati finiti e poi scrivere un'espressione regolare che corrispondesse a quella degli automi. Non è affatto complicato come potrebbe sembrare. Tuttavia, l'uso di un altro sistema di validazione avrebbe probabilmente fornito una risposta più semplice.

Ho fatto alcuni test ma mancare alcuni casi speciali è facile. Si prega di commentare se si individua un errore.

... e qui è il codice:

<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

"Combinando e annidando i vari gruppi forniti da XML Schema e impostando i valori di' minOccurs e maxOccurs', è possibile rappresentare qualsiasi modello di contenuto esprimibile con una DTD XML 1.0. " Ma non hanno mai detto che sarebbe carino. – Will

+0

Jasso.Questo è molto intelligente. Sto cercando di modificarlo per fornire: nessun elemento obbligatorio (perdere ChildA); e molti articoli 0 o 1-occurance (come ChildC). Ho dei problemi reali. Ho postato la domanda su http://stackoverflow.com/questions/14321579/how-to-make-a-schema-for-an-unordered-list-where-some-occur-once-some-many-time . Sembra che tu sia un esperto in questo. Se tu potessi dare un'occhiata lo apprezzerei. – Dave

+0

@Dave Grazie per aver apprezzato i miei sforzi. Ho scritto una risposta alla tua domanda. È arrivato un po 'tardi, perché non avevo effettuato l'accesso qui per alcune settimane. – jasso

1

Stavo leggendo il relax-NG shortcut syntax.

Sto indovinando questo sarebbe condensato al seguente nella sintassi compatta di relax-ng:

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

che è sicuro abbastanza.

+0

Mi dispiace che sia sbagliato ... poiché ChildA è almeno uno ma può essere più ... – Texas

+0

'head = element root {ChildA + & ChildC? & ChildB *} 'forse? – Alan

2

Questo dovrebbe fare quello che hai specificato:

<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

Grazie per aver provato, ma questo non si adatta. A e B possono apparire più volte, ma l'elemento '' specifica che ogni elemento in esso può apparire zero o una sola volta. Sarebbe bello se ci fosse una soluzione così semplice, ma penso che la soluzione di jasso sia probabilmente la migliore che otterremo. –

+1

cosa succede se imposti minOccurs = 1 e maxOccurs = 1 per tutti gli elementi figlio? –

+0

Questa risposta è corretta (AFAIKT) se si utilizza [XSD 1.1] (https://www.w3.org/TR/xmlschema11-1/). [G1.3 5.] (https://www.w3.org/TR/xmlschema11-1/#changes) spiega la differenza tra XSD 1.0 che consente ciò. – Flow

Problemi correlati