1

我的 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以及多个ElementBand ,但每个ElementC只有 1 个SetofBand 。SetOfCSetOfBandC

问题是ElementD有一个 keyref 引用一个特定的SetOfBandC和另一个引用ElementB该集合的一个,但是 XML Validator 在检查ElementD->ElementB__Keyref' 的有效性时它只搜索最后一个 SetOfBandC,而不是所有的,或者更好的是,在一个被引用ElementD->SetOfBandC__Keyref。因此,当ElementD->ElementB__Keyref引用ElementB不在 last 中的an 时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:我的代码中的名称不同,其中没有->

4

2 回答 2

1

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

据我了解,一个节点不仅可以通过其节点名称来全局识别,还可以通过nffg所属的名称来识别。因此,这在全局上是一个复合键:策略指的是具有 nffg 名称和节点名称的节点。然而,在当前模式keyRef中,策略中的 s 仅引用彼此独立的这两个键,因此 XML 模式不知道它们一起出现。

也许一种出路是使用全局唯一的节点名称,该名称由在节点键前面加上 nffg 键组成,例如Nffg1-Node1,并将其用作策略中的单个 keyref。如果您还想确保链接指向同一 nffg中的源节点和目标节点,您可能需要两个关键定义node:一个全局用于策略keyRefs(下allNffgsAndPolicies),一个本地到 nffg(下nffg)用于链接keyRefs.

稍微不同的替代方法是在节点中重复该nffgName属性,并将其与未更改的nodeName属性一起用作节点的全局复合键——通过使用键中的两个xs:field元素——您可以在策略中使用。您应该能够确保节点的本地属性与带有s 和snffgname的父 nffg的本地属性相匹配。keykeyRef

奖励问题:它仍然没有解释为什么原始实例和模式Node3被拒绝但其他值被接受。我本来希望在两个子树上都存在的值上引发错误。在规范中,从节点表中删除了跨子节点的冲突键,但是在这种情况下,一个类似的键Node2会发生冲突,因为它在两个子树上都存在,但不是Node3因为它只出现在第一个子树中。然而,这里发生了相反的情况,似乎只有最后一个孩子的节点表被考虑包含在顶级节点表中。

于 2017-01-18T07:32:11.083 回答
1

如果您能够使用 XML Schema 1.1,那么以下内容应该可以在不修改 XML 文档或模式结构本身的情况下工作。

  • 删除两个keyRefs fortns:policy

  • 相反,在复杂类型中使用断言 for 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"

加倍努力:如果除此之外,您还想确保节点名称存在于策略引用的 nffg 中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"/>
于 2017-01-18T15:34:30.630 回答