XML模式键/keyref -如何使用它们?

时间:2021-07-05 17:17:47

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.

长话短说:我想知道如何使用XSD中的key/keyref来让元素相互引用。它必须有一个示例的形式,使用一个简单的xsd和一个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)...

长话短说:我熟悉ID/IDREF的用法。我使用它们来连接JAXB的元素。我多次被告知,XSD中的key/keyref构造为元素间引用提供了增强的灵活性。我参考了OReilly XML模式手册,它似乎教会了关于key/keyref的正确定义以及它与ID/IDREF(但更好)的相似之处,并且没有给出一个简单的使用示例。它看起来并不是相似的,因为您将ID定义为一个元素中的属性,而IDREF在另一个元素中。但是key/keyref必须在引用和引用元素(AFAIK)的共同祖先中定义……

I use the XSD files to generate JAXB-bound Java classes with XJC

我使用XSD文件使用XJC生成jaxb绑定的Java类

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 '+' ).

我已经搜索了how-to、教程和示例,但是谷歌给了我一些残缺。SO上的搜索也是如此(谷歌和带'+'的全包搜索也是如此)。

In order to make everyone's lives easier i have prepared an XSD with already defined key/keyref pair as i have understood it.

为了让每个人的生活更轻松,我已经准备了一个XSD,其中包含我已经理解的键/keyref对。

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

如果“所有者”-元素引用“引用”-元素,那么一块XML会是什么样子?

EDIT : applied the change proposed by Tom W, changing the xpath attribute of the key element to "owner". JAXB (XJC) still doesnt care though.

编辑:应用Tom W提出的更改,将关键元素的xpath属性更改为“owner”。JAXB (XJC)仍然不介意。

Thank you

谢谢你!

5 个解决方案

#1


6  

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.

实例文档中没有特殊的语法。它只是要求keyref节点匹配一个extant关键节点。验证将告诉您是否满足键约束。

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:

我自己才刚刚开始玩键盘,但我觉得我发现了你的一个错误——aKey应该是:

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

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.

此外——这是一个陷阱——关键字约束不能识别默认名称空间。必须始终为选择器xpath的每个部分加上要查找的元素的名称空间前缀。如果您没有名称空间前缀——很难,您将需要添加一个。这是标准的一个限制。

#2


5  

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.

JAXB规范没有显式地涵盖key/keyref。然而,JAXB实现如EclipseLink MOXy(我是技术负责人)对其进行了扩展。我们即将发布的2.2版本提供了一种方法,可以通过注释来指定这种关系(我将结合一个示例)。下面是如何使用当前版本的链接。

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:

我本来希望能得到一个包含答案的例子,但是在我休假之前我已经没有时间了。以下是我们设计文件中的一个例子,展示了这个概念:

#3


4  

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:

我发现这个线程正在搜索OP正在搜索的内容—— 元素的一个简单使用示例。所有JAXB的东西对我来说都是希腊语,分散了我的注意力。对于后面找到这个线程的其他人,这里有一个简单的例子,是在OP在这里问这个问题几年后发布在MSDN上的:

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

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:

MSDN链路改变时,面包屑路径为:

https://msdn.microsoft.com/library then click "Switch to Library TOC view", and drill down through:

然后点击“切换到库TOC视图”,然后从下面开始:

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

MSDN库> .NET开发> .NET Framework 4.6和4.5 >开发指导>数据和建模> XML标准引用> XML Schema (XSD)引用> XML Schema元素> < XSD:key>元素

#4


3  

JAXB doesn't support references by means of xs:key or xs:keyref. The specification states that these constraints may be checked during validation, but they have no effect on data.

JAXB不通过xs:key或xs:keyref来支持引用。规范声明在验证过程中可以检查这些约束,但是它们对数据没有影响。

However, you can achieve this (more or less) by using xs:ID and xs: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.

但是,您可以通过使用xs:ID和xs:IDREF来实现(或多或少)。在介绍中,请参阅第2.2.15章中提到的另一个XML元素,以及在由Wolfgang Laun编写的JAXB教程中使用链接(ID, IDREF)组装数据的章节。

For your sample XSD, this would meaning changing the element definition to

对于示例XSD,这意味着将元素定义更改为

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

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.

