XML Schema란?
- XML Schema는 XML 문서의 구조를 설명함.
- XML Schema 언어는 XSD(XML Schema Definition) 이라고도 한다.
- XML 스키마의 목적 : XML 문서의 합법적 기본구성요소를 정의
- 문서에 어떤 요소와 속성이 나타나야 하는가?
- 하위 요소들의 수와 순서
- 요소와 속성의 데이터 유형
- 요소와 속성의 기본값/고정값
- 왜 XML 스키마를 배워야 하는가?
- 이미 수백가지의 표준화된 XML 포맷이 사용중이다.
- 수많은 XML 표준은 XML Schema로 정의되어 있다.
- XML Schema는 XML기반이며, DTD를 대체할 수있으며 훨씬 강력하다.
- XML 스키마는 데이터유형을 지원한다.
- 허용되는 내용을 쉽게 설명가능
- 데이터의 정확성 검증가능
- 데이터에 대한 제한을 정의가능
- 데이터 패턴(포맷)을 쉽게 정의가능
- 다른 유형으로 쉽게 변환 가능
- XML Schema는 XML 문법을 사용함. 따라서
- 새로운 언어를 배울 필요 없으며
- XML 에디터로 스키마파일을 편집할 수 있고
- XML parser로 스키마파일을 파싱할 수 있고
- XML DOM으로 처리할 수 있으며
- XSLT로 스키마를 변환할 수 있다.
- XML Schema는 확장가능하다. 따라서
- 다른 스키마를 재사용가능하다.
- 표준 유형에서 새로운 데이터유형을 생성할 수 있다.
- 동일한 문서에서 여러개의 스키마를 참조할 수 있다.
- XML 스키마를 사용하면 안전한 데이터 통신이 가능하다.
- 데이터를 보낼때, 내용에 대한 동일한 이해가 가능하다.
- 수신자가 이해할 수 있는 방법으로 데이터를 설명할 수 있다.
- "3-11-2004" 와 같이 데이터 해석이 달라질 염려를 없앨 수 있다.
- Well-Formed 문서만으로는 부족하다.
- Well-Formed 된 문서도 오류가 있을 수 있다.
- XML Schema를 사용하면 에러를 검증할 수 있다.
XSD 사용법
- XML 문서는 XML Schema에 대한 참조를 가질 수 있다.
- 예제 XML 문서 : note.xml
<?xml version="1.0" encoding="utf-8"?>
<note>
<to>Tove</to>
<from>Jani</from>
<body>Don't forget me this weekend!</body>
</note>
- 이 문서에 대한 XML Schema : note.xsd
<?xml version="1.0" encoding="utf-8"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="https://www.w3schools.com"
xmlns="https://www.w3cschools.com"
elementFormDefault="qualified">
<xs:element name="note">
<xs:complexType>
<xs:sequence>
<xs:element name="to" type="xs:string" />
<xs:element name="from" type="xs:string" />
<xs:element name="body" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
- 이 note.xsd를 참조하여 note.xml을 다시 작성하면
<?xml version="1.0"? encoding="utf-8">
<note
xmlns="https://www.w3schools.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://www.w3schools.com/xml/note.xsd">
<to>Tove</to>
<from>Jani</Jani>
<body>Don't forget me this weekend!</body>
</note>
XSD- <schema> 요소
- <schema> 요소는 모든 XML Schema 문서의 root 요소이다.
- <schema> 요소는 속성을 가질 수 있다.
- xmlns:xs="http://www.w3.org/2001/XMLSchema"
- 이 schema에 사용되는 데이터유형이 w3.org 네임스페이스에서 왔음을 의미함
- 이 데이터유형들을 사용할 때 xs: 를 사용해야 함
- targetNamespace="https://w3schools.com"
- 이 스키마에서 정의되는 요소(note, to, body)는 "w3school" 네임스페이스에서 왔음
- xmlns="https://www.w3schools.com"
- 네임스페이스 기본값이 "https://www.w3schools.com" 임
- elementFormDefault="qualified"
- 이 스키마에서 선언되는 XML 인스턴스 문서에 사용되는 모든 요소는 네임스페이스에 한정되어야 한다(namespace qualified)
- XML 문서에서 스키마를 참조할 때...
- xmlns="https://www.w3schools.com"
- 기본 네임스페이스 선언. 이 문서에서 사용된 모든 요소들은 w3schools 네임스페이스에 선언되었음을 의미함
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- 먼저 이렇게 XML schema instance 네임스페이스를 가져오면, 아래의 schemaLocation 속성을 사용할 수 있게됨.
- xsi:schemaLocation="https://www.w3schools.com note.xsd"
- schemaLocation 속성은 두개의 값이 들어가며, 첫번째값은 사용할 네임스페이스, 두번째는 해당 네임스페이스에서 사용하고자하는 XML 스키마의 위치임.
XSD Simple 요소
- simple 요소는 텍스트만 담을 수 있는 요소.
- 하지만, 텍스트는 여러가지 유형이 있음. XML Schema definition에는 boolean, string, data 등의 유형이 정의되어 있고, 사용자가 정의할 수도 있다.
- 내용을 제한하기 위해 데이터유형에 제한(facets)를 걸 수도 있고, 특정한 패턴만 요구할 수도 있음
- Simple 요소 정의방법
- <xs:element name="xxx" type="yyy" />
- xxx는 이름.
- yyy는 다음과 같은 여러가지를 사용할 수 있음
- xs:string
- xs:decimal
- xs:integer
- xs:boolean
- xs:date
- xs:time
- 예제 xml 요소
<lastname>Heo</lastname>
<age>35</age>
<dateborn>1970-03-27</dateborn>
- 이에 대한 simple 요소 정의
<xs:element name="lastname" type="xs:string"/>
<xs:element name="age" type="xs:integer"/>
<xs:element name="dateborn" type="xs:date"/>
- 기본값(default)과 고정값(fixed)
- 기본값
- <xs:element name="color" type="xs:string" default="red">
- 고정값
- <xs:element name="Rcolor" type="xs:string" fixed="red">
XSD 속성
- 속성을 정의하는 방법
- <attribute name="xxx" type="yyy" />
- 여기서 "yyy" 데이터 유형은 element와 동일
- 예
- <lastname lang="EN">Smith</lastname>을 정의하려면
<xs:element name="lastname" type="xs:string" />
<xs:attribute name="lang" type="xs:string" />
- 기본값과 고정값을 부여하는 방법은 요소의 경우와 동일하다.
- 필수/선택은 "use" attribute를 사용한다.
- <xs:attribute name="lang" type="xs:string" use="required" />
XSD Restrictions
- 이상과 같이 type을 지정하면 들어올 수 있는 내용을 제한하게 된다.
- 여기에 사용자가 원하는 제한을 더 가할 수 있다. 이것을 facets라고 한다.
- 최대값 최소값 : 아래의 예는 값의 범위를 정하는 방법
<xs:element name="age">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:minInclusive value="0" />
<xs:maxInclusive value="120" />
</xs:restriction>
</xs:simpleType>
</xs:element>
- 값 목록을 지정할 경우
<xs:element name="car">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="Audi" />
<xs:enumeration value="BMV" />
<xs:enumeration value="Golf" />
</xs:restriction>
</xs:simpleType>
</xs:element>
- 아래는 위와 동등한 내용
- 이 경우, "carType"은 다른 항목에도 사용할 수 있다.
- 재활용이 가능하므로, 대부분 이런 형태로 정의한다.
<xs:element name="car" type="carType" />
<xs:simpleType name="carType">
<xs:restriction base="xs:string">
<xs:enumeration value="Audi" />
.........
</xs:simpleType>
- 기타 여러가지 제한
- <xs:pattern value="[a-z]" /> : 소문자로 한글자.
- <xs:pattern value="[A-Z][A-Z][A-Z]" /> : 대문자로 세글자
- <xs:pattern value="[a-zA-A][a-zA-A][a-zA-A]" />: 세글자
- <xs:pattern value="[xyz]" /> : "x" 또는 "y" 또는 "z"
- <xs:pattern value="[0-9][0-9][0-9][0-9][0-9]" /> : 5자리 숫자
- <xs:pattern value="([a-z])*" /> : 소문자만. 글자수는 0 이상
- <xs:pattern value="([a-z][A-Z])+" /> : 소문자+대문자쌍으로. 글자수는 2이상
- <xs:pattern value="male|female" /> : "male" 또는 "female" 만
- <xs:pattern value="[a-zA-Z0-9]{8}" /> : 영숫자 8글자
- <xs:whiteSpace value="preserve" /> : 공백문자(LF, CR, Tab등)을 그대로 유지
- <xs:whiteSpace value="replace" /> : 모든 종류의 공백문자들을 space로 바꿈
- <xs:whiteSpace value="collapse" /> : 앞뒤, 여러개의 공백을 하나의 space로
- <xs:length value="8" /> : 8글자
- <xs:minLength value="5" /> <xs:maxLength value="8" /> 5글자에서 8글자까지
- 기타 데이터 유형에 관한 제한
- enumeration : 허용되는 값의 목록을 정의함
- factionDigits : 소숫점이하 자릿수 지정(0 이상)
- length : 문자의 수 또는 목록의 경우 목록의 수(0 이상)
- maxExclusive : 허용되는 숫자형의 상한값(미만)
- maxInclusive : 허용되는 숫자형의 상한값(이하)
- maxLength : 최대 문자수 또는 최대 목록수
- minExclusive : 허용되는 숫자형의 하한값(초과)
- minInclusive : 허용되는 숫자형의 하한값(이상)
- minLength : 최소 문자수 또는 최소 목록수
- pattern : 허용되는 문자열의 순서
- totalDigits : 허용되는 숫자 자릿수 (0 이상)
- whiteSpace : white space(LF, tab, space, CR)를 어떻게 취급할 지 지정
XSD Complex 요소
- Complex 요소란 다른 요소나 속성을 포함하는 요소로 4가지 종류가 있다.
- <product pid="12354" /> : empty 요소
- <employee><fn>A</fn><ln>B</ln></employee> : 다른 요소만 포함하는 요소
- <food type="desert">Ice cream</food> : 텍스트만 포함하는 요소
- <desc>It happened on <date lang="NR">03.03.99</date></desc>
: 다른 요소와 텍스트를 포함하는 요소 - 단!!!! 각각의 요소는 속성을 가질 수 있다.
Complex 요소를 정의하는 방법의 예
<employee>
<firstname>Jorhn</firstname>
<lastname>Smith</lastname>
</employee>
====
<xs:element name="employee">
<xs:complexType>
<xs:sequence> sequence를 사용하면 순서대로 나타나야 함.
<xs:element name="firstname" type="xs:string" />
<xs:element name="lastname" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
- 유형을 따로 정하면 여러번 반복하여 사용할 수 있다.
<xs:element name="employee" type="personType" />
<xs:element name="student" type="personType" />
<xs:complexType name="personType">
<xs:sequence>
<xs:element name="firstname" type="xs:string" />
<xs:element name="lastname" type="xs:string" />
</xs:sequence>
<xs:complexType>
- xs:complexContent와 xs:extension을 사용하면 기본 complex 요소를 확장시킬 수 있다.
<xs:element name="employee" type="fullPersonInfo" />
<xs:complexType name="personinfo">
<xs:sequence>
<xs:element name="firstname" type="xs:string" />
<xs:element name="lastname" type="xs:string" />
</xs:sequence>
<xs:complexType>
<xs:complexType name="fullPersonInfo">
<xs:complexContent>
<xs:extension base="personinfo">
<xs:sequence>
<xs:element name="address" type="xs:string">
<xs:element name="city" type="xs:string">
<xs:element name="country" type="xs:string">
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
XSD Empty 요소
- <product prodid="1234" /> 와 같이 내용이 없는 요소를 정의하려면 아래의 방법이 가장 간단.
<xs:element name="product" type="prodType" />
<xs:complexType name="prodtype">
<xs:attribute name="prodid" type="xs:positiveInteger" />
</xs:complexType>
XSD 요소들만 들어가는 Complex 유형
<person>
<firstname>A</firstname>
<lastname>B</lastname>
</person>
====
<xs:element name="person" type="personType" />
<xs:complexType name="personType">
<xs:sequence>
<xs:element name="firstname" type="xs:string" />
<xs:element name="lastname" type="xs:string" />
</xs:sequence>
</xs:complexType>
Text만 들어가는 Complex 유형
- simple 유형은 <xs:element name="xxx" type="yyy"/> 와 같이, 제한도, 속성도 못넣음
- <shoesize country="france">35</shoesize> 를 정의하는 방법
- complexType으로 정의하고, 내부에 simpleContent를 넣고 그 안에 extension 또는 restriction을 사용함.
<xs:element name="shoesize" type="shoeType" />
<xs:complexType name="shoeType"
<xs:simpleContent>
<xs:extension base="xs:integer">
<xs:attribute name="country" type="xs:string" />
</xs:extension>
</xs:simpleContent>
</xs:complexContent
XSD 문자와 요소가 혼합된 Comlex 유형
- 아래와 같이 문자와 요소가 섞여도 무방한 Complex 유형을 만들려면 mixed="true"를 추가하면 된다.
<letter>
Dear Mr.<name>John Smith</name>.
Your order <orderid>2043</orderid>
will be shipped on <shipdate>2001-07-13</shipdate>.
</letter>
<xs:element name="letter" type="letterType" />
<xs:complexType name="letterType" mixed="true">
<xs:sequence> ----> 순서대로 나타나야 함
<xs:element name="name" type="xs:string">
<xs:element name="order" type="xs:positiveInteger">
<xs:element name="shipdate" type="xs:date">
</xs:sequence>
</xs:complexType>
XSD 지시자(Indicator)
- 순서 지시자(Order Indicator)
- sequence - 모두 한번씩. 정해진 순서대로
- all - 모두 단 한번씩 등장해야 함. 순서는 없음
- choice - 둘중의 하나만 등장
- 횟수 지시자(Occurence Indicator)
- minOccurs/maxOccurs
- 그룹 지시자(Group Indicator)
- <xs:group name="xxx">
- 그룹을 지정하면 다른 정의에서도 사용할 수 있음
- 속성 그룹(attribute Group)
- <xs:attributeGroup name="xxx">
- 그룹을 지정하면 다른 정의에서도 사용할 수 있음
- 예제
<?xml version="1.0" encoding="UTF-8" ?>
<persons xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="family.xsd">
<person>
<fullname>Min Heo</fullname>
<childname>Minho</childname>
</person>
<person>
<fullname>Tove Refsnes</fullname>
<childname>Hege</childname>
<childname>Stale</childname>
<childname>Jim</childname>
</person>
<person>
<fullname>Stale Refsnes</fullname>
</person>
</persons>
- family.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:element name="persons">
<xs:complexType>
<xs:sequence>
<xs:element name="person" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="fullname" type="xs:string"/>
<xs:element name="childname" type="xs:string"
minOccurs="0" maxOccurs="5"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
XSD <any> 요소, <anyAttribute> 요소
- <any> 요소를 사용하면 스키마에서 지정하지 않은 요소를 사용할 수 있도록 확장시킬 수 있다.
- 아래는 family.xsd 파일의 일부
<xs:element name="person">
<xs:complexType>
<xs:sequence>
<xs:element name="firstname" type="xs:string" />
<xs:element name="lastname" type="xs:string" />
<xs:any minOccurs="0" />
--- </xs:element>
- 사용법은....
XSD Substitution Group
- 예를 들어, 영국고객과 노르웨이고객이 있어서, 영국식/노르웨이 언어로 정의하도록
- head 요소를 정의한 후, 이 head 요소를 대체할 수 있다고 명시한 또 다른 요소를 정의한다.
- 아래에서 head 요소는 "name", "navn"요소는 "name" 요소를 대체할 수 있음.
<xs:element name="name" type="xs:string" />
<xs:element name="navn" substitutionGroup="name" />
- XML Schema
<xs:element name="name" type="xs:string" />
<xs:element name="navn" substitutionGroup="name" />
<xs:complexType name="customerType">
<xs:sequence>
<xs:element ref="name" />
<xs:sequence>
</xs:complexType>
<xs:element name="customer" type="customerType" />
<xs:element name="kunde" substitutionGroup="customer" />
- 이런 식으로 정의하였을 때 XML 파일에는 아래와 같이 두가지가 모두 들어갈 수 있다.
<customer>
<name>Min Heo</name>
</customer>
<kunde>
<navn>John Smith</navn>
</kunde>
- 대체를 금지시키고 싶으면 block을 사용하면 된다.
<xs:element name="name" type="xs:string" block= "substitution" />
- SubstitutionGroup 사용방법
- 대체가능 요소(substitutable element)는 head요소와 동일한 type 또는 head 요소 유형에서 유도된 유형이어야 한다.
- 동일한 유형일 경우엔 substitution 하면서 type은 정의할 필요없지만, 유도할 경우 새로 정의
- substitutionGroup의 모든 요소(head 요소 및 substitutable 요소)는 반드시 Global 요소로 선언
XSD 예제
<?xml version="1.0" encoding="UTF-8" ?>
<shiporder orderid="8893"
xmlns:xsi="http://www.w3c.org/2001/XMLSchema-Instance"
xsi:noNamespaceSchemaLocaiton="shiporder.xsd">
<orderperson>John Smith</orderperson>
<shipto>
<name>Ola Nordmann</name>
<address>Langgt 2</address>
<city>400 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>
- root 요소 : shiporder (orderid라는 속성이 있음)
shiporder는 3개의 child 요소(orderperson, shipto, item) - xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"- 반드시 schema에 비교해야 함을 의미
- xsi:noNamespaceSchemaLocation="shiporder.xsd" - 스키마의 위치 (여기에선 동일한 폴더)
<?xml version="1.0" encoding="UTF-8" ?>
<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>
XSD 분할
- 문서가 복잡해지면 읽기 힘들다.
- 모든 요소와 속성을 미리 다 정의한 후, 이들을 ref 속성을 사용하여 참조한다.
Named 유형을 사용하기
- 클래스/유형을 먼저 정의하고, 요소 정의를 재활용.
===