我正在尝试使用xs:key和xs:keyref定义在XML模式上定义一些外键约束.我希望文档的结构按以下方式分层:
<?xml version="1.0" encoding="UTF-8"?>
<tns:root xmlns:tns="http://www.example.org/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.org/ SampleSchema.xsd ">
<parent parentKey="parent1">
<child childKey="child1"/>
<child childKey="child2"/>
</parent>
<parent parentKey="parent2">
<child childKey="child1"/>
<child childKey="child2"/>
</parent>
<referrer parentRef="parent1" childRef="child2"/>
</tns:root>
Run Code Online (Sandbox Code Playgroud)
每个父节点都有一个(全局)唯一键,由parentKey定义.每个子项都有由childKey定义的键,但是childKey仅在其包含父项的范围内是唯一的.
然后是一个引用者列表,其中包含对特定父和子的外键引用.
我可以根据需要定义键,只需将它们放在正确的元素上:根元素上的parentKey约束和父元素上的childKey约束.我也可以毫无困难地将keyref定义为parentKey.
尝试为childKey定义keyref时出现问题.我尝试在root元素上定义一个简单的keyref到childKey,但是这不起作用,因为我看不到只选择正确父子树下的子元素.(Eclipse验证器,至少,总是简单地验证文档中最后一个父子树的内容......).
然后我尝试定义一个复合键(在root上),用:
如果父项下定义了多个子项,则会失败.这是基于XSD 1.1规范 3.11.4节第3项的正确行为,该规则指出密钥必须与每个字段定义最多匹配一个节点.
重申一下:如果我强迫childKeys全球独一无二,这很容易实现; 困难在于引用本地唯一的childKeys.
任何XSD大师都有想法吗?
作为参考,这是一个示例XSD,注释掉了一个失败的childKey keyref:
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/" xmlns:tns="http://www.example.org/" elementFormDefault="unqualified">
<element name="root">
<complexType>
<sequence>
<element name="parent" maxOccurs="unbounded" minOccurs="1">
<complexType>
<sequence>
<element name="child" maxOccurs="unbounded" minOccurs="1">
<complexType>
<attribute name="childKey" type="string" use="required"/>
</complexType>
</element>
</sequence>
<attribute name="parentKey" type="string" use="required"/>
</complexType>
<key name="childKeyDef">
<selector xpath="child"/>
<field xpath="@childKey"/>
</key>
</element>
<element name="referrer" maxOccurs="unbounded" minOccurs="1">
<complexType>
<attribute name="parentRef" type="string"/>
<attribute name="childRef" type="string"/>
</complexType>
</element>
</sequence>
</complexType>
<key name="parentKeyDef">
<selector xpath="parent"/>
<field xpath="@parentKey"/>
</key>
<keyref name="parentKeyRef" refer="tns:parentKeyDef">
<selector xpath="referrers"/>
<field xpath="@parentRef"/>
</keyref>
<!-- <keyref name="childKeyRef" refer="tns:childKeyDef">-->
<!-- <selector xpath="referrers"/>-->
<!-- <field xpath="@childRef"/>-->
<!-- </keyref>-->
</element>
</schema>
Run Code Online (Sandbox Code Playgroud)
如何从孩子中引用父母呢?即使有很多子项,也只会有一个父项,并且组合 (parent,child) 创建一个全局唯一的键,即使子键仅在其父项中是唯一的:
<key name="childKeyDef">
<selector xpath="child"/>
<field xpath="@childKey"/>
<field xpath="../@parentKey"/>
</key>
Run Code Online (Sandbox Code Playgroud)
这在 xmllint 中不起作用,即使规范似乎没有明确禁止字段这样做 - 仅适用于选择器:3.11.4, (2) 表示选择器不能是祖先(它只能是上下文节点或后代。)
啊,这是棺材上的钉子(查看具体语法):允许的 XPath 表达式非常有限,并且根本不包括“..” http://www.w3.org/TR/xmlschema-1/# c-字段-xpaths
所以,抱歉,这并不能回答你的问题,但也许它会给你一些想法。