web-dev-qa-db-fra.com

Clé de schéma XML / keyref - comment les utiliser?

Pour faire court: je voudrais savoir comment utiliser la clé/référence de clé de XSD pour permettre aux éléments d'avoir des références les uns aux autres. il doit avoir la forme d'un exemple, en utilisant un simple xsd et un XML.

Longue histoire: je connais bien l'utilisation d'ID/IDREF. Je les utilise pour connecter des éléments pour JAXB. On m'a dit à plusieurs reprises que la construction key/keyref dans XSD offre une flexibilité accrue pour le référencement inter-éléments. J'ai consulté le livre OReilly XML Schema , qui semble tout enseigner sur la définition correcte de key/keyref et comment il est similaire à l'ID/IDREF (mais mieux) et ne donne pas un exemple simple de son utilisation. Il ne semble pas être similaire, car vous définissez l'ID comme attribut dans un élément et l'IDREF dans un autre élément et le tour est joué. Mais key/keyref doivent être définis dans un ancêtre commun du référencement et de l'élément référencé (AFAIK) ...

J'utilise les fichiers XSD pour générer des classes JAXB Java avec XJC

J'ai cherché des tutoriels, des tutoriels et des exemples, mais Google me donne des notes. idem pour les recherches sur SO (aussi avec google et recherche inclusive avec '+').

Afin de faciliter la vie de chacun, j'ai préparé un XSD avec une paire clé/clé de référence déjà définie telle que je l'ai comprise.

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

À quoi ressemblerait un morceau de XML, avec un élément "propriétaire" référençant un élément "référencé"?

ÉDITER : appliqué la modification proposée par Tom W, en changeant l'attribut xpath de l'élément clé en "propriétaire". JAXB (XJC) ne s'en soucie toujours pas.

Je vous remercie

26
kostja

Il n'y a pas de syntaxe spéciale dans le document d'instance. Il est simplement nécessaire que le nœud keyref corresponde à un nœud clé existant. La validation vous indiquera si la contrainte clé est satisfaite ou non.

RE votre code:

Je viens juste de commencer à essayer les clés moi-même, mais je pense avoir repéré une erreur dans la vôtre - aKey devrait ressembler à:

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

De plus - c'est un piège - les contraintes de clé ne reconnaissent pas l'espace de noms par défaut. Vous devez toujours préfixer chaque partie du selector xpath avec le préfixe d'espace de noms de l'élément que vous recherchez. Si vous n'avez pas de préfixe d'espace de noms - difficile, vous devrez en ajouter un. Il s'agit d'une limitation de la norme.

6
Tom W

J'ai trouvé ce fil recherchant la même chose que l'OP recherchait - un exemple d'utilisation simple du <xs:key> élément. Tous les trucs JAXB étaient grecs pour moi, et une distraction. Pour d'autres qui trouveront ce fil plus tard, voici un exemple simple publié sur MSDN quelques années après que l'OP ait posé la question ici sur SO:

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

Dans le cas où le lien MSDN change, le chemin de navigation était:

https://msdn.Microsoft.com/library puis cliquez sur "Basculer vers la vue de la table des matières de la bibliothèque", et explorez en détail:

Bibliothèque MSDN> Développement .NET> .NET Framework 4.6 et 4.5> Guide de développement> Données et modélisation> Référence des normes XML> Référence des schémas XML (XSD)> Éléments de schéma XML> <xsd: key> Element

5
UberschallSamsara

La spécification JAXB ne couvre pas explicitement key/keyref. Cependant, les implémentations JAXB telles que EclipseLink MOXy (je suis le responsable technique) ont des extensions pour cela. Notre prochaine version 2.2 fournit un moyen de spécifier ce type de relation via des annotations (je vais mettre en place un exemple). Vous trouverez ci-dessous un lien vers la façon de procéder à l'aide de la version actuelle.

Pour plus d'informations, voir:

[~ # ~] mise à jour [~ # ~]

J'espérais obtenir un exemple inclus avec la réponse, mais je manque de temps avant de partir en vacances. Voici un exemple de nos documents de conception qui illustre le concept:

5
bdoughan

JAXB ne prend pas en charge les références au moyen de xs:key ou xs:keyref. La spécification indique que ces contraintes peuvent être vérifiées lors de la validation, mais qu'elles n'ont aucun effet sur les données.

Cependant, vous pouvez y parvenir (plus ou moins) en utilisant xs:ID et xs:IDREF au lieu. Pour une introduction, voir les chapitres 2.2.15 Se référant à un autre élément XML et 4.3 Assemblage de données avec des liens (ID, IDREF) dans le J Tutoriel AXB par Wolfgang Laun.

Pour votre exemple de XSD, cela signifierait changer la définition de l'élément en

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

Notez que les identificateurs avec xs:ID type doit être globalement unique dans le document XML. En d'autres termes, vous ne pouvez pas avoir le même ID pour deux éléments différents dans le même fichier XML, même si les éléments sont de types différents.

Par défaut, un élément ou attribut de type xs:IDREF lier à Java.lang.Object. Si vous savez à l'avance de quel type sera l'objet référencé, vous pouvez personnaliser le mappage, soit en ajoutant des annotations JAXB au schéma, soit via une déclaration de liaison externe (par exemple, xjc -b bindings.xjb).

Exemple utilisant des annotations de schéma JAXB (non testé):

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

Exemple d'utilisation d'une déclaration de liaisons externes (non testée):

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

S'il vous plaît, essayez de voir ceci tutoriel key/keyref .

Le texte en couleur est très utile.

3
kitsune