2010-12-20 9 views
24

Lange Rede, kurzer Sinn: Ich würde gerne wissen, wie man den Schlüssel/keyref von XSD benutzt, um Elemente Referenzen zueinander haben zu lassen. Es muss eine Form eines Beispiels haben, mit einem einfachen xsd und einem XML.XML-Schema-Schlüssel/keyref - wie man sie benutzt?

Lange Geschichte: Ich bin vertraut mit der Verwendung von ID/IDREF. Ich benutze diese, um Elemente für JAXB zu verbinden. Mir wurde wiederholt gesagt, dass das key/keyref-Konstrukt in XSD eine erhöhte Flexibilität für die Referenzierung zwischen Elementen bietet. Ich habe die OReilly XML Schema book konsultiert, die alles über die richtige Definition von key/keyref zu lehren scheint und wie sie der ID/IDREF ähnelt (aber besser) und gibt kein einfaches Beispiel für ihre Verwendung. Es scheint nicht ähnlich zu sein, weil Sie die ID als ein Attribut in einem Element und die IDREF in einem anderen Element und voila definieren. Aber key/keyref haben in einem gemeinsamen Vorfahren der Referenzierung und das referenzierte Element (AFAIK) definiert werden ...

ich die XSD-Dateien verwenden, um zu generieren JAXB gebundenen Java-Klassen mit XJC

ich gesucht für Anleitungen, Tutorials und Beispiele, aber Google gibt mir Fetzen. Gleiches gilt für Suchanfragen auf SO (auch bei Google und inklusive Suche mit '+').

Um jedermanns Leben einfacher zu machen, habe ich eine XSD mit bereits definierten Schlüssel/Schlüssel-Paar vorbereitet, wie ich es verstanden habe.

<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
<xs:element name="root"> 
    <xs:complexType> 
     <xs:sequence> 
      <xs:element name="referenced"> 
       <xs:complexType> 
        <xs:attribute name="id" type="xs:string" /> 
       </xs:complexType> 
      </xs:element> 
      <xs:element name="owner"> 
       <xs:complexType> 
        <xs:attribute name="id" type="xs:string" /> 
       </xs:complexType> 
      </xs:element> 
     </xs:sequence> 
    </xs:complexType> 
    <xs:key name="aKey"> 
     <xs:selector xpath="owner" /> 
     <xs:field xpath="@id" /> 
    </xs:key> 
    <xs:keyref name="aKeyRef" refer="aKey"> 
     <xs:selector xpath="referenced" /> 
     <xs:field xpath="@id" /> 
    </xs:keyref> 
</xs:element> 

Wie würde sich ein Stück von XML wie mit einem 'owner'-Element verweist ein' referenced'-Element?

BEARBEITEN: Die von Tom W vorgeschlagene Änderung wurde angewendet, indem das Xpath-Attribut des Schlüsselelements in "Eigentümer" geändert wurde. JAXB (XJC) kümmert das immer noch nicht.

Danke

Antwort

6

Es im Instanzdokument keine besondere Syntax. Es ist einfach erforderlich, dass der Schlüsselref-Knoten mit einem vorhandenen Schlüsselknoten übereinstimmt. Die Validierung zeigt Ihnen, ob die Schlüsselbedingung erfüllt ist oder nicht.

RE Code:

Ich habe mit den Tasten selbst gerade erst begonnen Dilettantismus, aber ich glaube, ich habe einen Fehler in deinen getupft - aKey sollte wie folgt aussehen:

<xs:key name="aKey"> 
    <xs:selector xpath="owner" /> 
    <xs:field xpath="@id" /> 
</xs:key> 

Außerdem - das ist ein Fehler - Schlüsseleinschränkungen erkennen den Standardnamespace nicht. Sie müssen jedem Teil des selector X-Pfads immer das Präfix des Namens des Elements voranstellen, das Sie suchen. Wenn Sie kein Namespace-Präfix haben - zäh, müssen Sie eins hinzufügen. Dies ist eine Einschränkung des Standards.

+0

aah, deshalb ist kein Attribut beteiligt. Ich habe die Änderung angewendet, auf die Sie hingewiesen haben, aber JAXB generiert nichts, um vom Eigentümer auf das referenzierte Element zugreifen zu können - der gesamte key/keyref-Teil scheint keinen Einfluss auf das Mapping zu haben. Gibt es noch etwas, das ich vermisse? – kostja

+0

ich wollte sagen XJC generiert nicht ... – kostja

+0

Vielleicht sollte ich klarstellen, was ich in dem obigen Beitrag sage. Ich weiß nicht, was JAXB ist, aber das sollte keinen Unterschied machen - was ich sagen will ist, dass ... heißt. Es ist alles, was Sie brauchen, um die Schlüsselbeziehung auszudrücken, es gibt keine XML-Syntax, um eine Schlüsselbeziehung in der Instanz spezifisch zu deklarieren. Ich denke, Sie meinen, dass Sie ein Framework verwenden, das als ORM für XML-Dateien fungieren soll. In diesem Fall könnten Sie eine sinnvolle Ausgabe erwarten. In diesem Fall sollten Sie versuchen, mit dem Gültigkeitsbereich des Schlüssels und der keyref herumzuspielen Bewegen sie herum. –

2

JAXB unterstützt keine Referenzen mittels xs:key oder xs:keyref. Die Spezifikation besagt, dass diese Einschränkungen während der Validierung überprüft werden können, sie haben jedoch keine Auswirkungen auf Daten.

