XML Schema key/keyref - 如何使用它们?
Posted
技术标签:
【中文标题】XML Schema key/keyref - 如何使用它们?【英文标题】:XML Schema key/keyref - how to use them? 【发布时间】:2011-05-28 09:05:21 【问题描述】:长话短说:我想知道如何使用 XSD 中的 key/keyref 来让元素相互引用。它必须有一个示例的形式,使用一个简单的 xsd 和一个 XML。
长话短说:我熟悉 ID/IDREF 的用法。我使用它们来连接 JAXB 的元素。有人反复告诉我,XSD 中的 key/keyref 构造为元素间引用提供了增强的灵活性。我已经咨询了OReilly XML Schema book,它似乎教了关于 key/keyref 的正确定义以及它与 ID/IDREF 的相似之处(但更好)的所有内容,并且没有给出一个简单的使用示例。它似乎并不相似,因为您将 ID 定义为一个元素中的属性,而将 IDREF 定义为另一个元素中的属性,瞧。但是 key/keyref 必须在引用和被引用元素 (AFAIK) 的共同祖先中定义...
我使用 XSD 文件通过 XJC 生成 JAXB 绑定的 Java 类
我已经搜索了操作方法、教程和示例,但谷歌给了我一些残羹剩饭。对于 SO 上的搜索也是如此(也可以使用 google 和使用 '+' 的包容性搜索)。
为了让每个人的生活更轻松,我准备了一个 XSD,其中包含我理解的已经定义的 key/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>
如果“所有者”元素引用“引用”元素,那么一段 XML 会是什么样子?
编辑: 应用了 Tom W 提出的更改,将关键元素的 xpath 属性更改为“所有者”。但 JAXB (XJC) 仍然不在乎。
谢谢
【问题讨论】:
【参考方案1】:请尝试查看此key/keyref tutorial。
彩色文字很有帮助。
【讨论】:
这实际上非常有用。这听起来很疯狂,但彩色文字是最好的部分。但是,我确实希望它使用 AAA BBB 以外的其他东西,等等……一些现实生活中的例子。【参考方案2】:我发现这个线程正在搜索 OP 正在搜索的相同内容 - <xs:key>
元素的简单用法示例。所有 JAXB 的东西对我来说都是希腊式的,而且会分散注意力。对于后来发现这个线程的其他人,这是在 OP 在 SO 上提出问题几年后发布在 MSDN 上的一个简单示例:
https://msdn.microsoft.com/en-us/library/ms256101%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
如果 MSDN 链接发生更改,则面包屑路径为:
https://msdn.microsoft.com/library 然后点击“切换到图书馆目录视图”, 并向下钻取:
MSDN 库 > .NET 开发 > .NET Framework 4.6 和 4.5 > 开发指南 > 数据和建模 > XML 标准参考 > XML 架构 (XSD) 参考 > XML 架构元素 >
【讨论】:
【参考方案3】:JAXB 不支持通过xs:key
或xs:keyref
进行引用。规范声明这些约束可以在验证期间检查,但它们对数据没有影响。
但是,您可以(或多或少地)使用xs:ID
和xs:IDREF
来实现此目的。有关介绍,请参阅 Wolfgang Laun 的 JAXB Tutorial 中的 2.2.15 Referring to Another XML Element 和 4.3 Assembling Data with Links (ID, IDREF) 章节。
对于您的示例 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>
请注意,xs:ID
类型的标识符在 XML 文档中必须是全局唯一的。换言之,对于同一个 XML 文件中的两个不同元素,您不能拥有相同的 ID,即使这些元素属于不同类型。
默认情况下,xs:IDREF
类型的元素或属性绑定到 java.lang.Object
。如果您事先知道被引用对象的类型,您可以自定义映射,方法是向架构添加 JAXB 注释或通过外部绑定声明(例如,xjc -b bindings.xjb
)。
使用 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>
使用外部绑定声明的示例(未测试):
<jaxb:bindings node="//xs:element[@name=’owner’]//xs:attribute[@name='id']”>
<jaxb:property>
<jaxb:basetype name="SomeType"/>
</jaxb:property>
</jaxb:bindings>
【讨论】:
markusk 已经回答了我没有明确知道但猜到了情况的问题。如果您可以依靠验证来在您的业务数据中强制执行这些约束,我认为使用键应该不是问题,但据此我猜 JAXB 不会帮助您。祝你好运! 谢谢。这看起来就像我现在正在做的事情 :) 它工作正常,但是要产生类型安全的错觉,您必须手动将生成的所有者类中的引用从 Object 更改为真正的引用类。并且没有办法拥有真正的类型安全。这有点糟糕,我真的很想强制执行它,并认为可以通过 key/keyref 来实现 @kostja:您可以自定义 JAXB 映射以指定引用类。我已经用(未经测试的)如何执行此操作的示例更新了我的答案。【参考方案4】:JAXB 规范没有明确涵盖 key/keyref。然而,诸如EclipseLink MOXy(我是技术主管)之类的 JAXB 实现对此进行了扩展。我们即将发布的 2.2 版本提供了一种通过注解指定这种关系的方法(我将举一个例子)。以下是如何使用当前版本完成此操作的链接。
有关详细信息,请参阅:
JAXB - Example of following a keyref when unmarshalling更新
我希望得到一个包含在答案中的示例,但在我离开假期之前我已经没有时间了。以下是我们的设计文档中的一个示例,展示了这一概念:
http://wiki.eclipse.org/EclipseLink/DesignDocs/317962/Phase3#Relationship_Mapping_Support【讨论】:
谢谢,这看起来很有希望。我真的很期待你的榜样【参考方案5】:实例文档中没有特殊语法。只需要 keyref 节点匹配一个现存的 key 节点。验证会告诉你是否满足关键约束。
RE 你的代码:
我自己才刚刚开始涉足密钥,但我想我发现了你的错误 - aKey
应该如下所示:
<xs:key name="aKey">
<xs:selector xpath="owner" />
<xs:field xpath="@id" />
</xs:key>
此外 - 这是一个问题 - 键约束无法识别默认命名空间。您必须始终为selector
xpath 的每个部分加上您正在查找的元素的名称空间前缀。如果您没有命名空间前缀 - 很难,您需要添加一个。这是标准的限制。
【讨论】:
aah,这就是为什么不涉及属性的原因。我应用了您指出的更改,但 JAXB 不会生成任何能够从所有者访问引用元素的内容 - 整个 key/keyref 部分似乎对映射没有影响。也许还有其他我想念的东西吗? 也许我应该澄清一下我在上面的帖子中所说的话。我不知道 JAXB 是什么,但这不应该有任何区别 - 我想说的是说以上是关于XML Schema key/keyref - 如何使用它们?的主要内容,如果未能解决你的问题,请参考以下文章
Solr 6.1学习笔记-- 配置文件 managed-schema (schema.xml)
Solr 6.7学习笔记(02)-- 配置文件 managed-schema (schema.xml) - filter