2010-12-20 137 views
24

Resumen breve: me gustaría saber cómo usar la tecla/keyref de XSD para permitir que los elementos tengan referencias entre ellos. tiene que tener una forma de ejemplo, usando un simple xsd y un XML.XML Schema key/keyref - cómo usarlos?

Relato largo: Estoy familiarizado con el uso de ID/IDREF. Los uso para conectar elementos para JAXB. Me han dicho repetidamente que el constructo clave/keyref en XSD ofrece una mayor flexibilidad para la referencia entre elementos. He consultado el OReilly XML Schema book, que parece enseñar todo sobre la definición correcta de key/keyref y cómo es similar al ID/IDREF (pero mejor) y no da un ejemplo simple de su uso. No parece ser similar, porque define el ID como un atributo en un elemento y el IDREF en otro elemento y voila. Pero clave/keyref tienen que definirse en un ancestro común de la referencia y el elemento de referencia (que yo sepa) ...

utilizo los archivos XSD para generar clases Java con destino a JAXB con XJC

He buscado para how-tos, tutoriales y ejemplos, pero google me da restos. lo mismo para las búsquedas en SO (también con google y búsqueda inclusiva con '+').

Para facilitar la vida de todos, preparé un XSD con un par de llaves/llaveros ya definidos, tal como lo he entendido.

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

¿Cómo sería un pedazo de XML parecer, con un 'owner'-elemento de referencia a un' elemento referenced'?

EDIT: aplicó el cambio propuesto por Tom W, cambiando el atributo xpath del elemento clave a "owner". A JAXB (XJC) aún no le importa.

Gracias

Respuesta

6

no hay una sintaxis especial en el documento de instancia. Simplemente se requiere que el nodo keyref coincida con un nodo clave existente. La validación le dirá si la restricción de clave está o no satisfecha.

RE su código:

he hecho más que empecé escarceos con las llaves a mí mismo, pero creo que he encontrado un error en la tuya - aKey debe verse como:

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

Por otra parte - esto es un Gotcha: las restricciones clave no reconocen el espacio de nombres predeterminado. Siempre debe prefijar cada parte del selector xpath con el prefijo del espacio de nombres del elemento que está buscando. Si no tiene un prefijo de espacio de nombres, difícil, tendrá que agregar uno. Esta es una limitación del estándar.

+0

aah, es por eso que no hay ningún atributo involucrado. Apliqué el cambio que señaló, pero JAXB no genera nada para poder acceder al elemento al que hace referencia el propietario: toda la parte clave/parte clave no parece tener ningún impacto en el mapeo. ¿Hay algo más que me pierdo? – kostja

+0

quise decir que XJC no genera ... – kostja

+0

Tal vez debería aclarar lo que estoy diciendo en la publicación anterior. No sé lo que es JAXB, pero esto no debería marcar la diferencia, lo que estoy tratando de decir es que decir ... . .es todo lo que necesita para expresar la relación clave, no existe una sintaxis xml para declarar específicamente una relación clave en la instancia. Lo que supongo que quieres decir es que estás usando un marco que se supone que funciona como un ORM para archivos xml, en cuyo caso puedes esperar algún resultado significativo, en cuyo caso, intenta jugar con el alcance de la tecla y keyref por moviéndolos. –

2

JAXB no admite referencias mediante xs:key o xs:keyref. La especificación establece que estas restricciones se pueden verificar durante la validación, pero no tienen ningún efecto en los datos. Sin embargo, puede lograr esto (más o menos) usando xs:ID y xs:IDREF. Para una introducción, vea los capítulos 2.2.15 Referring to Another XML Element y 4.3 Assembling Data with Links (ID, IDREF) en el J AXB Tutorial de Wolfgang Laun.

Para su XSD de ejemplo, esto significa que el cambio de la definición de elemento a

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

en cuenta que los identificadores con el tipo xs:ID ser única a nivel mundial en el documento XML. En otras palabras, no puede tener la misma ID para dos elementos diferentes en el mismo archivo XML, incluso si los elementos son de tipos diferentes.

De forma predeterminada, un elemento o atributo del tipo xs:IDREF se une a java.lang.Object. Si sabe de antemano qué tipo será el objeto al que se hace referencia, puede personalizar la asignación, agregando anotaciones JAXB al esquema o mediante una declaración de enlace externo (por ejemplo, xjc -b bindings.xjb).

ejemplo utilizando anotaciones de esquema JAXB (no probado):

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

ejemplo utilizando una declaración de enlaces externo (no probado):

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

** markusk ** ha respondido lo que no conocía explícitamente, pero adivinó cuál era el caso. Siempre que pueda confiar en la validación para hacer cumplir estas limitaciones en los datos de su empresa, no creo que el uso de claves sea un problema, pero a partir de esto, creo que JAXB no lo ayudará. ¡Buena suerte! –

+0

gracias. que se parece a lo que estoy haciendo ahora :) Funciona bien, pero para tener incluso una ilusión de seguridad de tipo, tienes que cambiar manualmente las referencias en las clases de propietario generadas de Object a la clase de referencia real. Y no hay forma de tener seguridad real. Esto apesta un poco, realmente me gustaría aplicarlo y pensé que sería posible por medio de key/keyref – kostja

+0

@kostja: Puedes personalizar el mapeo JAXB para especificar la clase de referencia. He actualizado mi respuesta con muestras (no probadas) de cómo hacer esto. – markusk

5

La especificación JAXB no cubre explícitamente clave/keyref. Sin embargo, las implementaciones JAXB como EclipseLink MOXy (soy el líder tecnológico) tienen extensiones para esto. Nuestra próxima versión 2.2 proporciona un medio para especificar este tipo de relación a través de anotaciones (voy a armar un ejemplo). A continuación hay un enlace a cómo se puede hacer usando la versión actual.

Para más información ver:

ACTUALIZACIÓN

Tenía la esperanza de obtener un ejemplo que se incluye con la respuesta, pero me estoy quedando sin tiempo antes de irme de vacaciones A continuación se muestra un ejemplo de nuestros documentos de diseño que demuestra el concepto:

+0

gracias, esto parece prometedor. Estoy esperando tu ejemplo – kostja

4

yo encontramos este hilo en busca de lo mismo que el PO estaba buscando - un simple ejemplo de uso del elemento <xs:key>. Todas las cosas de JAXB eran griegas para mí, y una distracción. Para otros para encontrar este hilo después, aquí está un ejemplo sencillo publicado en MSDN un par de años después de la OP hizo la pregunta aquí en SO:

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

En el caso de los enlaces cambios de MSDN, el camino de migas de pan fue:

https://msdn.microsoft.com/library continuación, haga clic en "Cambiar a la vista Biblioteca TOC", y taladrar a través de:

MSDN> desarrollo .NET> .NET Framework 4.6 y 4.5> Guía de desarrollo> datos y Modelado> XML Estándares de Referencia> esquemas XML (XSD) Referencia> Esquema XML Elementos> < xsd: clave> Elemento

Cuestiones relacionadas