0

I have an XML doc that includes a repeating series of addresses whose actual content depends on the value of an included enumeration. I suppose this is a type of "tagged union" [or "discriminated union"?]:

{
<AddressList>
    <Address>
        <AddressType type="addressEnum" fixed="CanadianAddress"/>
        <AddressValue>
            <Street type="textstring">123 Yonge Street</Street>
            <Province type="provinceEnum" value="Ontario"/>
            <PostalCode type="postalCodeType" value="M1N 2O3"/>
        </AddressValue>
    </Address>
    <Address>
        <AddressType type="addressEnum" fixed="USAddress"/>
        <AddressValue>
            <Street type="textstring">456 Front Street</Street>
            <State type="stateEnum" value="New York"/>
            <ZipCode type="zipCodeType" value="12345"/>
        </AddressValue>
    </Address>
</AddressList>
}

I'm unclear how to express an XML schema [i.e. XSD] for the above XML. Do I need an empty 'AddressType' which both 'CanadianAddressType' and 'USAddressType' would extend? If I have 50 AddressTypes, would I require 50 such extensions?

NOTE: In case it's not obvious, the elements of a USAddress cannot appear following a CanadianAddress enumeration. Likewise, the elements of a CanadianAddress cannot appear following a USAddress enumeration.

badfd
  • 63
  • 7

1 Answers1

1

It is possible by using alternative components of XSD 1.1. Then you will be able to apply type for <AddressValue> node in depends on fixed attribute value of AddressType element, so

<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="http://tempuri.org/XMLSchema.xsd"
    elementFormDefault="qualified"
    xmlns="http://tempuri.org/XMLSchema.xsd"
    xmlns:mstns="http://tempuri.org/XMLSchema.xsd"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
    vc:minVersion="1.1">
  <xs:element name="AddressList" >
    <xs:complexType>
      <xs:sequence>
        <xs:element name="Address" minOccurs="1" maxOccurs="unbounded">
          <xs:complexType>
            <xs:sequence minOccurs="1" maxOccurs="1">
              <xs:element name="AddressType" type="AddressTypeTag"/>
              <xs:element name="AddressValue" type="USAddressValue">
                <xs:alternative test="../AddressType/@fixed='CanadianAddress'" type="CanadianAddressValue"/>
                <xs:alternative test="../AddressType/@fixed='USAddress'" type="USAddressValue"/>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:complexType name="CanadianAddressValue">
    <xs:sequence minOccurs="1" maxOccurs="1">
      <xs:element name="Street" type="StreetValue"/>
      <xs:element name="Province" type="TypeAndValue"/>
      <xs:element name="PostalCode" type="TypeAndValue"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="USAddressValue">
    <xs:sequence minOccurs="1" maxOccurs="1">
      <xs:element name="Street" type="StreetValue"/>
      <xs:element name="State" type="TypeAndValue"/>
      <xs:element name="ZipCode" type="TypeAndValue"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="StreetValue">
    <xs:simpleContent>
      <xs:extension base="xs:string">
        <xs:attribute name="type" type="xs:string"/>
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>
  <xs:complexType name="TypeAndValue">
    <xs:attribute name="type" type="xs:string"/>
    <xs:attribute name="value" type="xs:string"/>
  </xs:complexType>
  <xs:complexType name="AddressTypeTag">
    <xs:attribute name="type" fixed="addressEnum" type="xs:string" />
    <xs:attribute name="fixed" >
      <xs:simpleType>
        <xs:restriction base="xs:string">
          <xs:enumeration value="CanadianAddress"></xs:enumeration>
          <xs:enumeration value="USAddress"></xs:enumeration>
        </xs:restriction>
      </xs:simpleType>
    </xs:attribute>
  </xs:complexType>
</xs:schema>
Alexander
  • 3,922
  • 7
  • 24
  • 34
  • I'm not keen on having an XML 1.1 dependency; (almost) no one uses it, and there are few implementations. In particular, I'd like to use libxml2, which does not support XML 1.1. XML 1.1 notwithstanding, however, I do not see how the above schema creates a mandatory association between, say, the 'USAddress' enumeration and the 'USAddressValue'. – badfd Jun 07 '17 at 15:41
  • @badfd, I don't know how it is possible, but I have published only last part of the schema. I will try to find complete schema tomorrow. In XSD 1.0 elements with a same name must be of a same well-defined type (see [the similar topic](https://stackoverflow.com/q/1306305/7914637)). – Alexander Jun 07 '17 at 16:59
  • @badfd, I have updated my answer. Now the schema has displayed completely. The cause of using XSD 1.1 is described by my previous comment. Good luck! – Alexander Jun 08 '17 at 04:16
  • I am not able to duplicate your results using Xerces-J, Alexander. What validation tool are you using? – badfd Jul 03 '17 at 23:43