2014-03-12 10 views
5

Ich versuche, eine XSD-Vorlage für die folgenden zu definieren:XSD Zwei Elemente mit dem gleichen Namen, aber unterschiedlichen Attributwert

<template_data> 
    <given_name lang="ENG">Zluty</given_name> 
    <given_name lang="CES">Žlutý</given_name> 
</template_data> 

Bisher habe ich mit

<xs:complexType name="attribute_CES"> 
    <xs:attribute name="lang" type="xs:string" use="required" fixed="CES"/> 
</xs:complexType> 

<xs:complexType name="attribute_ENG"> 
    <xs:attribute name="lang" type="xs:string" use="required" fixed="ENG"/> 
</xs:complexType> 

<xs:element name="template_data"> 
    <xs:complexType> 
    <xs:sequence> 
     <xs:element name="given_name" type="attribute_CES"/> 
     <xs:element name="given_name" type="attribute_ENG"/>   
    </xs:sequence> 
    </xs:complexType> 
</xs:element> 

Problem kommen ist, das definiert ein Element mit ein und demselben Namen zweimal, jedes Mal mit einem anderen Typ, zu dem jeder XSD-Validator, den ich gefunden habe, protestiert.

Soweit ich weiß, können Sie verlangen, dass ein Attribut einen bestimmten Wert mit der Option fixed hat, und das ist in der Definition eines (komplexen) Typs enthalten. Wenn Sie also das Attribut mit einem anderen Wert haben möchten, müssen Sie einen neuen Typ definieren.

Was ich brauche, ist die template_data beide given_name s enthalten, genau einmal mit lang="CES", und genau einmal mit lang="ENG". Gibt es eine Möglichkeit, ein xsd-Validierungsschema dafür zu schreiben, oder ist das unmöglich (zum Beispiel, wenn die XML-Eingabe nicht den Standards entspricht)?

+0

Das mit XSD nicht möglich ist, da dies bedeutet, den Inhalt der Validierung - XSD nur das Schema validieren kann. Du brauchst etwas wie [Schematron] (http://en.wikipedia.org/wiki/Schematron), um zu erreichen, was du brauchst. – Filburt

+0

Wirklich? Ich habe eine grundlegende Inhaltsüberprüfung mit XSD gesehen, mit 'restriction' (http://www.w3schools.com/schema/schema_facets.asp) und mit' fixed' in Attributen (http://www.w3schools.com/ schema/schema_simple_attributes.asp) oder mit types. – Humungus

Antwort

7

Sie können nicht zwei Elemente mit demselben Namen mit verschiedenen Typen im selben Kontext deklarieren, aber ich denke, ich verstehe, was Sie tun möchten.

Wenn Sie wirklich Elemente mit sehr unterschiedlichen Inhalten hätten, wäre es sinnvoll, zwei Typen zu erstellen (und es wäre auch sinnvoll, wenn sie unterschiedliche Namen haben oder zumindest in einem anderen Kontext vorkommen). Da Ihre Daten ähnlich ist, und der Hauptunterschied ist ein Attribut, das den Textinhalt des Elements beschreibt, können Sie einen Typ erstellen und die Werte beschränken das Attribut empfangen kann:

<xs:complexType name="languageType"> 
    <xs:simpleContent> 
     <xs:extension base="xs:string"> 
      <xs:attribute name="lang" use="required"> 
       <xs:simpleType> 
        <xs:restriction base="xs:NMTOKEN"> 
         <xs:enumeration value="ENG"/> 
         <xs:enumeration value="CES"/> 
        </xs:restriction> 
       </xs:simpleType> 
      </xs:attribute> 
     </xs:extension> 
    </xs:simpleContent> 
</xs:complexType> 

In languageType über Sie einfach Inhalt haben (xs:string) und ein erforderliches lang Attribut, das nur zwei Werte haben kann: ENG oder CES.

Wenn Sie sicherstellen wollen, dass es genau zwei Elemente, können Sie das in Ihrer template_data Elementdefinition mit minOccurs="2" und maxOccurs="2" für das given_name Kind Element einschränken:

<xs:element name="template_data"> 
    <xs:complexType> 
     <xs:sequence> 
      <xs:element name="given_name" type="languageType" minOccurs="2" maxOccurs="2"/>   
     </xs:sequence> 
    </xs:complexType> 
    ... 

Jetzt ist es noch möglich ist, zwei zu haben, given_name Elemente mit demselben Attribut lang="ENG". Um zu verhindern, dass wir eine xs:key Definition im Rahmen der template_data Elementdefinition hinzufügen:

<xs:element name="template_data"> 
    <xs:complexType> ... </xs:complexType> 
    <xs:key name="languageKey"> 
     <xs:selector xpath="given_name" /> 
     <xs:field xpath="@lang"/> 
    </xs:key> 
</xs:element> 

Die xs:key verwendet die verschachtelten given_name als Selektor und sein lang Attribut als Schlüsselfeld. Es werden keine doppelten Felder erlaubt, dh es werden keine zwei given_name Elemente mit denselben lang Attributen erlaubt. Da Sie nur zwei erlauben, und sie können nur ENG oder CES sein, muss man ENG sein, und die anderen CES.

nun dieses XML-Dokument zu validieren:

<template_data> 
    <given_name lang="ENG">Zluty</given_name> 
    <given_name lang="CES">Žlutý</given_name> 
</template_data> 

<template_data> 
    <given_name lang="CES">Žlutý</given_name> 
    <given_name lang="ENG">Zluty</given_name> 
</template_data> 

Aber diese nicht:

<template_data> 
    <given_name lang="FRA">Zluty</given_name> 
    <given_name lang="CES">Žlutý</given_name> 
    <given_name lang="ENG">Zluty</given_name> 
</template_data> 

<template_data> 
    <given_name lang="ENG">Zluty</given_name> 
    <given_name lang="ENG">Zluty</given_name> 
</template_data> 

<template_data> 
    <given_name lang="ENG">Zluty</given_name> 
</template_data> 

<template_data> 
    <given_name>Zluty</given_name> 
    <given_name lang="ENG">Zluty</given_name> 
</template_data> 
+0

Danke, das ist genau das, was ich gesucht habe! Wäre dies aus Neugierde noch mit einem anderen Element, z.B. last_name, mit ähnlichen Regeln wie given_name? Ich meine zwei gegebene Namen mit lang CES und ENG, und zwei last_names mit lang CES und ENG. – Humungus

+0

Ja, aber Sie müssten einen zweiten Schlüssel für den Nachnamen definieren, da die Schlüssel in einem bestimmten Bereich eindeutig sind. Außerdem müssten Sie die Vorkommensbedingungen in das Element 'sequence' verschieben, wenn Sie den Vornamen und den Nachnamen zusammen beibehalten möchten. Sie können sie auch in ein übergeordnetes 'name'-Element einschließen und nur einen Schlüssel für das übergeordnete Element verwenden. – helderdarocha

Verwandte Themen