xsd针对同一文档的不同部分验证xml变量

时间:2016-06-27 16:07:39

标签: xml xsd xsd-validation xsd-1.1

不确定这是否可行,但我想用xsd(版本1.1)验证xml文档中使用的变量是在同一文档的不同部分中指定的。

我的文档的一部分如下所示:

<bf:Variables>
    <bf:Variable name="myVariable">
        ...
    </bf:Variable>
    <bf:Variable name="AnotherOne">
        ...
    </bf:Variable>
    <bf:Variable name="evenMore">
        ...
    </bf:Variable>
    ...
</bf:Variables>

然后在同一个文档中,我有另一个看起来像这样的部分:

<bf:Restrictions>
    <bf:Restriction variable="myVariable" operator="=">
        <bf:Value>True</bf:Value>
    </bf:Restriction>
    <bf:Restriction variable="AnotherOne" operator="=">
        <bf:Value>False</bf:Value>
    </bf:Restriction>
    <bf:Restriction variable="ThirdVariable" operator="=">
        <bf:Value>False</bf:Value>
    </bf:Restriction>
</bf:Restrictions>

我的目标是检查限制部分中使用的变量是否在变量部分中指定。 在上面的示例中,“ThirdVariable”应该无法通过xsd检查,因为它在“变量”部分中不存在。

1 个答案:

答案 0 :(得分:0)

这可以通过几种方式解决,有些方面比其他方式更好


使用断言的解决方案 - 但不是很好......

在XSD 1.1中,您可以使用<xs:assert>执行此操作。理想情况下,断言将放在引用元素<Restriction>上,这样就可以明确<Restriction>无效。

但是,由于<xs:assert>无法访问树中较高的值,因此<xs:assert>必须足够高才能使<Restriction><Variable>位于其中范围(儿童)。这样就可以了,但是现在你必须写一个通用规则,如果它失败将无法提供太多反馈 - 它只会告诉你一个或多个<Restriction>无效。

下面是一个非常快速的样本来展示。

Visual representation of the schema made with Liquid XML Studio

<?xml version="1.0" encoding="utf-8" ?>
<!--Created with Liquid XML 2017 Developer Bundle Edition 15.0.0.0 (https://www.liquid-technologies.com)-->
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="base">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="var" type="xs:string" minOccurs="0" maxOccurs="unbounded" />
                <xs:element name="Usage" type="xs:string" minOccurs="0" maxOccurs="unbounded" />
            </xs:sequence>
            <xs:assert test="count(Usage[not(./text() = ../var/text())]) = 0" />
        </xs:complexType>
    </xs:element>
</xs:schema>

示例XML

<?xml version="1.0" encoding="utf-8"?>
<!-- Created with Liquid XML 2016 Developer Bundle Edition 14.1.4.6649 (https://www.liquid-technologies.com) -->
<base xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Schema.xsd">
    <var>var1</var>
    <var>var2</var>
    <var>var4</var>
    <Usage>var1</Usage>
    <Usage>var2</Usage>
    <Usage>var3</Usage><!-- INVALID -->
</base>

错误消息(通过Saxon)

(10:7)关键cvc-assertion:断言评估('count(用法[not(./ text()= ../ var / text())])= 0')元素'base'on模式类型'#AnonType_base'未成功。





使用Key / KeyRef的更好解决方案

这是XSD 1.0友好的,效果很好。它告诉您是否有重复的可变名称,以及变量名称引用是否无效,指出实际问题。

Visual representation of the key keyref schema from Liquid XML Studio

<?xml version="1.0" encoding="utf-8" ?>
<!--Created with Liquid XML 2017 Developer Bundle Edition 15.0.0.0 (https://www.liquid-technologies.com)-->
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="base">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="Variables">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="Variable" minOccurs="0" maxOccurs="unbounded">
                                <xs:complexType>
                                    <xs:simpleContent>
                                        <xs:extension base="xs:string">
                                            <xs:attribute name="name" type="xs:string" />
                                        </xs:extension>
                                    </xs:simpleContent>
                                </xs:complexType>
                            </xs:element>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
                <xs:element name="Restrictions">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="Restriction" minOccurs="0" maxOccurs="unbounded">
                                <xs:complexType>
                                    <xs:simpleContent>
                                        <xs:extension base="xs:string">
                                            <xs:attribute name="variable" type="xs:string" />
                                        </xs:extension>
                                    </xs:simpleContent>
                                </xs:complexType>
                            </xs:element>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
        <xs:key name="VarDef">
            <xs:selector xpath="./Variables/Variable" />
            <xs:field xpath="@name" />
        </xs:key>
        <xs:keyref name="VarRef" refer="VarDef">
            <xs:selector xpath="./Restrictions/Restriction" />
            <xs:field xpath="@variable" />
        </xs:keyref>
    </xs:element>
</xs:schema>

示例XML

<?xml version="1.0" encoding="utf-8"?>
<!-- Created with Liquid XML 2017 Developer Bundle Edition 15.0.0.0 (https://www.liquid-technologies.com) -->
<base xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="SchemaKeyRef.xsd">
    <Variables>
        <Variable name="var1"></Variable>
        <Variable name="var2"></Variable>
        <Variable name="var3"></Variable>
    </Variables>
    <Restrictions>
        <Restriction variable="var1">string</Restriction>
        <Restriction variable="var2">string</Restriction>
        <Restriction variable="UNKNOWN">string</Restriction>
    </Restrictions>
</base>

现在生成的错误更加具体,使得调试问题变得更加容易。

来自.Net的错误(行号是错误的限制)

(12:10)错误'VarDef'Keyref中的键序列'UNKNOWN'无法引用某个键。

Saxon的错误(行号是包含元素库)

(14:7)严重的cvc-identity-constraint.4.3:找不到元素'base'的标识约束的值为'UNKNOWN'的键'VarRef'。