質問

It is possible to add dynamic attribute in <element> for example I have a <A> element it have a fixed attribute name 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">

That means attribute mode is fixed and attr1,attr2,attr3 and attr4 depend on values of mode attribute

mode - Fixed attribute.

attr1,attr2,attr3 and attr4 - Dynamic attribute depend on value of mode

Please give me suitable example.

役に立ちましたか?

解決

To allow attributes depending on the contents of other attributes you need XSD 1.1 (or some XSD 1.0 extension such as Schematron). In XSD 1.1 you can use an assertion xs:assert where you declare the rules for the complex type using XPath.

To validate this instance:

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

You can use a XSD like the one below:

<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>

I placed the attributes for each mode in a separate attribute group. Your mode attribute is not actually fixed but can have two values, so I used an enumeration to restrict it to those two values.

The line that requires XSD 1.1 is the xs:assert line. The XPath expression is evaluated relative to the elements in the complex type. If the expression is true, it will validate.

Validation will fail otherwise. These A nodes will both fail validation:

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

Update: I added the not() clauses above, since the assertion was incomplete as you noted. Now this validates to false:

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

You can also use other criteria (it's a XPath subset), such as the number of attributes, for example if you have a lot of attributes and want to avoid a lot of not() clauses you can use:

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

that will restrict the total number of attributes to 3.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top