XML Schema 1.1:复杂的循环关系检查

时间:2015-02-11 09:14:52

标签: xml xslt xsd xpath-2.0 xsd-1.1

这将是一个复杂的问题,所以如果你不是非常熟悉XML Schema 1.1,你可能无法回答这个问题。

但是,此验证检查适用于XML Schema 1.1 Nerds:)

我有类似以下的XML:

<HTMLFile filename="N40139">
    <variant>2</variant>
    <overlayTitle>Job Cards</overlayTitle>
    <groups>
        <group>
            <groupTitleBtn>true</groupTitleBtn>
            <name>Removing thermostat</name>
            <src>03-8.2.12.15-10.13.35_MTU_20V8000M91</src>
            <steps>
                <step number="1">
                    <start>0</start>
                </step>
                <step number="2">
                    <start>03</start>
                </step>
                <step number="4">
                    <start>30</start>
                </step>
            </steps>
        </group>
        <group>
            <groupTitleBtn>true</groupTitleBtn>
            <name>Removing thermostat2</name>
            <src>03-8.2.12.15-10.13.35_MTU_20V8000M91</src>
            <steps>
                <step number="1">
                    <start>35</start>
                </step>
                <step number="2">
                    <start>45</start>
                </step>
                <step number="4">
                    <start>55</start>
                </step>
            </steps>
        </group>
    </groups>
</HTMLFile>

这是我现有的XML Schema来验证这个XML:

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" 
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
vc:minVersion="1.1">

<xs:element name="HTMLVideoMapper">
    <xs:complexType>
        <xs:sequence>

            <xs:element name="HTMLFile" minOccurs="0" maxOccurs="unbounded">
                <xs:complexType>
                    <xs:sequence>

                        <xs:element name="variant" minOccurs="1" maxOccurs="1">
                            <xs:simpleType>
                                <xs:restriction base="xs:integer">
                                    <xs:minInclusive value="1"/>
                                    <xs:maxInclusive value="3"/>
                                </xs:restriction>
                            </xs:simpleType>
                        </xs:element>

                        <xs:element name="overlayTitle" type="xs:string" minOccurs="0" maxOccurs="1"/>

                        <xs:element name="groups" minOccurs="1" maxOccurs="1">
                            <xs:complexType>
                                <xs:sequence>

                                    <xs:element name="group" minOccurs="1" maxOccurs="unbounded">
                                        <xs:complexType>
                                            <xs:sequence>

                                                <xs:element name="groupTitleBtn" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
                                                <xs:element name="name" type="xs:string" minOccurs="0" maxOccurs="1"/>
                                                <xs:element name="src" type="xs:string" minOccurs="1" maxOccurs="1"/>

                                                <xs:element name="steps" minOccurs="0" maxOccurs="1">
                                                    <xs:complexType>
                                                        <xs:sequence>
                                                            <xs:element name="step" minOccurs="1" maxOccurs="unbounded">
                                                                <xs:complexType>
                                                                    <xs:sequence>

                                                                        <xs:element name="start" minOccurs="1" maxOccurs="1">
                                                                            <xs:simpleType>
                                                                                <xs:restriction base="xs:integer">
                                                                                    <xs:minInclusive value="0"/>
                                                                                    <xs:maxInclusive value="999"/>
                                                                                </xs:restriction>
                                                                            </xs:simpleType>
                                                                        </xs:element>
                                                                        <xs:element name="src" type="xs:string" minOccurs="0" maxOccurs="1"/>
                                                                        <xs:element name="end" type="xs:string" minOccurs="0" maxOccurs="1"/>

                                                                    </xs:sequence>
                                                                    <xs:attribute name="number" type="xs:integer" use="required"/>
                                                                </xs:complexType>
                                                            </xs:element>
                                                        </xs:sequence>
                                                    </xs:complexType>
                                                </xs:element>

                                            </xs:sequence>

                                        </xs:complexType>
                                    </xs:element>

                                </xs:sequence>
                            </xs:complexType>
                        </xs:element>

                    </xs:sequence>
                    <xs:attribute name="filename" type="xs:string" use="required" />

                    <!-- overlayTitle is not allowed in variant 3 -->
                    <xs:assert test="(variant = 3 or overlayTitle)" />

                    <!-- groups/group/name is not allowed in variant 3 -->
                    <xs:assert test="(variant = 3 or groups/group/name)" />

                    <!-- groups/group/groupTitleBtn is not allowed in variant 3 -->
                    <xs:assert test="(variant = 3 or groups/group/groupTitleBtn)" />

                    <!-- groups/group/steps is not allowed in variant 3 -->
                    <xs:assert test="(variant = 3 or groups/group/steps)" />

                    <!-- in variant 3 only one group is allowed -->

                    <!-- if the group src in two groups is the same,
                    than the nested step-elements of the second group can 
                    not have a smaller value than the last nested step-element 
                    in the first group -->
                </xs:complexType>
            </xs:element>

        </xs:sequence>
    </xs:complexType>
</xs:element>

但是我需要检查三个限制。我自己成功构建了这个XML Schema,但现在我遇到了我的经验。我无法在XML Schema中创建最后两个注释作为代码。

这是任务

  1. 如果元素variant的值为3,则组的长度 - > group-elements只能是一个(一个元素/对象)。
  2. 如果variant的值为1或2,则必须循环遍历所有组 - &gt;组。在迭代时,我们将每个src的{​​{1}}值保存在临时变量中,以便我们可以检查下一个group src是否相同。如果是这样,我们需要遍历该组的所有步骤以及前一组的步骤。仅在第二组的第一个group step元素大于第一组的start step点时才有效。
  3. 如果start的值为1或2,则还需要遍历所有组 - &gt;组和嵌套的variant元素。 step元素的每个start元素必须大于之前的step step。因此,如果start具有属性step且其number="1"元素的值为3,则下一步的start只能有number="2" } start。这是必要的检查。

1 个答案:

答案 0 :(得分:1)

既然你不能解释你发现困难的是什么,除了一般的建议之外不可能提供任何东西(或者只是为你解决问题,这真的错过了重点)。

您的问题似乎主要是您不确定如何在XPath中表达您的约束。

让我们从你已经写过的简单开始吧。评论说&#34; overlayTitle不允许在变体3&#34;中,这似乎与断言(variant = 3 or overlayTitle)不兼容,这将允许

<HTMLFile filename="N40139">
  <variant>3</variant>
  <overlayTitle>Job Cards</overlayTitle>
  ...

因为XPath或是包容性的,而不是独占的。

我认为你的意思是
if (variant eq 3) then not(overlayTitle) else true()
not(variant eq 3 and overlayTitle)
variant ne 3 or not(overlayTitle)

类似于变体3的其他约束。

对于你尚未制定的三个限制,我建议你看看

  • count()函数(可以告诉您groups/group出现的次数

  • 量化表达式(可以检查groups/group的每个实例的条件,包括您描述的复杂实例)

  • 一般值比较(可以比较来自$ group1和$ group2的所有步骤,以查看$ group2的任何后代是否小于或等于$ group1的任何后代:$group2//step/start &lt;= $group1//step/start - - 当然,你想要否定这一点。

如果XML中的冗余更少,那么验证将更加简单,当然,如果您提供了变体1,2和3不同的名称。