元素XSD架构中的动态属性

时间:2014-04-22 11:32:30

标签: xml xsd xsd-validation

可以在<element>中添加动态属性 例如,我有一个<A>元素,它有固定属性名称 mode

<A mode="ENABLE"> <!-- ENABLE or DISABLE-->

if mode is enable then it will add some more dynamic attribute in element `<A>`

like

<A mode="ENABLE" attr1="abc" attr2="xyz">

if mode is disable then it will like this .

<A mode="DISABLE" attr3="abc" attr4="xyz">

这意味着属性mode已修复且attr1,attr2,attr3 and attr4取决于mode属性的值

mode - 修正了属性。

attr1,attr2,attr3 and attr4 - 动态属性取决于mode

的值

请给我一个合适的例子。

1 个答案:

答案 0 :(得分:1)

要允许属性取决于其他属性的内容,您需要XSD 1.1(或某些XSD 1.0扩展,例如Schematron)。在XSD 1.1中,您可以使用断言xs:assert,使用XPath声明复杂类型的规则。

验证此实例:

<modes>
    <A mode="ENABLE"  attr1="abc" attr2="xyz" />
    <A mode="DISABLE" attr3="abc" attr4="xyz" />
</modes>

您可以使用如下所示的XSD:

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

    <xs:element name="modes">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="A" minOccurs="0" maxOccurs="unbounded"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:attributeGroup name="enabled-attributes">
        <xs:attribute name="attr1" type="xs:string" use="optional"/>
        <xs:attribute name="attr2" type="xs:string" use="optional"/>
    </xs:attributeGroup>

    <xs:attributeGroup name="disabled-attributes">
        <xs:attribute name="attr3" type="xs:string" use="optional"/>
        <xs:attribute name="attr4" type="xs:string" use="optional"/>
    </xs:attributeGroup>

    <xs:element name="A">
        <xs:complexType>
            <xs:attributeGroup ref="disabled-attributes"/>
            <xs:attributeGroup ref="enabled-attributes"/>
            <xs:attribute name="mode" use="required">
                <xs:simpleType>
                    <xs:restriction base="xs:NMTOKEN">
                        <xs:enumeration value="ENABLE" />
                        <xs:enumeration value="DISABLE" />
                    </xs:restriction>
                </xs:simpleType>
            </xs:attribute>
            <xs:assert test="(@mode='ENABLE'  and @attr1 and @attr2 and not(@attr3) and not(@attr4)) 
                          or (@mode='DISABLE' and @attr3 and @attr4 and not(@attr1) and not(@attr2))"/>
        </xs:complexType>
    </xs:element>
</xs:schema>

我将每个模式的属性放在一个单独的属性组中。您的mode属性实际上不是fixed,但可以有两个值,因此我使用枚举将其限制为这两个值。

需要XSD 1.1的行是xs:assert行。相对于复杂类型中的元素计算XPath表达式。如果表达式为true,它将验证。

否则验证将失败。这些A节点都将无法通过验证:

<modes>
    <A mode="DISABLE" attr1="fgs" attr4="hjs" />
    <A mode="ENABLE"  attr3="fgs" attr4="hjs" /> 
</modes>

更新:我在上面添加了not()条款,因为您注意到断言是不完整的。现在这验证为false:

<A mode="DISABLE" attr1="fgs" attr2="hjs" attr3="fgs" attr4="fgs"/>

您还可以使用其他条件(它是XPath子集),例如属性的数量,例如,如果您有很多属性并且想要避免使用的许多not()子句:< / p>

@mode='ENABLE' and @attr1 and @attr2 and count(@*) = 3

将属性总数限制为3.