注意,使用xs:ID类型的标识符在XML文档中必须是全局惟一的。换句话说,对于同一个XML文件中的两个不同元素,即使元素是不同类型的,也不能有相同的ID。

By default, an element or attribute of type xs:IDREF binds to java.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).

默认情况下,类型为xs:IDREF的元素或属性绑定到java.lang.Object。如果您事先知道被引用对象的类型,您可以通过向模式添加JAXB注释或通过外部绑定声明(例如,xjc -b bindings.xjb)定制映射。

Example using JAXB schema annotations (not tested):

使用JAXB模式注释(未测试)的示例:

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

Example using an external bindings declaration (not tested):

使用外部绑定声明(未测试)的示例:

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

#5


1  

Please, try to see this key/keyref tutorial.

请尝试查看这个key/keyref教程。

The colored text is very helpful.

彩色文字很有帮助。

#1


6  

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.

实例文档中没有特殊的语法。它只是要求keyref节点匹配一个extant关键节点。验证将告诉您是否满足键约束。

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:

我自己才刚刚开始玩键盘,但我觉得我发现了你的一个错误——aKey应该是:

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

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.

此外——这是一个陷阱——关键字约束不能识别默认名称空间。必须始终为选择器xpath的每个部分加上要查找的元素的名称空间前缀。如果您没有名称空间前缀——很难,您将需要添加一个。这是标准的一个限制。

#2


5  

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.

JAXB规范没有显式地涵盖key/keyref。然而,JAXB实现如EclipseLink MOXy(我是技术负责人)对其进行了扩展。我们即将发布的2.2版本提供了一种方法,可以通过注释来指定这种关系(我将结合一个示例)。下面是如何使用当前版本的链接。

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:

我本来希望能得到一个包含答案的例子,但是在我休假之前我已经没有时间了。以下是我们设计文件中的一个例子,展示了这个概念:

#3


4  

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:

我发现这个线程正在搜索OP正在搜索的内容—— 元素的一个简单使用示例。所有JAXB的东西对我来说都是希腊语,分散了我的注意力。对于后面找到这个线程的其他人,这里有一个简单的例子,是在OP在这里问这个问题几年后发布在MSDN上的:

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

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:

MSDN链路改变时,面包屑路径为:

https://msdn.microsoft.com/library then click "Switch to Library TOC view", and drill down through:

然后点击“切换到库TOC视图”,然后从下面开始:

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

MSDN库> .NET开发> .NET Framework 4.6和4.5 >开发指导>数据和建模> XML标准引用> XML Schema (XSD)引用> XML Schema元素> < XSD:key>元素

#4


3  

JAXB doesn't support references by means of xs:key or xs:keyref. The specification states that these constraints may be checked during validation, but they have no effect on data.

JAXB不通过xs:key或xs:keyref来支持引用。规范声明在验证过程中可以检查这些约束,但是它们对数据没有影响。

However, you can achieve this (more or less) by using xs:ID and xs: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.

但是,您可以通过使用xs:ID和xs:IDREF来实现(或多或少)。在介绍中,请参阅第2.2.15章中提到的另一个XML元素,以及在由Wolfgang Laun编写的JAXB教程中使用链接(ID, IDREF)组装数据的章节。

For your sample XSD, this would meaning changing the element definition to

对于示例XSD,这意味着将元素定义更改为

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

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.

注意,使用xs:ID类型的标识符在XML文档中必须是全局惟一的。换句话说,对于同一个XML文件中的两个不同元素,即使元素是不同类型的,也不能有相同的ID。

By default, an element or attribute of type xs:IDREF binds to java.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).

默认情况下,类型为xs:IDREF的元素或属性绑定到java.lang.Object。如果您事先知道被引用对象的类型,您可以通过向模式添加JAXB注释或通过外部绑定声明(例如,xjc -b bindings.xjb)定制映射。

Example using JAXB schema annotations (not tested):

使用JAXB模式注释(未测试)的示例:

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

Example using an external bindings declaration (not tested):

使用外部绑定声明(未测试)的示例:

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

#5


1  

Please, try to see this key/keyref tutorial.

请尝试查看这个key/keyref教程。

The colored text is very helpful.

彩色文字很有帮助。