元素XSD架构中的动态属性



可以在<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 的值

请给我举个合适的例子。

要根据其他属性的内容允许属性,您需要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()子句,则可以使用:

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

这将限制属性的总数为3。

最新更新