Sie können dies jedoch (mehr oder weniger) erreichen, indem Sie stattdessen xs:ID und xs:IDREF verwenden. Für eine Einführung siehe die Kapitel 2.2.15 Referring to Another XML Element und 4.3 Assembling Data with Links (ID, IDREF) in der JAXB Tutorial von Wolfgang Laun.

Für Ihre Probe XSD, wäre dies also die Elementdefinition zu

<xs:element name="root"> 
    <xs:complexType> 
     <xs:sequence> 
      <xs:element name="referenced"> 
       <xs:complexType> 
        <xs:attribute name="id" type="xs:ID" /> 
       </xs:complexType> 
      </xs:element> 
      <xs:element name="owner"> 
       <xs:complexType> 
        <xs:attribute name="id" type="xs:IDREF" /> 
       </xs:complexType> 
      </xs:element> 
     </xs:sequence> 
    </xs:complexType> 
</xs:element> 

Beachten Sie, dass Bezeichner mit der xs:ID Typänderung erforderlich ist global eindeutig im XML-Dokument sein. Mit anderen Worten, Sie können nicht dieselbe ID für zwei verschiedene Elemente in derselben XML-Datei haben, auch wenn die Elemente unterschiedliche Typen haben.

Standardmäßig bindet ein Element oder Attribut vom Typ xs:IDREF an java.lang.Object. Wenn Sie im Voraus wissen, welcher Typ das referenzierte Objekt sein soll, können Sie das Mapping anpassen, indem Sie dem Schema JAXB-Annotationen hinzufügen oder eine externe Bindungsdeklaration (z. B. xjc -b bindings.xjb).

Beispiel mit JAXB Schemaannotationen (nicht getestet):

<xs:element name="owner"> 
    <xs:complexType> 
     <xs:attribute name="id" type="xs:IDREF"> 
      <xs:annotation> 
       <xs:appinfo> 
        <jaxb:property> 
         <jaxb:baseType name=”SomeType”/> 
        </jaxb:property> 
       </xs:appinfo> 
      </xs:annotation> 
     </xs:attribute> 
    </xs:complexType> 
</xs:element> 

Beispiel eine externe Bindungen Erklärung (nicht getestet) mit:

<jaxb:bindings node="//xs:element[@name=’owner’]//xs:attribute[@name='id']”> 
    <jaxb:property> 
     <jaxb:basetype name="SomeType"/> 
    </jaxb:property> 
</jaxb:bindings> 
+0

** markusk ** hat geantwortet, was ich nicht explizit wusste, aber erraten, was der Fall. Vorausgesetzt, Sie können sich auf die Validierung verlassen, um diese Einschränkungen in Ihren Geschäftsdaten zu erzwingen. Ich denke nicht, dass die Verwendung von Schlüsseln ein Problem sein sollte, aber ich denke, dass JAXB Ihnen nicht helfen wird. Viel Glück! –

+0

danke. das sieht genauso aus wie das, was ich gerade tue :) Es funktioniert OK, aber um auch nur eine Illusion der Typsicherheit zu haben, müssen Sie die Referenzen in den generierten Eigentümerklassen manuell von Objekt auf die reale Referenzklasse ändern. Und es gibt keine Möglichkeit, echte Typsicherheit zu haben. Dieses irgendwie saugt, ich möchte es wirklich erzwingen und dachte, dass es möglich wäre, mittels key/keyref – kostja

+0

@kostja: Sie können das JAXB Mapping anpassen, um die Referenzklasse anzugeben. Ich habe meine Antwort mit (ungetesteten) Beispielen aktualisiert, wie man das macht. – markusk

5

Die JAXB spec deckt nicht explizit Schlüssel/keyref. Allerdings haben JAXB Implementierungen wie EclipseLink MOXy (Ich bin der Tech-Lead) Erweiterungen dafür. Unsere bevorstehende Version 2.2 bietet eine Möglichkeit, diese Art von Beziehung über Anmerkungen zu spezifizieren (ich werde ein Beispiel zusammenstellen). Im Folgenden finden Sie einen Link, wie Sie mit der aktuellen Version arbeiten können.

Weitere Informationen finden Sie unter:

UPDATE

Ich hatte gehofft, ein Beispiel mit der Antwort enthalten zu bekommen, aber ich bin läuft die Zeit davon bevor ich in den Urlaub fahre. Unten ist ein Beispiel aus unseren Design-Dokumenten, die das Konzept demonstriert:

+0

danke, das sieht vielversprechend aus. Ich freue mich sehr auf dein Beispiel – kostja

4

ich diesen Thread gefunden für die gleiche Sache sucht die OP suchten - ein einfaches Anwendungsbeispiel des <xs:key> Elements. Das ganze JAXB-Zeug war für mich griechisch und eine Ablenkung. später für andere diesen Thread zu finden, hier ist ein einfaches Beispiel auf MSDN ein paar Jahren geschrieben, nachdem die OP hier die Frage gestellt, auf SO:

https://msdn.microsoft.com/en-us/library/ms256101%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396

Falls die MSDN Link Änderungen, die Brotkrumen-Pfad war:

https://msdn.microsoft.com/library klicken Sie dann auf, und Drill-Down bis "zur Bibliothek TOC Ansicht wechseln":

MSDN Library> .NET Entwicklung> .NET Framework 4.6 und 4.5> -Entwicklung> Daten und Modellierung> XML-Standards Referenz> XML-Schema (XSD) Referenz> XML-Schema Elemente> < xsd: Schlüssel> Element