A complex type allows attributes, children or both: an xs:sequence (in order), xs:choice (one of) or xs:all (any order), with minOccurs/maxOccurs defaulting to 1. xs:simpleContent adds attributes to text, mixed="true" allows text between children, ref reuses global elements, and xs:unique, xs:key and xs:keyref enforce identity:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:include schemaLocation="types.xsd"/>
<xs:element name="catalog" type="catalogType">
<xs:unique name="uniqueSku"><xs:selector xpath="book/identifier"/><xs:field xpath="."/>
</xs:unique>
</xs:element>
<xs:complexType name="catalogType"><xs:sequence>
<xs:element name="header"><xs:complexType><xs:sequence>
<xs:element name="sender" type="xs:string"/><xs:element name="sent" type="xs:dateTime"/>
<xs:element name="records" type="xs:nonNegativeInteger"/>
</xs:sequence></xs:complexType></xs:element>
<xs:element name="book" type="bookType" maxOccurs="unbounded"/></xs:sequence>
<xs:anyAttribute namespace="http://www.w3.org/XML/1998/namespace" processContents="skip"/>
</xs:complexType>
<xs:element name="identifier" type="idType"/>
<xs:complexType name="bookType"><xs:sequence>
<xs:element ref="identifier"/><xs:element name="title" type="xs:string"/>
<xs:element name="contributor" type="contributorType" maxOccurs="unbounded"/>
<xs:element name="subject" type="subjectType"/>
<xs:element name="pages" type="xs:positiveInteger"/>
<xs:element name="published" type="xs:gYear"/><xs:element name="summary" type="xs:string"/>
<xs:element name="rating" type="ratingType" minOccurs="0"/>
<xs:element name="supply"><xs:complexType><xs:sequence>
<xs:element name="availability" type="availabilityType"/>
<xs:element name="price" type="priceType"/></xs:sequence></xs:complexType></xs:element>
</xs:sequence><xs:attribute name="id" type="xs:ID" use="required"/>
</xs:complexType>
<xs:complexType name="contributorType"><xs:sequence>
<xs:element name="name" type="xs:string"/><xs:element name="sort-name" type="xs:string"/>
</xs:sequence><xs:attribute name="role" type="roleType" use="required"/>
<xs:attribute name="seq" type="xs:positiveInteger" default="1"/>
</xs:complexType>
<xs:complexType name="subjectType"><xs:simpleContent><xs:extension base="xs:string">
<xs:attribute name="scheme" type="xs:token" use="required"/>
</xs:extension></xs:simpleContent></xs:complexType>
<xs:complexType name="idType"><xs:simpleContent><xs:extension base="xs:token">
<xs:attribute name="type" type="xs:token" default="sku"/>
</xs:extension></xs:simpleContent></xs:complexType>
<xs:complexType name="priceType"><xs:simpleContent><xs:extension base="moneyType">
<xs:attribute name="currency" type="xs:token" use="required"/>
</xs:extension></xs:simpleContent></xs:complexType>
</xs:schema>Every leaf is now typed (pages a positive integer, sent a timestamp), xs:anyAttribute admits xml:lang without fetching W3C's xml.xsd, and xs:unique catches a repeated SKU, which a DTD cannot express.