XML Schema:层次结构降低元素的keyref

时间:2017-01-17 11:13:10

标签: xml validation xsd key keyref

我的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以及多个ElementBElementC,但每个{{1}只有SetofBSetOfC }}。

问题是SetOfBandC有一个引用特定ElementD的keyref,另一个引用该集合的SetOfBandC,但是在检查ElementB时是XML Validator它的有效性仅在 last ElementD->ElementB__Keyref中搜索,而不是在所有这些中搜索,或者更好地在SetOfBandC引用的那个中搜索。 因此,当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

其中tns是我的目标命名空间。我错过了什么?

PS:我的代码中的名称不同,其中没有<xs:key name="ElementB__Key"> <xs:selector xpath="tns:ElementB" /> <xs:field xpath="@elemB_name" /> </xs:key>

2 个答案:

答案 0 :(得分:1)

我认为问题在于密钥的范围。

据我了解,节点不仅通过其节点名称进行全局标识,而且还通过属于名称进行全局标识。因此,这是一个复合键:策略是指具有nffg名称的节点以及节点名称。在当前架构中,策略中的keyRef仅相互独立地引用这两个键,因此XML Schema不知道它们是一起的。

可能一种方法是使用全局唯一的节点名称,该节点名称使用nffg键作为前缀,例如Nffg1-Node1,并将其用作策略中的单个keyref。如果您还想确保链接引用同一个nffg 中的源节点和目标节点,则可能需要node的两个关键定义:一个用于策略的全局{{1 s(在keyRef下),一个本地的nffg(在allNffgsAndPolicies下),用于链接nffg

稍微不同的替代方法是在节点中重复keyRef属性,并将其与未更改的nffgName属性一起用作节点的全局复合键 - 使用两个nodeName密钥中的元素 - 您可以在策略中使用。您应该能够确保节点的本地xs:field属性与父级nffg的属性匹配nffgnamekey

加分问题:它仍然无法解释为什么在原始实例和架构中,keyRef被拒绝但其他值被接受。我原以为错误会抛出两个子树上的值。在specification中,子节点之间的冲突密钥将从节点表中删除,但在这种情况下,像Node3这样的密钥会在两个子树上发生冲突,但不会与Node2冲突。仅出现在第一个子树中。相反的情况发生在此处,并且只有最后一个子节点表似乎被认为包含在顶级节点表中。

答案 1 :(得分:1)

如果您能够使用XML Schema 1.1,则以下内容不应修改XML文档或架构结构本身。

  • 删除keyRef

  • tns:policy个{}
  • 相反,在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的策略引用的nffg中,您可以对该断言进行微调:

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