Thomas J.S.: xml-schema: key und keyref

Beitrag lesen

Hallo,

Tja watt nun?

Du bist meiner Antwort vorgekommen, hätte dir das gleiche gesagt, wie du es nun herausgefunden hast (mehr oder weniger).

Dein key:

  

>   <xsd:key name="myKey">  
>     <xsd:selector xpath="a"/>  
>     <xsd:field xpath="b/@name"/>  
>     <xsd:field xpath="@name"/>  
>   </xsd:key>  

funktioniert nicht, denn bei einer Struktur wie:

  
 <a name="s">  
  <b name="v">..</b>  
  <b name="w">..</b>  
  <b name="x">..</b>  
 </a>  
 <a name="t">  
  <b name="x">..</b>  
  <b name="y">..</b>  
  <b name="z">..</b>  
 </a>  
 <a name="u">  
  <b name="x">..</b>  
  <b name="y">..</b>  
  <b name="z">..</b>  
 </a>  

produziert b/@name mehrere Treffer.
Das kann man noch verhindern:

  
 <xs:element name="root">  
  <xs:key name="KeyAB1">  
   <xs:selector xpath="a" />  
   <xs:field xpath="@name" />  
  </xs:key>  
 </xs:element>  
  
 <xs:element name="a">  
  <xs:key name="KeyAB2">  
   <xs:selector xpath="b"></xs:selector>  
   <xs:field xpath="@name"></xs:field>  
  </xs:key>  
 </xs:element>  

jetzt muss man <c> noch referenzieren:

  
 <xs:element name="root">  
  <xs:key name="KeyAB1">  
   <xs:selector xpath="a" />  
   <xs:field xpath="@name" />  
  </xs:key>  
  <xs:keyref refer="KeyAB1" name="RefKeyC">  
   <xs:selector xpath="c" />  
   <xs:field xpath="@context" />  
  </xs:keyref>  
 </xs:element>  
  

das erlaubt abre noch immer z.B:

<c context="t">...  
<c context="t">...

also muss man Eindeutigkeitsbeschränkung für <c> definieren (keyref impliziert nicht Eindeutigkeit) :

  
 <xs:element name="root">  
  <xs:key name="KeyAB1">  
   <xs:selector xpath="a" />  
   <xs:field xpath="@name" />  
  </xs:key>  
  <xs:unique name="C">  
   <xs:selector xpath="c" />  
   <xs:field xpath="@context" />  
  </xs:unique>  
  <xs:keyref refer="KeyAB1" name="RefKeyC">  
   <xs:selector xpath="c" />  
   <xs:field xpath="@context" />  
  </xs:keyref>  
 </xs:element>  

Man kann/soll ebenfalls noch für <d> eine Eindeutigkeitsbeschränkung machen.

  
 <xs:element name="c">  
  <xs:unique name="D">  
   <xs:selector xpath="d" />  
   <xs:field xpath="@id" />  
  </xs:unique>  
 </xs:element>  

Die Schwierigkeit ist jetzt, wie referneziert man ein bestimmtes <b> von einem bestimmten <a> ausgehend in <c>/<d>.

Und das geht eben nicht. Man kann noch eine Referenz setzen:

  
 <xs:element name="root">  
  <xs:key name="KeyAB1">  
   <xs:selector xpath="a" />  
   <xs:field xpath="@name" />  
  </xs:key>  
  <xs:unique name="C">  
   <xs:selector xpath="c" />  
   <xs:field xpath="@context" />  
  </xs:unique>  
  <xs:keyref refer="KeyAB1" name="RefKeyC">  
   <xs:selector xpath="c" />  
   <xs:field xpath="@context" />  
  </xs:keyref>  
  <xs:keyref refer="KeyAB2" name="RefKeyD">  
   <xs:selector xpath="c/d" />  
   <xs:field xpath="@id" />  
  </xs:keyref>  
 </xs:element>  

ABER: weil keyref eben keine Eindeutigkeit impliziert, können hier beliebige <b>-werte referenziert werden, sie müssen nur vorhanden sein. Dadurch ist z.B. so etwas möglich:

  
 <a name="s">  
  <b name="v">..</b>  
  <b name="w">..</b>  
  <b name="x">..</b>  
 </a>  
 <a name="u">  
  <b name="x">..</b>  
  <b name="y">..</b>  
  <b name="z">..</b>  
 </a>  
 <c context="s">  
  <d id="z">..</d> <---- falsche Referenz, ist aber "gültig"  
  <d id="x">..</d>  
 </c>  
 <c context="u">  
  <d id="x">..</d>  
  <d id="y">..</d>  
 </c>  

Was tun? Das XML anderes designen?

Grüße
Thomas

Hier nochmal das Schema insgesamt:

  
<?xml version="1.0" encoding="UTF-8"?>  
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">  
 <xs:element name="root">  
  <xs:complexType>  
   <xs:sequence>  
    <xs:element maxOccurs="unbounded" ref="a"/>  
    <xs:element maxOccurs="unbounded" ref="c"  />  
   </xs:sequence>  
  </xs:complexType>  
  <xs:key name="KeyAB1">  
   <xs:selector xpath="a" />  
   <xs:field xpath="@name" />  
  </xs:key>  
  <xs:unique name="C">  
   <xs:selector xpath="c" />  
   <xs:field xpath="@context" />  
  </xs:unique>  
  <xs:keyref refer="KeyAB1" name="RefKeyC">  
   <xs:selector xpath="c" />  
   <xs:field xpath="@context" />  
  </xs:keyref>  
  <xs:keyref refer="KeyAB2" name="RefKeyD">  
   <xs:selector xpath="c/d" />  
   <xs:field xpath="@id" />  
  </xs:keyref>  
 </xs:element>  
 <xs:element name="a">  
  <xs:complexType>  
   <xs:sequence>  
    <xs:element maxOccurs="unbounded" ref="b"/>  
   </xs:sequence>  
   <xs:attribute name="name" use="required" type="xs:NCName"/>  
  </xs:complexType>  
  <xs:key name="KeyAB2">  
   <xs:selector xpath="b"></xs:selector>  
   <xs:field xpath="@name"></xs:field>  
  </xs:key>  
 </xs:element>  
 <xs:element name="b">  
  <xs:complexType>  
   <xs:simpleContent>  
    <xs:extension base="xs:NMTOKEN">  
     <xs:attribute name="name" use="required" type="xs:NCName"/>  
    </xs:extension>  
   </xs:simpleContent>  
  </xs:complexType>  
 </xs:element>  
 <xs:element name="c">  
  <xs:complexType>  
   <xs:sequence>  
    <xs:element maxOccurs="unbounded" ref="d"/>  
   </xs:sequence>  
   <xs:attribute name="context" use="required" type="xs:NCName"/>  
  </xs:complexType>  
  <xs:unique name="D">  
   <xs:selector xpath="d" />  
   <xs:field xpath="@id" />  
  </xs:unique>  
 </xs:element>  
 <xs:element name="d">  
  <xs:complexType>  
   <xs:simpleContent>  
    <xs:extension base="xs:NMTOKEN">  
     <xs:attribute name="id" use="required" type="xs:NCName"/>  
    </xs:extension>  
   </xs:simpleContent>  
  </xs:complexType>  
 </xs:element>  
</xs:schema>