2010-12-20 8 views
24

Krótka historia: chciałbym wiedzieć, jak używać klucza/klucza z XSD, aby elementy miały odniesienia do siebie nawzajem. musi mieć postać przykładu, używając prostego xsd i XML.XML Schema key/keyref - jak z nich korzystać?

Długa historia: znam się na ID/IDREF. Używam ich do łączenia elementów dla JAXB. Powtarzano mi wielokrotnie, że konstrukcja key/keyref w XSD oferuje zwiększoną elastyczność w odwoływaniu między elementami. Konsultowałem się z OReilly XML Schema book, który wydaje się nauczać wszystkiego o poprawnej definicji klucza/klucza i jak jest podobny do ID/IDREF (ale lepszy) i nie daje prostego przykładu jego użycia. Nie wydaje się być podobne, ponieważ definiujesz ID jako atrybut w jednym elemencie, a IDREF w innym elemencie i voila. Ale klucz/keyref muszą być określone we wspólnym przodkiem bazowania i elementu powołanego (AFAIK) ...

używam pliki XSD wygenerować JAXB związana klas Java z XJC

Przeszukałem w przypadku poradników, samouczków i przykładów, ale google podaje mi notki. samo dla wyszukiwania w SO (również z wyszukiwaniem google i włącznie z "+").

Aby ułatwić życie wszystkim osobom, przygotowałem XSD z już zdefiniowaną parą key/keyref, ponieważ ją zrozumiałem.

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

Jak kawałek XML wyglądać, z 'owner'-elementu odnoszącego się do' referenced'-element?

EDYCJA: zastosowała zmianę zaproponowaną przez Toma W, zmieniając atrybut xpath elementu klucza na "właściciel". JAXB (XJC) nadal nie dba o to.

Dziękujemy

Odpowiedz

6

Nie ma specjalnej składni w dokumencie instancji. Wymagane jest jedynie, aby węzeł keyref pasował do istniejącego węzła klucza. Sprawdzanie poprawności powie ci, czy ograniczenie klucza jest spełnione.

RE kod:

Mam dopiero zaczął dabbling z kluczami siebie, ale myślę, że zauważył błąd w twoim - aKey powinna wyglądać następująco:

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

Ponadto - to jest hascha - ograniczenia klucza nie rozpoznają domyślnej przestrzeni nazw. Zawsze należy poprzedzać każdą część ścieżki selector przedrostkiem przestrzeni nazw elementu, którego szukasz. Jeśli nie masz prefiksu przestrzeni nazw - trudne, musisz go dodać. Jest to ograniczenie normy.

+0

Aah, dlatego nie ma żadnego atrybutu. Zastosowałem zmianę, którą wskazałeś, ale JAXB nie generuje niczego, aby mieć dostęp do elementu odniesienia od właściciela - cała część key/keyref wydaje się nie mieć wpływu na mapowanie. Czy może czegoś brakuje? – kostja

+0

Chciałem powiedzieć, że XJC nie generuje ... – kostja

+0

Może powinienem wyjaśnić, co mówię w powyższym poście. Nie wiem, czym jest JAXB, ale to nie powinno mieć znaczenia - staram się powiedzieć, że mówię ... . to wszystko, czego potrzebujesz, aby wyrazić kluczową relację, nie ma składni xml, aby konkretnie zadeklarować kluczową relację w instancji. Chyba masz na myśli to, że używasz frameworku, który powinien działać jako ORM do plików xml, w takim przypadku możesz spodziewać się znaczących wyników, w takim przypadku spróbuj bawić się z zakresem klucza i keyref przez przenoszenie ich. –

2

JAXB nie obsługuje referencji za pomocą xs:key lub xs:keyref. Specyfikacja określa, że ​​ograniczenia te mogą być sprawdzane podczas sprawdzania poprawności, ale nie mają wpływu na dane.

