Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
856 views
in Technique[技术] by (71.8m points)

xml - Conditional required elements in an XSD

I have a requirement for an xml schema which accepts either a request with the customer or with the customer id. If the customer Id is 0 then we need the customer data, if it's > 0 then customer data is optional (They can submit ammendements). My XSD looks like this at the moment;

<xs:complexType>


    <xs:any>
      <xs:element name="UserID" type="xs:string" minOccurs="1"/>
      <xs:element name="Password" type="xs:string" minOccurs="1"/>
      <xs:element name="ReferenceNumber" type="xs:string" minOccurs="0"  maxOccurs="1"/>
      <xs:element name="CustomerId" minOccurs="1" maxOccurs="1" type="xs:integer"/>
      <xs:element ref="WhereSigned"/>
      <xs:element name="ContactName" type="xs:string" minOccurs="0"  maxOccurs="1"/>
      <xs:element name="ContactTelephone" type="xs:string" minOccurs="0"  maxOccurs="1"/>
      <xs:element name="ContactFax" type="xs:string" minOccurs="0"  maxOccurs="1"/>
      <xs:element name="ContactEmail" type="xs:string" minOccurs="0"  maxOccurs="1"/>
      <xs:element ref="MainApplicant"  maxOccurs="1"/>
      <xs:element ref="JointApplicant" minOccurs="0" maxOccurs="1"/>
      <xs:element ref="Asset" minOccurs="0" maxOccurs="1"/>
    </xs:any>


</xs:complexType>

I need something a bit like this... (I wish it were this simple but alas not..)

<xs:complexType>
  <xs:choice>

    <xs:any>
      <xs:element name="UserID" type="xs:string" minOccurs="1"/>
      <xs:element name="Password" type="xs:string" minOccurs="1"/>
      <xs:element name="ReferenceNumber" type="xs:string" minOccurs="0"  maxOccurs="1"/>
      <xs:element name="CustomerId" minOccurs="1" maxOccurs="1">
        <xs:simpleType>
          <xs:restriction base="xs:integer">
            <xs:minInclusive value="0"/>
            <xs:maxInclusive value="0"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:element>
      <xs:element ref="WhereSigned"/>
      <xs:element name="ContactName" type="xs:string" minOccurs="0"  maxOccurs="1"/>
      <xs:element name="ContactTelephone" type="xs:string" minOccurs="0"  maxOccurs="1"/>
      <xs:element name="ContactFax" type="xs:string" minOccurs="0"  maxOccurs="1"/>
      <xs:element name="ContactEmail" type="xs:string" minOccurs="0"  maxOccurs="1"/>
      <xs:element ref="MainApplicant"  maxOccurs="1"/>
      <xs:element ref="JointApplicant" minOccurs="0" maxOccurs="1"/>
      <xs:element ref="Asset" minOccurs="0" maxOccurs="1"/>
    </xs:any>

    <xs:any>
      <xs:element name="UserID" type="xs:string" minOccurs="1"/>
      <xs:element name="Password" type="xs:string" minOccurs="1"/>
      <xs:element name="ReferenceNumber" type="xs:string" minOccurs="0"  maxOccurs="1"/>
      <xs:element name="CustomerId" minOccurs="1" maxOccurs="1">
        <xs:simpleType>
          <xs:restriction base="xs:integer">
            <xs:minInclusive value="1"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:element>
      <xs:element ref="Asset" minOccurs="0" maxOccurs="1"/>
    </xs:any>

   </xs:choice>
</xs:complexType>

Any XSD experts (do these even exist?!) who are able to lend a hand or some advice?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is possible in XSD 1.1; below is a simplified example, which assumes MainApplicant and WhereSigned are mandatory when CustomerId is equal to zero.

<?xml version="1.0" encoding="utf-8" ?>
<!-- XML Schema generated by QTAssistant/XSD Module (http://www.paschidev.com) -->
<xsd:schema elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xtm="http://paschidev.com/schemas/metadata/xtm">
    <xsd:complexType name="Request">
        <xsd:all>
            <xsd:element name="UserID" type="xsd:string" />
            <xsd:element name="Password" type="xsd:string" />
            <xsd:element name="ReferenceNumber" type="xsd:string" minOccurs="0"/>
            <xsd:element name="CustomerId" type="xsd:integer"/>
            <xsd:element ref="WhereSigned" minOccurs="0"/>
            <xsd:element name="ContactName" type="xsd:string" minOccurs="0" />
            <xsd:element name="ContactTelephone" type="xsd:string" minOccurs="0" />
            <xsd:element name="ContactFax" type="xsd:string" minOccurs="0" />
            <xsd:element name="ContactEmail" type="xsd:string" minOccurs="0" />
            <xsd:element ref="MainApplicant" minOccurs="0" />
            <xsd:element ref="JointApplicant" minOccurs="0" />
            <xsd:element ref="Asset" minOccurs="0" />
        </xsd:all>
        <xsd:assert test="CustomerId[. eq 0] and WhereSigned and MainApplicant or CustomerId[. ne 0]" />
    </xsd:complexType>
    <xsd:element name="Asset"/>
    <xsd:element name="MainApplicant" />
    <xsd:element name="JointApplicant" />
    <xsd:element name="WhereSigned" />  
</xsd:schema>

Minimum valid XML, when CustomerId is zero:

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Request">
    <UserID>UserID1</UserID>
    <Password>asodasqZX==</Password>
    <CustomerId>0</CustomerId>
    <WhereSigned/>
    <MainApplicant/>
</root>

When CustomerId is non-zero, then this is the minimum XML:

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Request">
    <UserID>UserID1</UserID>
    <Password>asodasqZX==</Password>
    <CustomerId>1</CustomerId>
</root>

The conditional can be easily controlled (see the @test expression); add regular XSD constraints as needed (e.g. if your CustomerId needs to be greater than or equal to zero, then make it nonNegativeInteger, etc.)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...