XSD 分层键结构

XSD Hierarchical key structure

我想在 'AxisConfiguration' 上为每个 MotionControl 设置一个复合键并在 'PredefinedPositions' 中引用它们。 每个 MotionControl 的 Axis-Attribute 必须是唯一的。 这个想法是在 MotionControl 的 'Id' 和 AxisConfiguration 的 'Axis' 上设置一个键。 但是不行,现在不知道怎么实现。

<Root>
    <MotionControls>
        <MotionControl Id="1">
            <AxisConfigurations>
                <AxisConfiguration Axis="A0" MappedTo="X" Type="Linear" MaxVelocity="0" Offset="0"/>
                <AxisConfiguration Axis="A1" MappedTo="Y" Type="Linear" MaxVelocity="0" Offset="0"/>
            </AxisConfigurations>
        </MotionControl>
        <MotionControl Id="2">
            <AxisConfigurations>
                <AxisConfiguration Axis="A0" MappedTo="X" Type="Linear" MaxVelocity="0" Offset="0"/>
                <AxisConfiguration Axis="A1" MappedTo="Y" Type="Linear" MaxVelocity="0" Offset="0"/>
            </AxisConfigurations>
        </MotionControl>
    </MotionControls>
    <PredefinedPositions>
        <PredefinedPosition Name="PositionWorkingRoomHome" Order="Z,X,YA">
            <AxisPositions>
                <AxisPosition MotionControlId="1" Axis="A0" Value="1000"/>
                <AxisPosition MotionControlId="2" Axis="A0" Value="95000"/>
            </AxisPositions>
        </PredefinedPosition>
    </PredefinedPositions>
</Root>

 <xs:key name="PK_Axis">
  <xs:selector xpath=".//MotionControl"/>
  <xs:field xpath="@Id"/>
  <xs:field xpath="AxisConfigurations/AxisConfiguration/@Axis"/>
</xs:key>
<xs:keyref name="FK_Axis" refer="PK_Axis">
  <xs:selector xpath=".//AxisPosition"/>
  <xs:field xpath="@MotionControlId"/>
  <xs:field xpath="@Axis"/>
</xs:keyref>

验证结果:

Field "./AxisConfigurations/AxisConfiguration/@Axis" of identity constraint "PK_Axis" matches more than one value within the scope of its selector; fields must match

您没有告诉我们 key/keyref 约束出现在您的架构中的什么位置,这很关键。

但话说回来,我不确定这是否可以做到。当 key 和 keyref 出现在不同的元素上时会发生什么的规则非常复杂,我不确定我是对的,但我想不出办法。

使用 XSD 1.1 断言很容易,当然:在 Root 的声明中你可以断言

every $ap in .//AxisPosition satisfies 
  some $ac in .//AxisConfiguration satisfies 
    ($ap/@Axis = $ac/@Axis 
      and $ap/@MotionControlId = $ac/ancestor::MotionControl/@Id)

可能可以提高一点点效率:

    every $ap in .//AxisPosition satisfies 
      exists(MotionControls/MotionControl[@Id = $ap/MotionControl 
        and AxisConfigurations/AxisConfiguration/@Axis = $ap/@MotionControlId])