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