[英]XML Schema: keyref to hierarchically lower element
我的XML结构如下:
ROOT
|_ SetOfBandC (*)
| |_ SetOfB (1)
| | |_ ElementB (*)
| | |_ ElementB__Key
| |_ SetOfC (1)
| |_ ElementC (*)
| |_ ElementC__Key
|_ ElementD (*)
|
|_ SetOfBandC__Key
|_ ElementD__Key
|
|_ ElementD->SetOfBandC__Keyref
|_ ElementD->ElementB__Keyref
在这种结构中我可以有多个SetOfBandC
以及多个ElementB
和ElementC
,但只有1个SetofB
和SetOfC
每个SetOfBandC
。
问题是, ElementD
有keyref引用特定SetOfBandC
,另一个引用ElementB
那一套的,但对于检查时,XML验证ElementD->ElementB__Keyref
的有效性。它仅仅查找在最后 SetOfBandC
,而不是在所有的它们,或者更好的是,在ElementD->SetOfBandC__Keyref
引用的ElementD->SetOfBandC__Keyref
。 所以,当ElementD->ElementB__Keyref
引用了ElementB
这是不是在最后SetOfBandC
,验证将无法正常工作。
这是我的ElementD->ElementB__Keyref
:
<xs:keyref name="ElementD->ElementB__Keyref" refer="tns:ElementB__Key ">
<xs:selector xpath="tns:ElementD" />
<xs:field xpath="@elementD_ref" />
</xs:keyref>
还有我的ElementB__Key
:
<xs:key name="ElementB__Key">
<xs:selector xpath="tns:ElementB" />
<xs:field xpath="@elemB_name" />
</xs:key>
其中tns是我的目标名称空间。 我想念什么?
PS:我的代码中的名称不同,并且没有->
。
我认为问题在于密钥的范围。
据我了解,一个节点不仅可以通过其节点名称进行全局标识,还可以通过所属的nffg的名称进行全局标识。 因此,这在全局上是一个复合键:策略指的是具有nffg名称和节点名称的节点。 但是,在当前模式中,策略中的keyRef
仅相互独立地引用这两个键,因此XML Schema不知道它们是一起使用的。
也许一种解决方法是使用全局唯一的节点名称,该名称由节点密钥加上nffg密钥(例如Nffg1-Node1
,并将其用作策略中的单个keyref。 如果还希望确保链接引用同一nffg中的源节点和目标节点,则可能需要为node
两个键定义:一个是策略keyRef
的全局keyRef
(在allNffgsAndPolicies
下),一个在allNffgsAndPolicies
本地(在下面) nffg
)的链接keyRef
。
一种稍有不同的替代方法是在节点中重复nffgName
属性,并将其与未更改的nodeName
属性一起用作节点的全局复合键(通过在键中使用两个xs:field
元素),可以在策略中使用它。 您应该能够确保节点的本地nffgname
属性与具有key
s和keyRef
的父级nffg匹配。
额外的问题 :它仍然不能解释为什么在原始实例和模式下,拒绝Node3
但接受其他值。 我本来希望在两个子树上存在的值上引发错误。 在规范中 ,跨子节点的冲突键已从节点表中删除,但是在这种情况下,像Node2
这样的键会因为在两个子Node3
都发生冲突而不会发生冲突,因为只有在第一个子树中出现的Node3
才发生冲突。 但是,这里发生了相反的情况,似乎只有最后一个孩子的节点表才被考虑包含在顶级节点表中。
如果您能够使用XML Schema 1.1,则以下内容无需修改XML文档或架构结构本身即可使用。
删除tns:policy
两个keyRef
而是对allNffgsAndPolicies
使用复杂类型的allNffgsAndPolicies
:
<xs:element name="allNffgsAndPolicies"> <xs:complexType> <xs:sequence> <!-- same content as in original schema --> </xs:sequence> <xs:assert test="every $i in tns:policy satisfies $i/@srcNode = tns:nffg/tns:nodes/tns:node/@nodeName and $i/@destNode = tns:nffg/tns:nodes/tns:node/@nodeName"/> </xs:complexType> <!-- other keys and keyRefs, only keep the first three --> </xs:element>
我可以在oXygen中成功测试:它可以验证原始文档,如果使用不存在的源或目标节点名称,则验证失败。
要激活XML Schema 1.1,请在xs:schema
元素中添加以下属性:
xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" vc:minVersion="1.1"
要加倍努力:如果最重要的是,您还想确保节点名称存在于策略使用nffgRef
引用的nffgRef
,则可以微调断言:
<xs:assert test="
every $i in tns:policy satisfies
$i/@srcNode = tns:nffg[@nffgName eq $i/@nffgRef]/tns:nodes/tns:node/@nodeName
and
$i/@destNode = tns:nffg[@nffgName eq $i/@nffgRef]/tns:nodes/tns:node/@nodeName"/>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.