2010-05-19 9 views
6

Ich arbeite regelmäßig mit einigen XML-Dateien und möchte eine bessere Validierung dann eine DTD bereitstellen können. Also begann ich, über Schemata zu lesen, um zu sehen, ob sie mir helfen würden. Bisher war ich in der Lage, etwas zu schaffen, das fast so funktioniert, wie ich es brauche, außer für ein Stück. Ich möchte in der Lage sein, das Attribut eines Elements auf die Werte eines anderen Attributs von Geschwister- oder Vorgängerelementen des gleichen Elementtyps zu beschränken. Ist das überhaupt möglich mit XML Schema key/keyref constrictions?So erstellen Sie ein XML-Schema mit Schlüssel/Schlüsselreferenzen für verschachtelte Elemente des gleichen Typs

ich ein Dokument haben, die etwa wie folgt aussieht:

<nodeContainer> 
    <node name="Table"> 
    </node> 

    <node name="MyHouse"> 
     <node name="RoomWithDoor"> 
     </node> 
     <node name="DiningRoom" extends="RoomWithDoor"> 
      <node name="DiningTable" extends="Table"> 
      </node> 
     </node> 
    </node> 

    <node name="MySummerHouse"> 
     <node name="DiningRoom"> 
      <node name="DiningTable" extends="Table"> 
      </node> 
     </node> 
    </node> 
</nodeContainer> 

In diesem Dokument können Knoten andere Knoten "erweitern", das sind:

  • Geschwister
  • Geschwister der Eltern

Knoten sollten jedoch nicht "erweitern":

  • Eltern
  • Kinder-Knoten des Geschwister der Eltern

Das bedeutet, dass MyHouse kann „erweitern“ Tabelle, das macht keinen Sinn, aber ich bin mit dem in Ordnung.

Wichtig ist auch, dass beide Hausknoten in der Lage sein sollten, ihre eigenen Knoten DiningRoom zu haben.

Und mein aktuelles Schema ist ähnlich wie diese:

<xs:complexType name="node"> 
    <xs:choice minOccurs="0" maxOccurs="unbounded"> 
     <xs:element ref="node"/> <!-- node can have other nodes inside it --> 
     <xs:element ref="leaf"/> 
    </xs:choice> 
    <xs:attribute name="name"  type="xs:anySimpleType" use="required"/> 
    <xs:attribute name="extends" type="xs:anySimpleType"/> 
</xs:complexType> 

<!-- document root --> 
<xs:element name="root"> 
    <xs:complexType> 
     <xs:choice minOccurs="0" maxOccurs="unbounded"> 
      <xs:element name="nodeContainer"> 
       <xs:complexType> 
        <xs:choice minOccurs="0" maxOccurs="unbounded"> 
         <xs:element ref="node"/>  
        </xs:choice> 
       </xs:complexType> 
      </xs:element> 
      <xs:element ref="otherType"/> 
     </xs:choice> 
    </xs:complexType> 

    <!-- create constrictions --> 
    <xs:unique name="UniqueNodes"> 
     <xs:selector xpath="nodeContainer/node"/> 
     <xs:field xpath="@name"/> 
    </xs:unique> 
    <xs:keyref refer="UniqueNodes" name="ValidNodeExtends"> 
     <xs:selector xpath=".//node"></xs:selector> 
     <xs:field xpath="@extends"></xs:field> 
    </xs:keyref> 
</xs:element> 

Dieses Schema funktioniert Teil das, was ich suche. Er legt die Schlüssel als die Namen der ersten Knotenebene in nodeContainer fest, und diese Schlüssel können verwendet werden, um jeden Knoten auf jeder Ebene auf oder unter nodeContainer zu "erweitern". Und das funktioniert, solange ich Geschwister auf niedrigeren Ebenen nicht "verlängern" möchte. Das Beispieldokument oben nicht, weil diese Linie bestätigen:

<node name="DiningRoom" extends="RoomWithDoor"> 

Im Schema I RoomWithDoor erstellt habe, ist kein gültiger Schlüssel zuweisen zu „erweitert“, da sie nicht Teil der ersten Ebene von Knoten sind in nodeContainer. Aber gibt es trotzdem die Schlüssel/Schlüsselrezepte zu schreiben, um sie zu gültigen Schlüsseln zu machen? Macht die Platzierung der Schlüssel/Keyref-Definitionen einen Unterschied? Sind meine XPaths zu spezifisch (wie können sie weniger spezifisch sein)?

Antwort

0

Was ist, wenn Sie den XPath-Selektor ändern

<xs:selector xpath="nodeContainer//node"/> 

Mit anderen Worten für UniqueNodes zu

passieren würde - jedes Knotenelement unter dem nodeContainer. Würde dies nicht erlauben, was Sie erreichen möchten?