2
votes

I am trying to create an XSD for following schema and I am unsure how to self reference the same type element. I tried using the ref attribute but visual studio keeps on raising an error when i create the xml file. When creating XML inside the pre-req element it is expecting me to provide it a full Course element with description/department/credits

can someone help generate xsd for the xml at the end

<xs:element name="Course">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="Description" />
        <xs:element name="Department" />
        <xs:element name="Credits" type="xs:decimal" />
        <xs:element name="Prerequisite" minOccurs="0" maxOccurs="unbounded">
          <xs:complexType>
            <xs:sequence>
              <xs:element ref="Course" minOccurs="1" maxOccurs="unbounded"/>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
      <xs:attribute name="CourseCode" type="xs:string" use="required" />
    </xs:complexType>
  </xs:element>

  <xs:element name="Courses">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="Course" minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

And here is the XML

<Courses>
  <Course CourseCode="ABC123">
    <Description>This is Math Level 2</Description>
    <Department>Maths</Department>
    <Credits>7.5</Credits>
    <Prerequisite>
      <Course CourseCode="MTH001"></Course>
    </Prerequisite>
  </Course>
  <Course CourseCode="MTH001">
    <Description>This is Math Level 1</Description>
    <Department>Maths</Department>
    <Credits>5.0</Credits>
  </Course>
</Courses>
1

1 Answers

2
votes

It's logical that a full course element is expected: that's what you defined in your XSD when you said <xs:element ref="Course" - you recursively referred to your full course element.

You can create a local element definition for an element <Course that has a different type and then it can have different validation rules.

That's the first step.

The second step is that xml schema has built-in support for an identifier that you can refer to. In an attribute that defined the identifier, you should use the type xs:ID instead of xs:string. And in the attribute that refers to the identifier, you should use the type xs:IDREF instead of xs:string.

Combining the two, you get:

<xs:element name="Course">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="Description" />
            <xs:element name="Department" />
            <xs:element name="Credits" type="xs:decimal" />
            <xs:element name="Prerequisite" minOccurs="0" maxOccurs="unbounded">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element name="Course" minOccurs="1" maxOccurs="unbounded">
                            <xs:complexType>
                                <xs:attribute name="CourseCode" type="xs:IDREF" use="required" />
                            </xs:complexType>
                        </xs:element>
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
        </xs:sequence>
        <xs:attribute name="CourseCode" type="xs:ID" use="required" />
    </xs:complexType>
</xs:element>

That should validate your input XML, and as a bonus, when the course id that you used in your <Prerequisite> doesn't exist in your XML, it now raises a validation error.