如何在嵌套元素标签上使用 keyref
How to use keyref on nested element tag
我要验证的内容:
<root xsi:noNamespaceSchemaLocation="test.xsd" xmlns="" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
<A>
<a id="ID-1"/>
<a id="ID-2"/>
</A>
<BBB>
<b>
<bb>
<bbb idref="ID-1"></bbb>
</bb>
</b>
</BBB>
</root>
这是我的 .xsd
文件:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
<xsd:element name="root">
<xsd:complexType>
<xsd:all minOccurs="1" maxOccurs="1">
<xsd:element name="A" type="myA"/>
<xsd:element name="BBB" type="myBBB"/>
</xsd:all>
</xsd:complexType>
<xsd:key name="myId">
<xsd:selector xpath="./A/a"/>
<xsd:field xpath="@id"/>
</xsd:key>
<xsd:keyref name="myIdref" refer="myId">
<xsd:selector xpath="./BBB/b/bb/bbb"/>
<xsd:field xpath="@idref"/>
</xsd:keyref>
</xsd:element>
<xsd:complexType name="myA">
<xsd:sequence minOccurs="1">
<xsd:element name="a">
<xsd:complexType>
<xsd:attribute name="id" type="xsd:ID"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="myBBB">
<xsd:sequence minOccurs="1">
<xsd:element name="b">
<xsd:complexType>
<xsd:all>
<xsd:element name="bb">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="bbb">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="idref" type="xsd:ID"></xsd:attribute>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:all>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
但是我得到:
element bbb: Schemas validity error : Element 'bbb', attribute 'idref':
Warning: No precomputed value available, the value was either invalid or something strange happend.
我尝试使用 xsd:NCName
但这并没有改变任何东西。如果我使用尚未定义的 ID-3
,我会得到
No match found for key-sequence ['ID-3'] of keyref 'myIdref'.
我想引用 A 元素的 id
和 bbb 元素的 idref
。我的xPath
错了吗?
我不应该为 keyRef
使用 xsd:ID
吗?
我猜你的问题是你希望 bbb
的元素属性类型是 xsd:IDREF
而不是 xsd:ID
。那么它将与您的 xsd:ID
定义相对应:
<xsd:attribute name="idref" type="xsd:IDREF"></xsd:attribute>
要添加的一个小修复是将 maxOccurs="unbounded"
属性添加到
...
<xsd:complexType name="myA">
<xsd:sequence minOccurs="1" maxOccurs="unbounded">
...
所以,整个 XSD 可以是
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
<xsd:element name="root">
<xsd:complexType>
<xsd:all minOccurs="1" maxOccurs="1">
<xsd:element name="A" type="myA"/>
<xsd:element name="BBB" type="myBBB"/>
</xsd:all>
</xsd:complexType>
<xsd:key name="myId">
<xsd:selector xpath="./A/a"/>
<xsd:field xpath="@id"/>
</xsd:key>
<xsd:keyref name="myIdref" refer="myId">
<xsd:selector xpath="./BBB/b/bb/bbb"/>
<xsd:field xpath="@idref"/>
</xsd:keyref>
</xsd:element>
<xsd:complexType name="myA">
<xsd:sequence minOccurs="1" maxOccurs="unbounded">
<xsd:element name="a">
<xsd:complexType>
<xsd:attribute name="id" type="xsd:ID"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="myBBB">
<xsd:sequence minOccurs="1">
<xsd:element name="b">
<xsd:complexType>
<xsd:all>
<xsd:element name="bb">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="bbb">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="idref" type="xsd:IDREF"></xsd:attribute>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:all>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
现在您的 XSD 应该验证您的 XML。
要完成这项工作,您甚至不需要
<xsd:key name="myId">
<xsd:selector xpath="./A/a"/>
<xsd:field xpath="@id"/>
</xsd:key>
<xsd:keyref name="myIdref" refer="myId">
<xsd:selector xpath="./BBB/b/bb/bbb"/>
<xsd:field xpath="@idref"/>
</xsd:keyref>
因为此功能隐含在 xsd:ID
/xsd:IDREF
代码中。 xs:keyref
更灵活,但在您的示例中,不需要。
您从模式处理器中看到一些非常糟糕的诊断:哪种软件会输出像 "or something strange happend" 这样的拼写错误消息?
这是 Saxon 的输出:
Processing file:/Users/mike/Desktop/temp/test.xml
Validation error on line 4 column 19 of test.xml:
FORG0001: In content of element <A>: The content model does not allow element <Q{}a> to
appear more than once.
See http://www.w3.org/TR/xmlschema-1/#cvc-complex-type clause 2.4
Validation error on line 4 column 19 of test.xml:
The field in constraint {myId} has no value
See http://www.w3.org/TR/xmlschema-1/#cvc-identity-constraint clause 4.2.1
Validation error on line 9 column 27 of test.xml:
XQDY0027: ID value 'ID-1' is not unique
See http://www.w3.org/TR/xmlschema-1/#cvc-id clause 2
让我们来看看这些。
第一个很容易通过在类型 myA
.
中添加 maxOccurs="unbounded" 来修复
当我们解决这个问题时,第二个错误就消失了:我认为 Saxon 对选择器中 XPath 表达式的计算假设数据是有效的,但它什么也没发现,因为这个假设不正确。
第三个错误是因为您将 bbb/@idref
声明为 xs:ID。如果将其更改为 xs:NCName,错误就会消失。
您需要决定是否要使用 ID/IDREF 机制或 key/keyref 机制进行参照完整性检查。两者都用是没有意义的。
我要验证的内容:
<root xsi:noNamespaceSchemaLocation="test.xsd" xmlns="" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
<A>
<a id="ID-1"/>
<a id="ID-2"/>
</A>
<BBB>
<b>
<bb>
<bbb idref="ID-1"></bbb>
</bb>
</b>
</BBB>
</root>
这是我的 .xsd
文件:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
<xsd:element name="root">
<xsd:complexType>
<xsd:all minOccurs="1" maxOccurs="1">
<xsd:element name="A" type="myA"/>
<xsd:element name="BBB" type="myBBB"/>
</xsd:all>
</xsd:complexType>
<xsd:key name="myId">
<xsd:selector xpath="./A/a"/>
<xsd:field xpath="@id"/>
</xsd:key>
<xsd:keyref name="myIdref" refer="myId">
<xsd:selector xpath="./BBB/b/bb/bbb"/>
<xsd:field xpath="@idref"/>
</xsd:keyref>
</xsd:element>
<xsd:complexType name="myA">
<xsd:sequence minOccurs="1">
<xsd:element name="a">
<xsd:complexType>
<xsd:attribute name="id" type="xsd:ID"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="myBBB">
<xsd:sequence minOccurs="1">
<xsd:element name="b">
<xsd:complexType>
<xsd:all>
<xsd:element name="bb">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="bbb">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="idref" type="xsd:ID"></xsd:attribute>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:all>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
但是我得到:
element bbb: Schemas validity error : Element 'bbb', attribute 'idref':
Warning: No precomputed value available, the value was either invalid or something strange happend.
我尝试使用 xsd:NCName
但这并没有改变任何东西。如果我使用尚未定义的 ID-3
,我会得到
No match found for key-sequence ['ID-3'] of keyref 'myIdref'.
我想引用 A 元素的 id
和 bbb 元素的 idref
。我的xPath
错了吗?
我不应该为 keyRef
使用 xsd:ID
吗?
我猜你的问题是你希望 bbb
的元素属性类型是 xsd:IDREF
而不是 xsd:ID
。那么它将与您的 xsd:ID
定义相对应:
<xsd:attribute name="idref" type="xsd:IDREF"></xsd:attribute>
要添加的一个小修复是将 maxOccurs="unbounded"
属性添加到
...
<xsd:complexType name="myA">
<xsd:sequence minOccurs="1" maxOccurs="unbounded">
...
所以,整个 XSD 可以是
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
<xsd:element name="root">
<xsd:complexType>
<xsd:all minOccurs="1" maxOccurs="1">
<xsd:element name="A" type="myA"/>
<xsd:element name="BBB" type="myBBB"/>
</xsd:all>
</xsd:complexType>
<xsd:key name="myId">
<xsd:selector xpath="./A/a"/>
<xsd:field xpath="@id"/>
</xsd:key>
<xsd:keyref name="myIdref" refer="myId">
<xsd:selector xpath="./BBB/b/bb/bbb"/>
<xsd:field xpath="@idref"/>
</xsd:keyref>
</xsd:element>
<xsd:complexType name="myA">
<xsd:sequence minOccurs="1" maxOccurs="unbounded">
<xsd:element name="a">
<xsd:complexType>
<xsd:attribute name="id" type="xsd:ID"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="myBBB">
<xsd:sequence minOccurs="1">
<xsd:element name="b">
<xsd:complexType>
<xsd:all>
<xsd:element name="bb">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="bbb">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="idref" type="xsd:IDREF"></xsd:attribute>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:all>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
现在您的 XSD 应该验证您的 XML。
要完成这项工作,您甚至不需要
<xsd:key name="myId">
<xsd:selector xpath="./A/a"/>
<xsd:field xpath="@id"/>
</xsd:key>
<xsd:keyref name="myIdref" refer="myId">
<xsd:selector xpath="./BBB/b/bb/bbb"/>
<xsd:field xpath="@idref"/>
</xsd:keyref>
因为此功能隐含在 xsd:ID
/xsd:IDREF
代码中。 xs:keyref
更灵活,但在您的示例中,不需要。
您从模式处理器中看到一些非常糟糕的诊断:哪种软件会输出像 "or something strange happend" 这样的拼写错误消息?
这是 Saxon 的输出:
Processing file:/Users/mike/Desktop/temp/test.xml
Validation error on line 4 column 19 of test.xml:
FORG0001: In content of element <A>: The content model does not allow element <Q{}a> to
appear more than once.
See http://www.w3.org/TR/xmlschema-1/#cvc-complex-type clause 2.4
Validation error on line 4 column 19 of test.xml:
The field in constraint {myId} has no value
See http://www.w3.org/TR/xmlschema-1/#cvc-identity-constraint clause 4.2.1
Validation error on line 9 column 27 of test.xml:
XQDY0027: ID value 'ID-1' is not unique
See http://www.w3.org/TR/xmlschema-1/#cvc-id clause 2
让我们来看看这些。
第一个很容易通过在类型 myA
.
当我们解决这个问题时,第二个错误就消失了:我认为 Saxon 对选择器中 XPath 表达式的计算假设数据是有效的,但它什么也没发现,因为这个假设不正确。
第三个错误是因为您将 bbb/@idref
声明为 xs:ID。如果将其更改为 xs:NCName,错误就会消失。
您需要决定是否要使用 ID/IDREF 机制或 key/keyref 机制进行参照完整性检查。两者都用是没有意义的。