根据 xsd 1.1 中的属性和元素定义断言

Defining assertions depending on both attributes and elements in xsd 1.1

我需要在我的 XSD 架构中定义以下情况。这是我的例子 XML:

<initialization>

  <stat name="SelfActualization" range="" init="" tickValue="" colorR="" colorG="" colorB=""/>
  <stat name="Social" range="" init="" tickValue="" colorR="" colorG="" colorB=""/>

  <staticAction name="Study" >
    <SelfActualization reqPoints="0" gainedPoints="0" />
    <Social reqPoints="0" gainedPoints="0" />
  </staticAction>

  <staticAction name="Greetings" >
    <SelfActualization reqPoints="0" gainedPoints="0" />
    <Social reqPoints="0" gainedPoints="0" />
  </staticAction>

  <staticAction name="Eat" >
    <SelfActualization reqPoints="0" gainedPoints="0" />
    <Social reqPoints="0" gainedPoints="0" />
  </staticAction>

</initialization>

我需要的第一个断言:我可以根据需要定义任意数量的 "stat" 元素(在本例中只有 2 个),并且我已经设法获得了这种行为。我不知道该怎么做:在我的任何 "StaticActions" 中,我需要重新命名上面定义的所有 "stats" (作为元素,这是我已经通过 xs:anyType 元素,但我需要一个断言来控制名称对应),并且按照它们在开始时定义的相同顺序。 正如我们在示例中看到的那样,确实 "SelfActualization" 和 "Social" 在我所有的 StaticActions 中都以正确的顺序存在。如果之前没有定义另一个"stat",或者缺少定义的"stats"之一,或者顺序错误,则必须拒绝XML。到目前为止,我的 XSD 看起来像这样:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="initialization" type="initializationType" />

<xs:complexType name="initializationType">
  <xs:sequence>
    <xs:element  minOccurs="0" maxOccurs="unbounded" ref="stat"/>
    <xs:element  minOccurs="0" maxOccurs="unbounded" ref="staticAction"/>
  </xs:sequence>
</xs:complexType>

<xs:element name="staticAction" type="StaticActionType"/>

<xs:complexType name="StaticActionType">
    <xs:complexContent>
        <!-- Base is anyType -->
        <xs:extension base="xs:anyType">
            <xs:attribute name="name" type="xs:string"/>
            <!-- Check that every "dynamic" child has the two integer attributes and no other attributes -->
            <xs:assert test="every $element in ./* satisfies 
                ($element[
                    matches(@reqPoints, '^[+-]?\d+$') and
                    matches(@gainedPoints, '^[+-]?\d+$') and
                    count(@*=2)])"/>
            <!-- Test that there is no content in staticAction nor in the "dynamic" nodes -->
            <xs:assert test="matches(string(.), '^\s*$')"/>
        </xs:extension>
    </xs:complexContent>
</xs:complexType>

我需要的第二个断言:我使用简单的 xs:sequence 在 xsd 模式的开头声明了 StaticActions,因为我确实需要一定数量的 StaticActions 并按特定顺序进行。在那里,我想确保这些 staticActions 具有正确的名称(通过 staticAction 定义中指定的 "name" 属性):例如,我想要 "Study" "Greetings" 和 "Eat" 。所以我需要通过一个简单的断言来检查我的 XML 中的所有 3 个 "Study"、"Greetings" 和 "Eat" 都在那里。

编辑:最后一点是:除了如下例所示的动态元素之外,我的 staticAction 还需要包含 2 个静态元素:

<initialization>

  <stat name="SelfActualization" range="" init="" tickValue="" colorR="" colorG="" colorB=""/>
  <stat name="Social" range="" init="" tickValue="" colorR="" colorG="" colorB=""/>

  <staticAction name="Study" >
    <SelfActualization reqPoints="0" gainedPoints="0" />
    <Social reqPoints="0" gainedPoints="0" />

    <RequiredAction action="string" cardinality="int" />
    <SuccessLikelihood likelihood="int" />
  </staticAction>

因此我需要修改 "StaticAction" 的定义并修改一些检查 staticAction 的所有子项的断言。

对于第一个要求,您可以在 initializationType 中使用以下断言:

<xs:assert test="every $staticAction in ./staticAction satisfies deep-equal(data($staticAction/*/name()), data(./stat/@name)) "/>

这确保每个 staticAction 包含节点名称与 stat 元素的属性名称相同且顺序相同的子节点。

对于第二个要求,您可以使用这个简单的断言,假设顺序不重要并且值可以重复:

<xs:assert test="every $staticAction in ./staticAction satisfies $staticAction/@name = ('Study', 'Greetings', 'Eat') "/>

这也可以在XSD中建模:

<xs:attribute name="name">
    <xs:simpleType>
        <xs:restriction base="xs:string">
            <xs:enumeration value="Study"/>
            <xs:enumeration value="Greetings"/>
            <xs:enumeration value="Eat"/>
        </xs:restriction>
    </xs:simpleType>
</xs:attribute>

否则,如果值不能重复但必须出现,您可以使用三个不同的断言来确保每个值都存在一次(例如:count(./staticAction[@name='Eat']) = 1)。