Można to jednak osiągnąć (mniej lub bardziej), używając zamiast tego xs:ID i xs:IDREF. Wprowadzenie, zobacz rozdziały 2.2.15 Referring to Another XML Element i 4.3 Assembling Data with Links (ID, IDREF) w J AXB Tutorial Wolfganga Launa.

Dla próbki XSD, miałoby to sens zmiany definicji elementu do

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

Należy zauważyć, że identyfikatory z typem xs:ID muszą być globalnie unikalne w dokumencie XML. Innymi słowy, nie możesz mieć tego samego identyfikatora dla dwóch różnych elementów w tym samym pliku XML, nawet jeśli elementy są różnych typów.

Domyślnie element lub atrybut typu xs:IDREF wiąże się z java.lang.Object. Jeśli wiesz wcześniej, jaki typ będzie obiektem przywoływanym, możesz dostosować mapowanie, dodając adnotacje JAXB do schematu lub przez zewnętrzną deklarację powiązania (np. xjc -b bindings.xjb).

przykład stosując adnotacje schematu JAXB (nie badane):

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

przykład za pomocą zewnętrznego zgłoszenia wiązań (nie sprawdzone)

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

** markusk ** odpowiedział na to, co nie powiedziałem jednoznacznie, ale zgadł, o co chodzi. Pod warunkiem, że możesz polegać na sprawdzaniu poprawności w celu wyegzekwowania tych ograniczeń w danych biznesowych, nie sądzę, aby używanie kluczy było problemem, ale z tego powodu JAXB nie pomoże. Powodzenia! –

+0

dziękuję. wygląda to tak, jak robię to teraz :) Działa to dobrze, ale aby mieć nawet iluzję bezpieczeństwa typu, trzeba ręcznie zmienić referencje w wygenerowanych klasach właściciela z Object na prawdziwą klasę referencyjną. I nie ma sposobu na prawdziwe bezpieczeństwo. To trochę jest do bani, naprawdę chciałbym to wymusić i pomyślałem, że będzie to możliwe za pomocą key/keyref – kostja

+0

@kostja: Możesz dostosować mapowanie JAXB, aby określić klasę odniesienia. Zaktualizowałem swoją odpowiedź za pomocą (nietestowanych) przykładów tego, jak to zrobić. – markusk

5

spec JAXB nie wiążące obejmują klucz/keyref. Jednak implementacje JAXB, takie jak EclipseLink MOXy (jestem liderem technicznym) mają do tego rozszerzenia. Nasza nadchodząca wersja 2.2 dostarcza sposobu na określenie tego rodzaju relacji za pomocą adnotacji (poskładam razem przykład). Poniżej znajduje się link do tego, jak można to zrobić przy użyciu aktualnej wersji.

Aby uzyskać więcej informacji, patrz:

UPDATE

Miałem nadzieję dostać przykład dołączonego do odpowiedzi, ale mam coraz mniej czasu zanim wyjadę na wakacje. Poniżej jest przykład z naszych dokumentów projektowych, które pokazuje koncepcję:

+0

dziękuję, to wygląda obiecująco. Naprawdę nie mogę się doczekać twojego przykładu – kostja

4

Znalazłem ten wątek szukając tego samego OP został szukasz - prosty przykład użycia elementu <xs:key>. Wszystkie rzeczy JAXB były dla mnie greckie i rozpraszały. Dla innych znalezienie tego wątku później, oto prosty przykład napisali na MSDN kilka lat po OP poprosił o pytanie na SO:

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

W przypadku zmiany łącza MSDN ścieżka breadcrumb brzmiała:

https://msdn.microsoft.com/library następnie kliknij "Przełącz do widoku Biblioteka TOC", i drążyć:

MSDN Library> NET> .NET Framework 4.6 i 4.5> Rozwój przewodnik> Dane i modelowanie> XML Normy odniesienia> schematów XML (XSD) Odniesienie> Schemat XML Elementy> < xsd: klucz> Element