Search code examples
xmlxsdxsd-validationdtdxml-validation

XSD conditional element


I am in the process of learning XSD. I want to transform my DTDs into XSDs in order to avail myself of the possibilities of XSD. I have run into the following problem:

The DTD that I want to transform reads (in part):

<!ELEMENT author ((first|(first, middle))?, last, suffix?)>

The idea here is that there may be (but does not have to be) a middle element only if there is a first element (i.e., no middle name if there is no first name).

I had this DTD transformed into XSD by Oxygen XML Editor, which gave the following:

  <xs:element name="author">
    <xs:complexType>
      <xs:sequence>
        <xs:choice minOccurs="0">
          <xs:element ref="first"/>
          <xs:sequence>
            <xs:element ref="first"/>
            <xs:element ref="middle"/>
          </xs:sequence>
        </xs:choice>
        <xs:element ref="last"/>
        <xs:element minOccurs="0" ref="suffix"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

But the validation engine used by Oxygen (Xerces) throws the following error concerning this part:

first and first (or elements from their substitution group) violate "Unique Particle Attribution".

So my question is this: What is the proper way to express my DTD in XSD? How can the constraint that I want to put on the middle element be expressed without violating "Unique Particle Attribution"?

Thanks in advance for your help!


Solution

  • Rewriting the content model of author like this,

      <xs:element ref="author">
        <xs:complexType>
          <xs:sequence>
            <xs:sequence minOccurs="0">
              <xs:element ref="first"/>
              <xs:element ref="middle" minOccurs="0"/>
            </xs:sequence>
            <xs:element ref="last"/>
            <xs:element ref="suffix" minOccurs="0"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    

    will express the same constraint as the DTD without violating Unique Particle Attribution.