XSD 예제

이 장에서는 XML Schema를 작성하는 방법을 안내해 드리겠습니다. 또한, Schema를 작성하는 다양한 방법을 배울 수 있습니다.

XML 문서

이름이 "shiporder.xml"인 XML 문서를 보겠습니다:

<?xml version="1.0" encoding="ISO-8859-1"?>
<shiporder orderid="889923">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="shiporder.xsd">
 <orderperson>George Bush</orderperson>
 <shipto>
  <name>John Adams</name>
  <address>Oxford Street</address>
  <city>London</city>
  <country>UK</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>

위의 XML 문서는 "shiporder"라는 루트 요소를 포함하고 있으며, "orderid"라는 이름을 가진 속성을 포함하고 있습니다. "shiporder" 요소는 "orderperson"、"shipto" 및 "item" 세 가지 다른 서브 요소를 포함하고 있습니다. "item" 요소는 두 번 등장하며, "title"、선택 사항인 "note" 요소、"quantity" 및 "price" 요소를 포함하고 있습니다.

위의 행 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"는 XML 파서가 특정 스키마를 기준으로 문서를 검증하도록 알립니다. 이 행 xsi:noNamespaceSchemaLocation="shiporder.xsd"는 스키마의 위치를 정의합니다(여기서는 "shiporder.xml"과 같은 폴더에 있습니다).

XML Schema를 생성하십시오.

지금, 위의 XML 문서에 schema를 생성해야 합니다.

새 파일을 열어 "shiporder.xsd"라는 이름을 지정할 수 있습니다. schema를 생성하려면 단순히 XML 문서의 구조를 따라 우리가 발견한 각 요소를 정의하면 됩니다. 먼저 표준 XML 선언을 시작합니다:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
...
...
</xs:schema>

위의 schema에서는 표준 이름 공간 (xs)을 사용했으며, 이 이름 공간과 관련된 URI는 Schema의 언어 정의(Schema language definition)입니다. 표준 값은 http://www.w3.org/2001/XMLSchema입니다.

다음으로, "shiporder" 요소를 정의해야 합니다. 이 요소는 다른 요소를 포함하는 속성을 가지고 있으므로 복합 타입으로 간주됩니다. "shiporder" 요소의 자식 요소는 xs:sequence 요소로 감싸져 있으며, 자식 요소의 순서를 정의합니다:

<xs:element name="shiporder">
 <xs:complexType>
  <xs:sequence>
  ...
  ...
  </xs:sequence>
  ...
 </xs:complexType>
</xs:element>

그런 다음, "orderperson" 요소를 간단한 타입으로 정의해야 합니다. 이는 이 요소가 어떠한 속성이나 다른 요소를 포함하지 않기 때문입니다. 타입 (xs:string)의 접두사는 이름 공간의 접두사에 의해 정의되며, 이 이름 공간은 XML schema에서 예약된 데이터 타입과 관련된 XML schema와 연결됩니다:

<xs:element name="orderperson" type="xs:string"/>

다음으로, 두 요소를 복합 타입으로 정의해야 합니다: "shipto"와 "item". "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>

schema를 통해 maxOccurs와 minOccurs 속성을 사용하여 특정 요소가 등장할 수 있는 횟수를 정의할 수 있습니다. maxOccurs는 특정 요소가 등장할 수 있는 최대 횟수를 정의하며, minOccurs는 최소 횟수를 정의합니다. maxOccurs와 minOccurs의 기본 값은 모두 1입니다!

지금, "item" 요소를 정의할 수 있습니다. 이 요소는 "shiporder" 요소 내에서 여러 번 등장할 수 있습니다. 이는 "item" 요소의 maxOccurs 속성 값을 "unbounded"으로 설정하여 이루어집니다. 이렇게 하면 "item" 요소는 창작자가 원하는 모든 횟수로 등장할 수 있습니다. 주의하세요, "note" 요소는 선택 사항입니다. 이미 이 요소의 minOccurs 속성 값을 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>

이제 "shiporder" 요소의 속성을 선언할 수 있습니다. 이는 필수 속성이므로 use="required"로 지정합니다。

비고:이 속성의 선언은 마지막에 위치해야 합니다:

<xs:attribute name="orderid" type="xs:string" use="required"/>

이 이름으로 "shiporder.xsd"의 schema 파일의 문서 목록은 다음과 같습니다:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<xs:schema xmlns:xs="http://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>

Schema 분할

이전 설계 방법은 매우 간단하지만, 문서가 복잡해지면 읽기와 유지보수가 어려워집니다.

다음에 소개할 설계 방법은 모든 요소와 속성의 정의를 먼저 하고, 그 다음에 ref 속성을 사용하여 참조하는 방법에 기반합니다.

이제 새로운 방법으로 설계된 schema 파일입니다:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- 간단한 요소 정의 -->
<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"/>
<!-- 속성 정의 -->
<xs:attribute name="orderid" type="xs:string"/>
<!-- 복합 요소 정의 -->
<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>

지정된 타입(이름된 타입) 사용

제3가지 설계 방법은 클래스나 타입을 정의하며, 이를 통해 요소 정의를 재사용할 수 있게 합니다. 구체적인 방법은 다음과 같습니다: 먼저 간단한 요소와 복합 요소에 이름을 부여한 후, 요소의 type 속성을 통해 이들을 지정합니다.

이는 제3가지 방법을 사용하여 설계된 schema 파일("shiporder.xsd")입니다:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<xs:schema xmlns:xs="http://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>

restriction 요소는 데이터 타입이 W3C XML Schema 이름 공간의 데이터 타입에서 비롯된 것을 보여줍니다. 따라서 다음 단편은 요소나 속성 값이 문자 타입의 값이어야 한다는 것을 의미합니다:

<xs:restriction base="xs:string">

restriction 요소는 요소에 제한을 가하는 데 자주 사용됩니다. 위의 schema에서 이러한 부분을 보세요:

<xs:simpleType name="orderidtype">
 <xs:restriction base="xs:string">
  <xs:pattern value="[0-9]{6}"/>
 </xs:restriction>
</xs:simpleType>

이 코드는 요소나 속성의 값이 문자열이어야 하며, 연속된 여섯 자릿수로 되어 있어야 하며, 이 문자는 0-9의 숫자여야 합니다.