Clave/clave de esquema XML: ¿cómo usarlos?
xsd reference (5)
En pocas palabras, me gustaría saber cómo usar la clave / keyref de XSD para que los elementos tengan referencias entre sí. Debe tener una forma de ejemplo, utilizando un xsd simple y un XML.
Larga historia: estoy familiarizado con el uso de ID / IDREF. Los uso para conectar elementos para JAXB. Me han dicho repetidamente que la construcción de clave / clave en XSD ofrece una flexibilidad mejorada para la referencia entre elementos. He consultado el libro de Esquemas XML de OReilly , que parece enseñar todo acerca de la definición correcta de clave / clave y cómo es similar a la ID / IDREF (pero mejor) y no da un ejemplo sencillo de su uso. No parece ser similar, porque define la ID como un atributo en un elemento y la IDREF en otro elemento y listo. Pero key / keyref debe definirse en un ancestro común de la referencia y el elemento referenciado (AFAIK) ...
Utilizo los archivos XSD para generar clases Java vinculadas a JAXB con XJC
He buscado tutoriales, tutoriales y ejemplos, pero Google me da trucos. 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 clave / clave ya definido 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 una pieza de XML, con un elemento ''propietario'' que hace referencia a un elemento ''referenciado''?
EDITAR: aplicó el cambio propuesto por Tom W, cambiando el atributo xpath del elemento clave a "propietario". A JAXB (XJC) todavía no le importa.
Gracias
Encontré este hilo buscando lo mismo que buscaba el OP: un ejemplo de uso simple del elemento <xs:key>
. Todas las cosas de JAXB eran griegas para mí, y una distracción. Para otros que encuentren este hilo más adelante, aquí hay un ejemplo simple publicado en MSDN un par de años después de que el 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 caso de que el enlace de MSDN cambie, la ruta de navegación era:
https://msdn.microsoft.com/library luego haga clic en "Cambiar a la vista de tabla de contenido" y luego profundice en:
MSDN Library> .NET development> .NET Framework 4.6 y 4.5> Guía de desarrollo> Datos y modelado> Referencia de estándares XML> Referencia de esquemas XML (XSD)> Elementos del esquema XML> <xsd: key> Elemento
JAXB no admite referencias mediante xs:key
o xs:keyref
. La especificación establece que estas restricciones pueden verificarse durante la validación, pero no tienen efecto en los datos.
Sin embargo, puede lograr esto (más o menos) utilizando xs:ID
y xs:IDREF
lugar. Para una introducción, vea los capítulos 2.2.15 Refiriéndose a otro elemento XML y 4.3 Ensamblando datos con enlaces (ID, IDREF) en el Tutorial de J AXB por Wolfgang Laun.
Para su muestra XSD, esto significaría cambiar la definición del 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>
Tenga en cuenta que los identificadores con el tipo xs:ID
deben ser globalmente únicos 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 diferentes tipos.
De forma predeterminada, un elemento o atributo de tipo xs:IDREF
enlaza a java.lang.Object
. Si sabe de antemano de qué tipo será el objeto al que se hace referencia, puede personalizar la asignación, ya sea agregando anotaciones JAXB al esquema o mediante una declaración de enlace externo (por ejemplo, xjc -b bindings.xjb
).
Ejemplo de uso de 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 externos (no probado):
<jaxb:bindings node="//xs:element[@name=’owner’]//xs:attribute[@name=''id'']”>
<jaxb:property>
<jaxb:basetype name="SomeType"/>
</jaxb:property>
</jaxb:bindings>
La especificación JAXB no cubre explícitamente key / keyref. Sin embargo, las implementaciones de 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 (pondré un ejemplo). A continuación se muestra un enlace a cómo se puede hacer usando la versión actual.
Para más información, ver:
ACTUALIZAR
Esperaba que se incluyera un ejemplo 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:
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 se cumple o no la restricción clave.
RE su código:
Yo solo empecé a meterme con las llaves, pero creo que he detectado un error en el tuyo: aKey
debería verse así:
<xs:key name="aKey">
<xs:selector xpath="owner" />
<xs:field xpath="@id" />
</xs:key>
Además, esto es un gotcha: las restricciones de clave no reconocen el espacio de nombres predeterminado. Siempre debe prefijar cada parte de la xpath del selector
con el prefijo de 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 de la norma.
Por favor, trate de ver este tutorial clave / keyref .
El texto coloreado es muy útil.