Một ví dụ XSD
Chương này sẽ trình bày cách viết một Lược đồ XML. Bạn cũng sẽ biết rằng một lược đồ có thể được viết theo nhiều cách khác nhau.
Một tài liệu XML
Chúng ta hãy xem tài liệu XML có tên "shiporder.xml" này:
<?xml version="1.0" encoding="UTF-8"?>
<shiporder orderid="889923"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="shiporder.xsd">
<orderperson>John Smith</orderperson>
<shipto>
<name>Ola Nordmann</name>
<address>Langgt 23</address>
<city>4000 Stavanger</city>
<country>Norway</country>
</shipto>
<item>
<title>Empire Burlesque</title>
<note>Special Edition</note>
<quantity>1</quantity>
<price>10.90</price>
</item>
<item>
<title>Hide your heart</title>
<quantity>1</quantity>
<price>9.90</price>
</item>
</shiporder>
Tài liệu XML ở trên bao gồm phần tử gốc, "shiporder", chứa thuộc tính bắt buộc được gọi là "orderid". Phần tử "shiporder" chứa ba phần tử con khác nhau: "người đặt hàng", "shipto" và "item". Phần tử "mục" xuất hiện hai lần và chứa phần tử "tiêu đề", phần tử "ghi chú" tùy chọn, phần tử "số lượng" và phần tử "giá".
Dòng trên: xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" cho trình phân tích cú pháp XML biết rằng tài liệu này phải được xác thực dựa trên một lược đồ. Dòng: xsi:noNamespaceSchemaLocation="shiporder.xsd" chỉ định Lược đồ nằm ở ĐÂU (ở đây nó nằm trong cùng thư mục với "shiporder.xml").
Tạo một lược đồ XML
Bây giờ chúng ta muốn tạo một lược đồ cho tài liệu XML ở trên.
Chúng tôi bắt đầu bằng cách mở một tệp mới mà chúng tôi sẽ gọi là "shiporder.xsd". Để tạo lược đồ, chúng ta chỉ cần làm theo cấu trúc trong tài liệu XML và xác định từng phần tử khi chúng ta tìm thấy nó. Chúng ta sẽ bắt đầu với khai báo XML tiêu chuẩn, theo sau là phần tử xs:schema xác định một lược đồ:
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="https://www.w3.org/2001/XMLSchema">
...
</xs:schema>
Trong lược đồ ở trên, chúng tôi sử dụng không gian tên tiêu chuẩn (xs) và URI được liên kết với không gian tên này là định nghĩa ngôn ngữ Lược đồ, có giá trị tiêu chuẩn là https://www.w3.org/2001/XMLSchema.
Tiếp theo, chúng ta phải xác định phần tử "shiporder". Phần tử này có một thuộc tính và nó chứa các phần tử khác, do đó chúng tôi coi nó là một kiểu phức tạp. Các phần tử con của phần tử "shiporder" được bao quanh bởi phần tử xs:sequence xác định trình tự có thứ tự của các phần tử phụ:
<xs:element name="shiporder">
<xs:complexType>
<xs:sequence>
...
</xs:sequence>
</xs:complexType>
</xs:element>
Sau đó, chúng ta phải định nghĩa phần tử "orderperson" là một kiểu đơn giản (vì nó không chứa bất kỳ thuộc tính hoặc phần tử nào khác). Loại (xs:string) có tiền tố không gian tên được liên kết với Lược đồ XML cho biết loại dữ liệu lược đồ được xác định trước:
<xs:element name="orderperson" type="xs:string"/>
Tiếp theo, chúng ta phải xác định hai phần tử thuộc loại phức tạp: "shipto" và "item". Chúng ta bắt đầu bằng cách xác định phần tử "shipto":
<xs:element name="shipto">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="address" type="xs:string"/>
<xs:element name="city" type="xs:string"/>
<xs:element name="country" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
Với các lược đồ, chúng ta có thể xác định số lần xuất hiện có thể có của một phần tử với các thuộc tính maxOccurs và minOccurs. maxOccurs chỉ định số lần xuất hiện tối đa cho một phần tử và minOccurs chỉ định số lần xuất hiện tối thiểu cho một phần tử. Giá trị mặc định cho cả maxOccurs và minOccurs là 1!
Bây giờ chúng ta có thể định nghĩa phần tử "item". Phần tử này có thể xuất hiện nhiều lần bên trong phần tử "shiporder". Điều này được chỉ định bằng cách đặt thuộc tính maxOccurs của phần tử "item" thành "không bị chặn", có nghĩa là có thể có nhiều lần xuất hiện của phần tử "item" như tác giả mong muốn. Lưu ý rằng phần tử "ghi chú" là tùy chọn. Chúng tôi đã chỉ định điều này bằng cách đặt thuộc tính minOccurs về 0:
<xs:element name="item" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="title" type="xs:string"/>
<xs:element name="note" type="xs:string" minOccurs="0"/>
<xs:element name="quantity" type="xs:positiveInteger"/>
<xs:element name="price" type="xs:decimal"/>
</xs:sequence>
</xs:complexType>
</xs:element>
Bây giờ chúng ta có thể khai báo thuộc tính của phần tử "shiporder". Vì đây là thuộc tính bắt buộc nên chúng tôi chỉ định use="required".
Lưu ý: Việc khai báo thuộc tính phải luôn ở cuối cùng:
<xs:attribute name="orderid" type="xs:string" use="required"/>
Đây là danh sách đầy đủ của tệp lược đồ có tên "shiporder.xsd":
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="https://www.w3.org/2001/XMLSchema">
<xs:element name="shiporder">
<xs:complexType>
<xs:sequence>
<xs:element name="orderperson" type="xs:string"/>
<xs:element name="shipto">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="address" type="xs:string"/>
<xs:element name="city" type="xs:string"/>
<xs:element name="country" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="item" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="title" type="xs:string"/>
<xs:element name="note" type="xs:string" minOccurs="0"/>
<xs:element name="quantity" type="xs:positiveInteger"/>
<xs:element name="price" type="xs:decimal"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="orderid" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
</xs:schema>
Chia lược đồ
Phương pháp thiết kế trước đó rất đơn giản nhưng có thể khó đọc và bảo trì khi tài liệu phức tạp.
Phương pháp thiết kế tiếp theo dựa trên việc xác định tất cả các thành phần và thuộc tính trước tiên, sau đó tham chiếu đến chúng bằng thuộc tính ref.
Đây là thiết kế mới của tệp lược đồ ("shiporder.xsd"):
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="https://www.w3.org/2001/XMLSchema">
<!-- definition of simple elements -->
<xs:element name="orderperson" type="xs:string"/>
<xs:element name="name" type="xs:string"/>
<xs:element name="address" type="xs:string"/>
<xs:element name="city" type="xs:string"/>
<xs:element name="country" type="xs:string"/>
<xs:element name="title" type="xs:string"/>
<xs:element name="note" type="xs:string"/>
<xs:element name="quantity" type="xs:positiveInteger"/>
<xs:element name="price" type="xs:decimal"/>
<!-- definition of attributes -->
<xs:attribute name="orderid" type="xs:string"/>
<!-- definition of complex elements -->
<xs:element name="shipto">
<xs:complexType>
<xs:sequence>
<xs:element ref="name"/>
<xs:element ref="address"/>
<xs:element ref="city"/>
<xs:element ref="country"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="item">
<xs:complexType>
<xs:sequence>
<xs:element ref="title"/>
<xs:element ref="note" minOccurs="0"/>
<xs:element ref="quantity"/>
<xs:element ref="price"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="shiporder">
<xs:complexType>
<xs:sequence>
<xs:element ref="orderperson"/>
<xs:element ref="shipto"/>
<xs:element ref="item" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute ref="orderid" use="required"/>
</xs:complexType>
</xs:element>
</xs:schema>
Sử dụng các loại được đặt tên
Phương pháp thiết kế thứ ba xác định các lớp hoặc kiểu, cho phép chúng ta sử dụng lại các định nghĩa phần tử. Điều này được thực hiện bằng cách đặt tên cho các phần tử simpleTypes và complexTypes, sau đó trỏ đến chúng thông qua thuộc tính type của phần tử.
Đây là thiết kế thứ ba của tệp lược đồ ("shiporder.xsd"):
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="https://www.w3.org/2001/XMLSchema">
<xs:simpleType name="stringtype">
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:simpleType name="inttype">
<xs:restriction base="xs:positiveInteger"/>
</xs:simpleType>
<xs:simpleType name="dectype">
<xs:restriction base="xs:decimal"/>
</xs:simpleType>
<xs:simpleType name="orderidtype">
<xs:restriction base="xs:string">
<xs:pattern value="[0-9]{6}"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="shiptotype">
<xs:sequence>
<xs:element name="name" type="stringtype"/>
<xs:element name="address" type="stringtype"/>
<xs:element name="city" type="stringtype"/>
<xs:element name="country" type="stringtype"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="itemtype">
<xs:sequence>
<xs:element name="title" type="stringtype"/>
<xs:element name="note" type="stringtype" minOccurs="0"/>
<xs:element name="quantity" type="inttype"/>
<xs:element name="price" type="dectype"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="shipordertype">
<xs:sequence>
<xs:element name="orderperson" type="stringtype"/>
<xs:element name="shipto" type="shiptotype"/>
<xs:element name="item" maxOccurs="unbounded" type="itemtype"/>
</xs:sequence>
<xs:attribute name="orderid" type="orderidtype" use="required"/>
</xs:complexType>
<xs:element name="shiporder" type="shipordertype"/>
</xs:schema>
Phần tử hạn chế chỉ ra rằng kiểu dữ liệu được lấy từ kiểu dữ liệu không gian tên Lược đồ XML của W3C. Vì vậy, đoạn sau có nghĩa là giá trị của phần tử hoặc thuộc tính phải là giá trị chuỗi:
<xs:restriction base="xs:string">
Phần tử hạn chế thường được sử dụng nhiều hơn để áp dụng các hạn chế cho các phần tử. Nhìn vào các dòng sau từ lược đồ trên:
<xs:simpleType name="orderidtype">
<xs:restriction base="xs:string">
<xs:pattern value="[0-9]{6}"/>
</xs:restriction>
</xs:simpleType>
Điều này chỉ ra rằng giá trị của phần tử hoặc thuộc tính phải là một chuỗi, nó phải có chính xác sáu ký tự liên tiếp và các ký tự đó phải là số từ 0 đến 9.