Long story short : i would like to know how to use the key/keyref from XSD to let elements have references to each other. it has to have a form of an example, using a simple xsd and an XML.
Long story : I am familiar with usage of ID/IDREF. I use those to connect elements for JAXB. I have been told repeatedly that the key/keyref construct in XSD offers enhanced flexibility for inter-element referencing. I have consulted the OReilly XML Schema book, that seems to teach everything about correct definition of key/keyref and how it is similar to the ID/IDREF (but better) and doesn't give a simple example of its use. It doesn't seem to be similar, because you define the ID as an attribute in one element and the IDREF in another element and voila. But key/keyref have to be defined in a common ancestor of the referencing and the referenced element (AFAIK)...
I use the XSD files to generate JAXB-bound Java classes with XJC
I have searched for how-tos, tutorials and examples, but google gives me scraps. same for searches on SO (also with google and inclusive search with '+' ).
In order to make everyone's lives easier i have prepared an XSD with already defined key/keyref pair as i have understood it.
<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>
How would a piece of XML look like, with an 'owner'-element referencing a 'referenced'-element?
EDIT : applied the change proposed by Tom W, changing the xpath attribute of the key element to "owner". JAXB (XJC) still doesnt care though.
Thank you
I found this thread searching for the same thing the OP was searching for - a simple usage example of the
<xs:key>
element. All the JAXB stuff was greek to me, and a distraction. For others finding this thread later, here's a simple example posted on MSDN a couple years after the OP asked the question here on SO:https://msdn.microsoft.com/en-us/library/ms256101%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
In case the MSDN link changes, the breadcrumb path was:
https://msdn.microsoft.com/library then click "Switch to Library TOC view", and drill down through:
MSDN Library > .NET development > .NET Framework 4.6 and 4.5 > Development Guide > Data and Modeling > XML Standards Reference > XML Schemas (XSD) Reference > XML Schema Elements > <xsd:key> Element
There is no special syntax in the instance document. It is simply required that the keyref node matches an extant key node. Validation will tell you whether or not the key constraint is satisfied.
RE your code:
I've only just started dabbling with keys myself, but I think I've spotted an error in yours -
aKey
should look like:Furthermore - this is a gotcha - key constraints don't recognise the default namespace. You must always prefix every part of the
selector
xpath with the namespace prefix of the element you're looking up. If you don't have a namespace prefix - tough, you'll need to add one. This is a limitation of the standard.Please, try to see this key/keyref tutorial.
The colored text is very helpful.
The JAXB spec does not explicitly cover key/keyref. However JAXB implemenations such as EclipseLink MOXy (I'm the tech lead) have extensions for this. Our upcoming 2.2 release provides a means to specify this kind of relationship via annotations (I'll put together an example). Below is a link to how it can be done using the current release.
For more information see:
UPDATE
I was hoping to get an example included with the answer, but I am running out of time before I leave on vacation. Below is an example from our design documents that demonstrates the concept:
JAXB doesn't support references by means of
xs:key
orxs:keyref
. The specification states that these constraints may be checked during validation, but they have no effect on data.However, you can achieve this (more or less) by using
xs:ID
andxs:IDREF
instead. For an introduction, see the chapters 2.2.15 Referring to Another XML Element and 4.3 Assembling Data with Links (ID, IDREF) in the JAXB Tutorial by Wolfgang Laun.For your sample XSD, this would meaning changing the element definition to
Note that identifiers with the
xs:ID
type are required to be globally unique in the XML document. In other words, you cannot have the same ID for two different elements in the same XML file, even if the elements are of different types.By default, an element or attribute of type
xs:IDREF
binds tojava.lang.Object
. If you know in advance what type the referenced object will be, you can customize the mapping, either by adding JAXB annotations to the schema or through an external binding declaration (e.g.,xjc -b bindings.xjb
).Example using JAXB schema annotations (not tested):
Example using an external bindings declaration (not tested):