공간정보/표준2018. 6. 18. 23:28

ISO TC211 UML 모델을 실제 응용프로그램에서 활용하기 위해서는, 이 모델들을 직렬화하고 정보처리단위간에 전송할 수 있는 표현으로 구현되어야 한다. 대부분 현재의 구현은 XML을 사용하여 직렬화하며, 이때 XML Schema를 사용하여 교환 문서의 구조를 정의한다. 개념 모델을 구현하는 스키마를 자동적으로 생성하려면, UML 모델로부터 XML 스키마를 생성하는 소프트웨어 처리가 필요하다. 여기에서 설명하는 처리는 여러가지 최신 표준을 위하여 사용된다.

필요 소프트웨어

여기에 서술된 내용은 매우 간략한 정보이다. 자세한 내용은 Harmonized Model Management Group 위키를 참조하라

Enterprise Architect(EA) : ISO TC211 조화 UML모델을 생성, 갱신, 관리하는데 사용되는 상용 소프트웨어 패키지. 여기에 설명된 내용은 버전 12.1.1230을 기초로 한다. 2017년 07월 현재 EA 버전은 13.5이지만, 새로운 버전에 이 절차를 테스트하지 않았다.

ISO TC211 조화 모델(Harmonized Model) : ISO TC211 조화 모델은 웹에서 접근가능한 디렉토리에 저장되어 있다. 이 디렉토리에는 TC211가 책임을 맡고있는 모든 UML 모델을 담고 있는 파일들이 있다. 이 모델들은 EA로부터 XMI XML 교환포맷을 사용하여 내보낸(export) 것으로, 이들 XMI 파일들은 이 온라인 디렉토리에서 버전 관리(아래 Subversion을 볼 것)되고 있다. EA를 제외한 다른 UML 모델링 패키지도 이들 XMI 파일을 사용할 수 있으나, 실용적으로는 모델의 측면(노트, 태그, 색 코딩 등)을 모두 신뢰성있게 변환할 수 있을 정도로 표준화된 상태가 아니다. TC211 조화모델 저장소에 있는 XMI 문서는 다음의 네임스페이스를 사용한다. 

xmi.version="1.1" xmlns:UML="omg.org/UML1.3"

아울러 Enterprise Architect exporter 버전 2.5를 사용했고, windows-1252 캐릭터 인코딩을 사용하였다.

Subversion : TC211 조화모델 저장소는 Subversion 소프트웨어와 아파치 소프트웨어 재단의 오픈소스 패키지를 사용하여 관리되고 있다. 모델 요소를 체크아웃하고 변화를 체크하려면, 반드시 Subversion 클라이언트를 설치해야 하며, 모델 저장소와 연결해야 한다.

ShapeChange : Interactive Instruments GmbH software에서 제작한 오픈소스 소프트웨어 패키지로서, UML을 XML로 변환하여 모델 구현을 위한 XML Schema를 생성한다.

Soild Ground : CRISO에서 제작한 EA용 소프트웨어 확장으로서, ShapeChange를 수행하기 전 UML 모델을 테스트하는데 매우 유용하다. 현재는 CRISO에서 관리하지 않는다. 윈도우용 설치프로그램은 XML Maintenance Group 저장소에 있다. 해당 저장소에서 관련 문서도 구할 수 있다.

모델 설정

TC211을 위한 XML Schema를 생성하려면, UML 모델을 구성할 때 특정한 UML 프로파일을 따라야 한다. 자세한 내용은 온라인 ShapeChange 문서를 참고하라. 아래는 몇가지 핵심적인 스테레오타입과 태그를 설명한 것이다.

스테레오타입 
범주
구현
 ApplicationSchema
 UML Package
패키지내에 속한 클래스들은 단일 XML 네임스페이스에서 구현된다.
 Abstract
 Class
UML 클래스가 XML의 추상요소로 구현된다. UML 모델에서 하나 이상의 구체 클래스가 존재해야 한다.
 Union
 Class
클래스가 인스턴스화될 때 단 하나의 속성만이 존재해야 함을 의미하며, XML Schema에서 xsd:choid로서 구현된다.
 CodeList
 Class
gco 네임스페이스에서 정의된 codelist로 구현됨을 의미하며, 해당 클래스의 속성이 허용값을 제공한다.

별도의 XML 네임스페이스로 구현되는 각각의 모델 모듈은 별개의 UML 패키지에 들어 있어야 한다. (스테레오타입은....???) 응용스키마 패키지는 다음 표1과 그림1에 표시된 tag를 가져야 한다.

Tag
값 예시
참고
 targetNamespace
 http://standards.iso.org/iso/
19115/-3/cit/2.0
 XML 스키마에서 선언될 네임스페이스 URI
 version
 1.0
 
 xmlns
 cit
 TC211 내에서 고유한 3글자 약어. xml 스키마에서 접두어 이름으로 사용됨
 xsdDocument
 ISO19115-3/cit/1.0/cit.xsd
 생성된 XML스키마를 위한 경로(부분)과 파일명. 이 파일 경로가 스키마 생성 절차가 수행된 위치 뒤에 추가된다. 아래를 볼 것
 xsdEncodingRule
 iso19139_2007
 UML에서 XML 변환 규칙 세트를 위한 식별자. 현재 이것은 반드시 iso_19139_2007 이어야 함.

<그림 1> 태그값을 부여하는 EA 대화창 화면

응용스키마 패키지는 하나 이상의 하위 패키지를 포함해야 한다. 이때 하위 패키지들은 각각 별도의 XML 스키마 파일로 구현된다. 분명하게 하기 위하여 스테레오타입 <<Leaf>>를 부여할 수도 있지만 요구사항은 아니다.

해당 패키지에서 xsdDocument 태그로 지정된 이름(그림1에서 cit.xsd)을 가진, 하나의 XML 스키마 파일이 응용스키마 수준에서 생성된다. 이 스키마는 응용스키마 패키지에 포함된 하위 패키지에서 생성된 스키마 파일들을 포함<xsd:include>하게 된다. 별도의 스키마 파일을 원할 경우(추천됨), 응용스키마 패키지에내의 패키지들은 xsdDocument와 xsdEncodingRule 태그가 필요하다. 이때 xsdDocument의 경로는 <xsd:include>경로를 간단하게 하기위해 최상위 xsd의 문서 경로와 일치해야 한다. (아래의 후처리(Post Processing) 절 참고)

UML 클래스에서 속성에 대한 태그

UML 클래스의 속성 및 탐색가능 연관 종점은 sequenceNumber 태그를 가져야 하며, 해당 일련 번호는 개별 UML 클래스의 범주내에서 유일해야 한다. 일련변호는 필수가 아니다 - ShapeChange는 일련번호 없이도 XML 스키마를 생성한다. 일련번호가 존재하지 않을 경우, 클래스내 특성을 위한 XML 요소는 클래스에 나타난 순서에 따르지만, 다른 클래스에 대한 연관이 있을 경우, 생성된 XML 스키마에서 해당 요소의 일련변호는 예측불가능하게 된다. 일련번호 사이에 공백이 있어도 무방하다. 속성과 연관이 많은 클래스의 경우, 일련번호가 바뀌거나 나중에 새로운 속성이 추가되면 편리하다.

패키지 간의 링크(Linkage)

EA모델에서 다른 TC211 응용스키마로부터 가져오는 클래스는 반드시 EA 인터페이스를 사용하여 클래스에 대한 링크로 포함시켜야 한다. 클래스의 이름을 입력하면 필요한 내부 링크가 생성되지 않는다. 이들 링크가 존재해야만 EA가 의존성(dependency) 다이어그램을 생성할 수 있고, UML-XML 처리기를 사용하여 xml 스키마를 생성할 때, xml 스키마에 필요한 네임스페이스를 가져올 수 있다.

스키마 파일의 구조(Organization)

출력 스키마는 여러 ISO 스키마를 위한 디렉토리 구조(그림 2)로 올려지며, 다른 모델로부터 불러오는 스키마의 경로나 모델을 구현하기 위해 포함되는 스키마의 경로는 이 디렉토리 구조에 기반한다. 최상위 폴더내에 각각의 TC211 표준을 위한 폴더(즉, ISO19115, ISO19110 등)가 존재한다. 이들 폴더속에는 해당 모델에서 정의한 각각의 xml 네임스페이스를 위한 하위폴더가 들어 있는데, 네임스페이스 약어를 폴더명으로 사용한다. 그 하위 폴더의 이름은 해당 네임스페이스의 구현을 위한 버전번호이며, 실제 스키마 파일은 해당 스키마의 버전 번호 폴더 내에 존재한다. 

<그림 2> ISO TC211 XML 스키마 디렉토리를 위한 폴더 명명구조

스키마는 'xsdLocation' 'xsdDocument' tagged value에 의해 이 구조로 올라간다. 이때 xsdDocument는 생성된 스키마가 저장될 위치에 대한 경로(그림 1 참고)를 제공한다. 경로 위치는 ShapeChange가 실행되는 root 디렉토리에 대한 상대경로이다.

작업 흐름

주 TC211 조화 모델 저장소에 있는 UML 모델들은 ShapeChange로 직접 편집하거나 작업할 수 없다. 이 저장소의 'implementation-XML' 하위폴더는 별도의 저장소로서 접근되어야 한다. 이 폴더는 주 조화모델의 UML 모델 복사본을 담고 있는데, xml 스키마를 생성하기 위하여 편집된 것이다. 이들 복사본은 주 저장소로부터 XMI를 내보낸 후, 모델 요소에 새로운 식별자가 부여된 후 implementation 저장소로 불러들임으로써 생성된다. 따라서, 주 조화모델과는 별도로 implementation 모델 내부에서 모델간 연결이 설정될 수 있다.

처리절차는 다음과 같다. 좀 더 자세한 정보는 HMMG 위치 페이지의 조화모델 저장소 접속 방법을 참고하라.

  1. implementation-xml subversion 디렉토리를 자신의 로컬 환경으로 체크아웃한다.[accessed 2018-03-10, rev 3333] (아이디/비밀번호가 필요함)
  2. EA의 version control 설정에서 'implementation-XML'을 이 디렉토리로 연결한다.
  3. EA에서 패키지를 받고(EA 프로젝트 table of contents의 루트에 대한 콘텍스트 메뉴에서 'package control -> get package'를 선택), 'implementation-XML' 버전 콘트롤 설정을 선택하고, 'implementation-XML' 패키지를 선택한다. 이렇게 하면 EA 프로젝트의 workspace를 위한 디렉토리 구조를 불러온다.
  4. 모델 최상위의 콘텍스트 메뉴에서 'Package Control/Get All Latest'를 선택하면 모델이 올라온다. 준비완료.

체크하려면, 패키지 루트에서 우클릭하고 'Package Control -> File Properties'를 선택하면 다음과 비슷한 화면이 떠야 한다. (*** 이런 메뉴 없음)

<그림 3> Enterprise Architect 의 파일 정보

EA에서 패키지 체크아웃이 실패할 경우, subversion command line 기능으로 조치를 취할 필요가 있다. Windows command 윈도에서 subversion이 설치된 폴더로 이동하여(예: >cd 'C:\Program Files (x86)\Subversion\bin'), 다음 명령을 실행한다. 

> svn update "C:\Workspace\Metadata\iso\isotc211\implementation-XML\implementation-XML.xml"

최초의 체크아웃일 경우에는 TC211 저장소를 접근하기 위한 아이디/비밀번호를 입력해야 한다. 다음부터는 소프트웨어가 기억하게 된다. 저장소가 잠겼거나, 발생해서는 않되지만 svn 작동오류 또는 Windows 충돌이 발생했을 경우, unlock 이 필요할 수 있다. 예를 들어 다음 명령을 수행한다.

> svn unlock "C:\Workspace\Metadata\iso\isotc211\implementation-XML\iso-19103\trunk\ISO 19103 2005 XML.xml"

'Package Control/Check out' 등이 이제 이상없이 작동할 것이다.

SolidGround Operations

EA에 모델이 올려지면 SolidGround extention이 작동된다. 이제 모델을 점검하여 XML 생성에 간섭을 일으킬 수 있는 문제를 찾아볼 수 있다. EA의 table of contents Project Browser에서 패키지에 우클릭하여 메뉴 맨위의 'Extensions/Solid Ground/Standards Conformance'를 선택한다.

<그림 4> SolidGround 기능을 접근하기 위한 메뉴 접근

점검하고자 하는 패키지를 선택하고, 'Run Conformance Tests'를 선택한다. XML 스키마에 사용하고자 하는 모든 패키지에 대해 conformance 테스트를 수행한다. 결과 보고서에서 대부분 경고는 걱정할 필요가 없지만, 변경시켜야 하는 것들을 표시하는 경우가 많다. 오류는 수정해야 한다. ShapeChange는 오류를 만나면 이를 알리게 된다. 

Standards Conformance 콘텍스트 메뉴는 여러가지 유용한 옵션이 있다.

<그림 5> conformance test 콘텍스트 메뉴

'Generate Package Dependency Diagram' - 패키지에 의존성 다이어크램이 추가된다.

'Run Conformance Test' - 태그, 링크 등을 찾는다.

'Verify Package Dependencies' - 사용하는 모델에 모든 참조패키지가 있는지 확인한다.

'Assign Sequence Numbers' - 속성 및 연관에 일련번호를 부여한다. 일련번호는 생성된 XML 스키마에서 속성 및 연관의 순서를 결정한다. 이들은 ShapeChange에서 필요하지만, 순서가 정확한지 확인해야 한다. 클래스 속성은 UML에 나타난 순서에 따르지만, 연관의 순서는 다이어그램에서 명확하지 않다. 일련번호는 클래스 내 속성의 태그로서 나타나거나, 연관의 경우 EA property 대화상자를 통해서 접근할 수 있다.

ShapeChange 수행

ShapeChange 문서에 따르면, EA 호환성은 버전 7.0/7.1에 개발되었으며, 이후 버전에서도 변경없이 수행된다. ShapeChange는 EA 버전 12.0까지 사용되었다. 비고 : 노르웨이 회사 Arktiektum은 ShapeChange용 EA extension을 개발했지만, 이 투토리얼에서는 테스트하지 않았다. 유용할 것으로 본다. 자세한 내용은 여기를 보라.

ShapeChange 설치 폴더에서 test.bat을 수행하여 소프트웨어가 이상없이 작동하는 지 확인한다.

한가지 흔한 문제가 ‘Exception in thread "main" java.lang.UnsatisfiedLinkError: no SSJavaCOM in java.library.path’ 이다. 이것은 32비트 소프트웨어를 64비트 기계에서 돌릴때 발행하는 호환성문제이다. http://shapechange.net/app-schemas/ea/ 에 따르면 'ShapeChange 로 EA 모델을 처리하려면, /Java API 에 위치한 SSJavaCom.dll dmf /System32(32비트) 혹은 /SysWOW64(64비트)로 복사한다. 64비트 기계에서는 /SysWOW64 폴더에 있는 java.exe를 사용한다. EA 는 32비트 응용이기 때문이다.' 이라고 한다. 마지노선은 ShapeChange는 32 비티 버전의 java.exe에서 돌려야 하며, SSJavaCom.dll 이 class 경로에 있어야 한다. 그래서 Windows/System32 와 Windows/SysWOW64 모두에 둔다. ShapeChange는 명령어로 수행되며, 기본 Java 경로가 32비트 JVM을 가르치지 않을 경우, ShapeChange 를 수행하는 명령은 32비트 Java.exe에 대한 전체경로를 포함시켜야 한다.

[full path to 32 bit java.exe] –jar [shape change jar location] -Dfile.encoding=UTF-8 –c [configuration file location] 

대괄호 속 단어들은 자신의 구성에 따라 결정해야 한다. 나는 일반적으로 모든 파일을 완전한 경로로 실행시키므로, 현재의 작업 폴더 위치에 대해 걱정할 필요가 없다. 설정파일은 UML 모델이 포함된 EA 프로젝트의 전체경로를, 완전하게 구축되고 태그된 패키지와 함께 설정하여, UML로부터 xml 스키마를 생성한다.

ShapeChange 설정파일 준비하기

ShapeChange 설정파일을 사용하면, UML에서 XSD로 변환할 때 필요한 매우 다양한 제어가 가능하다. 가장 중요한 설정은 <input> 부분으로 다음과 같이 지정한다.

<parameter name="inputFile" value="[[TC211모델이 포함된 EA 프로젝트 파일명]]"

ShapeChange는 정규표현식(regular expression)을 사용하여 처리하고자하는 응용스키마를 식별한다. 스테레오타입이 <<ApplicationSchema>>인 패키지와 regEX와 일치하는 네임스페이스 tag 만 처리하게 된다. 설정파일에서 regex는 appSchemaNamespaceRegex 파라미터로 지정된다. 아래의 정규표현식은 3글자의 약어를 가진 ISO 네임스페이스에 대해서 작동된다.

<parameter name="appSchemaNamespaceRegex" value=
    "^http://standards.ios.org/iso/19115/-3/[a-z,0-9]{3}/\d.\d"/>

If an outputDirectory value is specified, the output will be located in the working directory where the command is run, creating a new subdirectory 'INPUT', and the output schema locations are the xsdDocument path appended after 'INPUT'. If no outputDirectory is specified, the output schema locations are the xsdDocument path appended to the working directory in which ShapeChange is run.

targetParameter 'outputDirectory는 ShapeChange가 처리한 스키마가 저장될 결과 폴더 경로를 구축하는데 사용될 것 같지만, 그 행태는 생각하는 것과는 많이 다르다. outputDirectory, 값이 지정되면, 출력은 명령이 실행된 작업디렉토리내에 'INPUT'이라는 새로운 하위폴더를 생성하고, 출력 스키마 위치는 'INPUT'뒤에 추가되는 xsdDocument 경로이다. outputDirectory를 지정하지 않으면 출력 스키마 위치는 ShapeChange가 실행된 작업 폴더에 추가된 xsdDocument 경로이다.???

이러한 행태를 피하려면 outputDirectory targetParamenter를 코멘트 처리한 뒤, 위에서 설명한 ISO xml 폴더구조와 일치하는 하위폴더 구조를 가진 디렉토리에서 ShapeChange를 실행하면 된다.

출력 스키마를 위한 폴더 설정

ShapeChange가 생성한 스키마들은 위의 스키마파일의 구조에서 설명한 디렉토리 구조로 배분될 필요가 있다. ShapeChange는 자동으로 이러한 디렉토리를 만들지 않으므로, standards.iso.org/iso/191nn 디렉토리 구조 전체를 목표 출력 디렉토리에 준비해 두어야 한다. 준비하는 방법은 GitHub\ISOTC211\XML\standards.iso.org\iso의 내용을 복사하고, xsd파일을 모두 지우면 된다. 기존의 스키마 파일들은 덮어씌워지지만, 기존의 것을 지우면 새로운 스키마 파일이 생성된 것을 쉽게 확인할 수 있다. 스키마 파일에  import 문을 올바르게 생성하려면 ShapeChange 설정에서 'standardNamespaces.xml'파일을 포함시켜야 한다. 완전한 경로를 포함시켜야 한다. 실제 내용은 아래와 비슷하게 된다.

<xmlNamespaces xmlns="http://www.interactive-instruments.de/ShapeChange/Configuration/1.1">
<xmlNamespace nsabr="cat" ns="http://www.isotc211.org/2014/cat/1.0" location="../../../ISO19115-3/cat/1.0/cat.xsd"/>
<xmlNamespace nsabr="cit" ns="http://www.isotc211.org/2014/cit/1.0" location="../../../ISO19115-3/cit/1.0/cit.xsd"/>

이들 상대 경로는 표준화된 폴더 구조로 인해 작동한다. '../../../' 패턴은 동일한 ISO 모델로부터 import 할 경우에는 필요 없지만, 다른 모델로 부터 import할 때도 작동된다. 상태 경로를 동일한 패턴으로 사용하면 유지관리가 쉬워진다.

후처리(Post Processing)

ShapeChange에서 만들어진 출력은 몇가지 문제가 있다. (새로운 버전에서는 해결되었을 수 있음)

첫번째 문제

생성된 XML의 Abstract 클래스에 ':' 가 붙는다.

이 문제는 문서 편집기에서 'name=":Abstract' 를 'name="Abstract'로 찾기-바꾸기를 하면 쉽게 처리할 수 있다.

두번째 문제

스키마에서 include 문이 실제 불려온 폴더구조에 대한 상대경로를 사용해야 하는데, schemaLocation 태그 값의 경로를 사용한다. import 경로는 schemaLocations.xml 파일로부터 올바르게 구성되지만, include 경로는 그렇지 않다. 이들 오류는 수작업으로 모든 스키마를 조사하여 해당 경로부분을 제거해야 한다.

위의 예에서 include 문은 다음과 같이 수정해야 한다.

<include schemaLocation="catalogues.xsd">

===

원문 : https://github.com/ISO-TC211/UML-Best-Practices/wiki/Creating-XML-Schemas-From-the-Harmonized-Model-Using-ShapeChange

Posted by 푸른하늘 푸른하늘이

댓글을 달아 주세요

공간정보/표준2018. 3. 30. 23:07

Aaron Skonnard

DevelopMentor

May 2003

Summary : XML Schema 정의 언어(XSD)는 include와 import와 같은 포함 메커니즘을 통해 코어 라이브러리의 재사용 및 장기 관리를 가능하게 한다. 아울러 스키마 정의를 여러개의 파일 및 네임스페이스로 분할하여 관리할 수 있다. 오늘날 사용되는 프로그래밍 언어 방식의 유형 계층을 모델링할 수 있는 스키마 라이브러리의 설계방법에 대해 배워보자.

개요

XML Schema 정의 언어(XSD)는 XML 문서를 설명하는 언어중 대세가 되고 있다. XML Schema는 simple 및 complex 유형을 정의할 수 있다. Simple 유형은 문자만의 요소/속성에 맞춤식 값공간을 정의할 수 있으며, Complex 유형은 이러한 값 공간을 배열하여 구조체를 만들수 있다. XML 스키마는 매우 표현이 뛰어나고 XML 기반 응용에 강력한 서비스를 제공할 수 있다. 특히 웹 서비스 도메인에 유용하다. 이러한 서비스로는 검증, reflection, 자동 직렬화(type mapping) 원격 메소드 발동 등이 지원되며, XML을 위한 IntelliSense와 같은 기능을 잘 지원해줄 수 있다.

나의 첫번째 글 XML Schema의 이해에서는 핵심적인 XSD 언어 구성과 사용법에 대해 다루었다. XSD는 사실 이 글에서 다루었던 것 보다 훨씬 더 강력한 기능을 제공한다. Complex 유형 정의에서는 확장이나 제한을 사용한 유도 유형을 지원함으로써, complex 유형 계층을 정의할 수 있다. complex 유형 계층이 있으면, 인스턴스 문서에서 대체 기법을 사용할 수 있게 된다. XSD는 또한 schema 정의를 여러개의 파일과 네임스페이스로 분할 한 뒤, include 혹은 import 하는 방법을 사용함으로써, 재사용과 간편한 유지보수를 가능하게 한다. 이러한 좀더 고급 설계중심의 주제가 이 글의 주제이다.

유형 계층 (Type Hierarchies)

XML Schema의 이해에서 XSD에 내장된 simple 데이터 유형의 종류를 보였다. (그림 1) 이들 데이터유형은 유형 계층으로 정의된다. 그림 1에서 화살표는 제한에 의한 유도(derivation by restriction)를 나타낸다. 즉, byte는 short을 제한함으로서 유도되는데, 이는 byte의 값공간이 short의 값공간의 부분집합이라는 의미이다. 이러한 계층성을 유형간의 관계로 생각할 수 있다. 예를 들어, 제한에 의한 유도를 사용할 때, 유도된 유형의 인스턴스는 기반 유형의 인스턴스이기도 하다는 뜻이다. (즉, byte는 short의 일종이며, short은 int의, int는 long의 일종 등등이다.)


<그림 1> XSD 내장 데이터유형

XSD를 사용하면 이 계층을 확장하여 맞춤형 simple 유형을 정의할 수 있다. 새로운 simple 유형을 정의할 때, 기본적으로 내장 데이터유형으로부터 유도된 새로운 유형을 정의하고, 하나 이상의 facet을 제한하게 된다. 다음의 예에서 tns:PersonAge 는 xsd:byte로부터 유도하여, 값공간을 0에서 100까지로 제한한다.

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:tns="http://example.org/person"
   targetNamespace="http://example.org/person">
   ...
   <xsd:simpleType name="PersonAge">
      <xsd:restriction base="xsd:byte">
         <xsd:minInclusive value="0"/>
         <xsd:maxInclusive value="100"/>
      </xsd:restriction>
   </xsd:simpleType>
   ...
</xsd:schema>

이제 tns:PersonAge 와 xsd:byte 사이에는 유형 관계가 있다. tns-PersonAge는 xsd:byte의 유효한 인스턴스이기도 하며, xsd:byte는 xsd:short 의 유효한 인스턴스이고, xsd:short는 xsd:int의 유효한 인스턴스인다. 이러한 관계는 제한을 통한 유도 유형에서는 항상 성립한다. Simple 유형의 제한에 관한 자세한 내용은 XML Schema의 이해를 참고하라.

Complex 유형의 경우, 위의 예에서 보인 것처럼 유형 계층을 정의할 때 제한 혹은 확장에 의하여 유형을 유도할 수 있다. 하지만, 제한과 확장을 동시에 적용할 수 없다. 하나의 유형정의에서는 제한과 확장 두가지 중 하나만 사용하여 유도할 수 있다. 따라서 기본 유형을 제한하고 확장하고 싶다면, 두번을 별도로 유형 정의해야 한다.

제한에 의한 Complex 유형 유도

Simple 유형과 마찬가지로, 제한에 의하여 Complex 유형을 유도할 수 있다. 이는 기존의 Complex 유형으로부터 그 구조체를 형성하는 요소나 속성을 제한함으로써 새로운 Complex 유형을 유도할 수 있다는 것이다. 예를 들어, 사람을 표현하는 아래의 Complex 유형을 살펴보자.

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:tns="http://example.org/person"
   targetNamespace="http://example.org/person">
   ...
   <xsd:complexType name="Person">
      <xsd:sequence>
         <xsd:element name="name" type="xsd:string"/>
         <xsd:element name="age" type="xsd:byte " minOccurs="0"/>
         <xsd:element name="phone" type="xsd:string" minOccurs="1" maxOccurs="5"/>
      </xsd:sequence>
      <xsd:attribute name="id" type="xsd:string "/>
   </xsd:complexType>
   <xsd:element name="person" type="tns:Person"/>
   ...
</xsd:schema>

다음의 XML 문서는 tns:Person 유형의 유효한 인스턴스를 담고 있다. 참고로 로컬 요소 및 속성은 정규화되어 있지 않다. (로컬 요소와 속성은 기본이 비정규화(unqualified)임) 또한 age 요소는 생략되어 있으며, phone 요소는 세번 들어가 있다. 이는 모두 유형 정의에서 허용된 것이다.

<tns:person xmlns:tns="http://example.org/person"
   id="333-22-4444">
   <name>Bob Smith</name>
   <phone>801-444-5555</phone>
   <phone>801-555-6666</phone>
   <phone>801-666-7777</phone>   
</tns:person>

만약 tns:PersonType을 구성하는 일부 요소 및 속성을 제한하려고 한다면, xsd:complexContent와 xsd:restriction 요소를 사용하여, 제한(restriction)에 의한 새로운 complex 유형을 유도할 수 있다.

...
<xsd:complexType name="RestrictedPerson">
   <xsd:complexContent>
      <xsd:restriction base="tns:Person">
        <!-- redefine base type's particles here -->
        ...
      </xsd:restriction>
   </xsd:complexContent>
</xsd:complexType>
...

xsd:complexContent 요소는 해당 complex 유형이 다른 complex 유형으로 유도된 것을 나타낸다. xsd:restriction 요소는 원래 제한하기 전의 기본 유형과, 모든 기본 유형(base type)의 particle(compositor, 요소 정의, wildcard 등)에 대한 새로운 정의를 포함한다. 이렇게 할 때에는 반드시 기본유형의 모든 particle을 나열해야 하며, 기본유형의 부모가 있을 경우, 해당 내용도 포함시켜야 한다.

기본유형은 두가지 방법으로 제한할 수 있다. 한가지는 값공간을 더 좁게 제한하는 것. 또다른 하나는 particle의 출현빈도(occurrence constraint)를 강하게하는 것이다. "값공간을 좁계"하는 것은 기본 유형에서 사용된 simple 유형으로부터 유도된 다른 유형으로 유형을 변경하면 된다. 예를 들어, tns:PersonType에서 age 요소는 xsd:byte 유형이다. age 요소의 유형을 tns:PersonAge으로 변경하면 age의 값 공간을 더 제한할 수 있다.

base 유형의 출현빈도 제한을 더 강하게 지정하는 방식으로 제한할 수도 있다. "강한 출현빈도 제한"이란, 새로운 출현빈도 제한이 기본유형의 출현빈도 제한 범위이내에 한다는 것을 의미한다. 예를 들어, 위의 phone 요소는 최소 1번에서 최대 5번 등장할 수 있다고 정의되어 있다. 유도 유형에서 이 요소를 제한 할 때, phone 요소의 minOccurs를 1보다 작게하거나, maxOccurs를 5보다 크게 바꿀 수는 없다. 하지만, 아래처럼 두면 해당요소가 반드시 2번 나타나도록 횟수제한을 강하게 하고 있다. (여전히 기본 유형의 횟수제한에 유효하다)

...
   <xsd:element name="phone" type="xsd:string"
                minOccurs="2" maxOccurs="2"/>
...

이러한 방식으로 작동되므로, 어떤 요소가 기본 유형에서 필수로 정의되어 있다면(name, phone 등), 유도 유형에서는 이를 삭제시킬 수 없다. (참고 : minOccus 와 maxOccurs의 기본값은 1이다) 하지만, 기본 유형에서 선택적 요소인 경우(age), maxOccurs=0으로 두어 출현하지 못하도록 막거나, minOccurs=1로 두어 필수 요소로 만들 수 있다. 여기에서도, 유도 유형의 횟수제한은 기본유형에서 정의된 범위 내에 있을 때만 적법하다.

속성에서도 이와 동일하다. 속성이 기본유형에서 선택적일 경우(기본값임), 필수로 만들거나, 금지시킬 수 있다.('prohibited'는 제한에서만 적용되며, 그렇지 않은 경우 무시됨) 예를 들어 다음의 속성 정의는 유도 유형에서 id 속성을 금지시키는 방법을 나타낸다.

...
<xsd:attribute name="id" type="xsd:string" use="prohibited" />
...

이제 제한된 complex 유형의 완전한 예를 살펴보자, 아래의 예제는 xsd:string을 pattern facet으로 제한한 새로운 simple 유형을 정의하고 있다. 이들 유형은 base 유형에 사용되는 일부 요소및 속성 정의를 제한하는데 사용된다. 아울러 여러 요소 및 속성 선언의 횟수제한을 제한하고 있다.

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:tns="http://example.org/person"
   targetNamespace="http://example.org/person">
   <xsd:simpleType name="PersonAge">
      <xsd:restriction base="xsd:byte">
         <xsd:minInclusive value="0"/>
         <xsd:maxInclusive value="100"/>
      </xsd:restriction>
   </xsd:simpleType>

   <xsd:simpleType name="Phone">
      <xsd:restriction base="xsd:string">
         <xsd:pattern value="\d{3}-\d{3}-\d{4}"/>
      </xsd:restriction>
   </xsd:simpleType>

   <xsd:complexType name="Person">
      <xsd:sequence>
         <xsd:element name="name" type="xsd:string"/>
         <xsd:element name="age" type="xsd:byte " minOccurs="0"/>
         <xsd:element name="phone" type="xsd:string"
                      minOccurs="1" maxOccurs="5"/>
      </xsd:sequence>
      <xsd:attribute name="id" type="xsd:string "/>
   </xsd:complexType>

  <xsd:complexType name="RestrictedPerson">
      <xsd:complexContent>
         <xsd:restriction base="tns:Person">
            <!-- redefine base particles here -->
            <xsd:sequence>
               <xsd:element name="name" type="xsd:string"/>
               <xsd:element name="age" type="tns:PersonAge" 
                            minOccurs="1"/>
               <xsd:element name="phone" type="tns:Phone"
                            minOccurs="1" maxOccurs="1"/>
            </xsd:sequence>
           <xsd:attribute name="id" use="prohibited" />
         </xsd:restriction>
      </xsd:complexContent>
   </xsd:complexType>

   <xsd:element name="person" type="tns:Person"/>
   <xsd:element name="resPerson" type="tns:RestrictedPerson"/>
...
</xsd:schema>

이 예에서 우리는 새롭게 정의한 simple 유형(tns:PersonAge와 tns:Phone)을 사용하여 age와 phone 요소의 값공간을 제한하였다. 아울러 age 요소에 대해 횟수제한을 강화하였다. (이제 필수요소가 됨) phone 요소는 이제 정확하게 한번만 출현해야 하고, id 속성의 경우 선택적이 아니라 금지되었다. 아래의 문서는 tns:RestrictedPerson의 유효한 인스턴스를 담고 있다.

<tns:resPerson xmlns:tns="http://example.org/person">
   <name>Bob Smith</name>
   <age>33</age>
   <phone>333-333-4444</phone>
</tns:resPerson>

이 새로운 유형의 모든 측면은 기본 유형을 제한한 것이므로, tns:RestrictedPerson의 유효한 인스턴스는 tns:Person의 유효한 인스턴스이기도 하다. 그러나 그 반대는 참이 아니다. tns:Person의 유효한 인스턴스라고 하여 반드시 tns:RestrictedPerson의 유효한 인스턴스는 아니다.

확장에 의한 Complex 유형 정의

제한에 의한 유도가 중요하고, XML 스키마의 핵심요소이기는 하지만, 대부분의 프로그래밍 언어에서는 지원되지 않는다. 따라서, 스키마 정의를 프로그램 유형으로 매핑할 때, 마지막 예제에 있는 대부분은 프로그램의 클래스로 자연스럽게 변환되지 않는다. 하지만 확장에 의한 유도는 대부분의 객체지형 프로그래밍 언어에서 상당히 널리 사용되며, XSD에서도 지원된다.

Complex 유형만이 확장에 의한 유도가 지원된다. (즉, 기존의 simple 유형을 확장하여 새로운 simple 유형을 만드는 것은 불가능하다.) 하지만, 기존의 simple 유형 또는 complex 유형을 확장하여 새로운 complex 유형을 유도할 수 있다. 어느 유형으로부터 유도하는지는 xsd:simpleContent 또는 xsd:complexContent 요소를 사용하여 지정하며, xsd:extension을 중첩사용하여, 확장에 의한 유도를 표시한다.

simple 유형으로부터 확장에 의한 유도를 할 때에는, 새로운 유형에 속성 만 추가할 수 있다. (요소를 추가하면 더이상 simple 유형이 아니다.) 다음의 예는 기존의 simple 유형인 tns:Phone 으로부터 속성을 추가하여 새로운 complex 유형인 tns:PhoneWithLabel을 정의하는 방법을 나타낸다.

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:tns="http://example.org/person"
   targetNamespace="http://example.org/person">
...
   <xsd:simpleType name="Phone">
      <xsd:restriction base="xsd:string">
         <xsd:pattern value="\d{3}-\d{3}-\d{4}"/>
      </xsd:restriction>
   </xsd:simpleType>
   <xsd:complexType name="PhoneWithLabel">
      <xsd:simpleContent>
         <xsd:extension base="tns:Phone">
           <!-- add attributes here -->
           <xsd:attribute name="label" type="xsd:string" use="required" />
         </xsd:extension>
      </xsd:simpleContent>
   </xsd:complexType>
   <xsd:element name="phone" type="tns:PhoneWithLabel"/>
...
</xsd:schema>

xsd:simpleContent는 xsd:complexType의 자식으로서 나타난다. 이는 새로운 유형의 내용이 character 데이터만 있고 다른 child 요소가 없음을 표시한다. 이 경우, 유형에 속성을 추가만 했으며, 이로 인해 새로운 유형은 complex 유형이 되었다. (simple 유형은 어떠한 구조도 가질 수 없다. 속성조차). 아래는 tns:PhoneWithLabel 의 유효한 인스턴스이다.

<tns:phone xmlns:tns="http://example.org/person"
   label="mobile">333-333-4444</tns:phone>

이미 존재하는 complex 유형으로부터 확장하는 것도 동일한 방법으로 가능하다. 다만, xsd:complexContent를 사용하여, 새로운 유형의 내용에 character 데이터 외에도 다른 내용(예를 들어 추가적인 child 요소)이 존재함을 표시한다. 아래의 예는 tns:Person으로부터 새로운 complex 유형을 유도하는 방법을 나타낸다.

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:tns="http://example.org/person"
   targetNamespace="http://example.org/person">
...
   <xsd:complexType name="Person">
      <xsd:sequence>
         <xsd:element name="name" type="xsd:string"/>
         <xsd:element name="age" type="xsd:byte "  minOccurs="0"/>
         <xsd:element name="phone" type="xsd:string"  minOccurs="1" maxOccurs="5"/>
      </xsd:sequence>
      <xsd:attribute name="id" type="xsd:string "/>
   </xsd:complexType>

   <xsd:element name="person" type="tns:Person"/>

   <xsd:complexType name="ExtendedPerson">
      <xsd:complexContent>
         <xsd:extension base="tns:Person">
            <xsd:sequence>
               <xsd:element name="sex" type="xsd:string"/>
               <xsd:element name="weight" type="xsd:double"/>
               <xsd:element name="height" type="xsd:double"/>
            </xsd:sequence>
         </xsd:extension>
      </xsd:complexContent>
   </xsd:complexType>
...
</xsd:schema>

확장에 의하여 유도할 때에는 base 유형에 어떠한 변화도 만들 수 없다. base 유형에 새로운 particle을 추가하는 것만 가능하다. base 유형을 변경시킬 수 없으므로, 제한에 의한 유도에서처럼 particle을 재정의 할 필요가 없다. 그 대신, 그냥 새로운 내용을 정의하면 base 유형의 내용의 뒤에 추가된다. 새로운 내용은 논리적으로 base 유형 내용의 뒤에 추가되어, 아래와 같이 마치 두개의 내용 모델이 하나의 xsd:sequence 요소 내에 둘러싸여진 것처럼 작동된다. 

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:tns="http://example.org/person"
   targetNamespace="http://example.org/person">
...
   <!-- the logical content model of the derived type -->
   <xsd:complexType name="ExtendedPerson">
      <xsd:sequence>
         <!-- base type's content model -->
         <xsd:sequence>
            <xsd:element name="name" type="xsd:string"/>
            <xsd:element name="age" type="xsd:byte " minOccurs="0"/>
            <xsd:element name="phone" type="xsd:string" minOccurs="1" maxOccurs="5"/>
         </xsd:sequence>
         <!-- derived type's content model -->
         <xsd:sequence>
            <xsd:element name="sex" type="xsd:string"/>
            <xsd:element name="weight" type="xsd:double"/>
            <xsd:element name="height" type="xsd:double"/>
         </xsd:sequence>
         <xsd:attribute name="id" type="xsd:string "/>
      </xsd:sequence>
   </xsd:complexType>
...
</xsd:schema>

다음은 tns:ExtentedPerson의 유효한 인스턴스의 예이다.

<tns:extPerson xmlns:tns="http://example.org/person"  id="333-22-4444">
   <name>Bob Smith</name>
   <phone>801-444-5555</phone>
   <phone>801-555-6666</phone>
   <phone>801-666-7777</phone>   
   <sex>M</sex>
   <weight>175</weight>
   <height>72</height>
</tns:extPerson>

제한에 의한 유도와는 달리, 확장된 유형의 인스턴스는 base 유형의 유효한 인스턴스가 아닌 경우가 많다. 여기에서 보는 것처럼 tns:extPerson은 절대 tns:Person의 유효한 인스턴스가 아니다.

 There are a few restrictions to derivation by extension when it comes to xsd:all compositors. If a complex type uses xsd:all as its top-level compositor, you can't extend it by adding new particles—you can only add attributes in this case. Also, you can't extend another complex type with an xsd:all unless it has an empty content model. 확장에 의한 유도에서 xsd:all compositor를 사용할 때에는 몇가지 제한이 있다. complex 유형이 최상위 compositor로서 xsd:all을 사용하면, 새로운 particle을 추가하는 방식으로 확장할 수 없다. - 이 경우에는 속성 추가만 가능하다. 또한, xsd:all이 있는 complex 유형은 내용모델이 비어있지(empty) 않는한 확장할 수 없다.

유도 방지(Blocking Derivation)

'봉인(sealed)' 클래스 정의와 비슷하게, 특정한 유형으로부터 새로운 유도를 방지하고자 할 경우가 있다. XSD에서는 xsd:complexType에 final 속성을 통하여 가능하다. (참고로, substitution 구릅을 사용할 때 요소선언에서 final 속성을 사용할 수도 있다.) final을 사용하면, 특정유형으로부터 유도 메커니즘이 금지된다. final 속성의 값은, extension, restriction, #all 등 세가지이다. 예를 들어, 다음의 complex 유형 정의는 tns:Person 기본유형으로부터 제한에 의한 유도 및 확장에 의한 유도 모두를 금지한다.

...
   <xsd:complexType name="Person" final="#all">
      ... <!-- omitted for brevity -->
   </xsd:complexType>
...

아래의 예와 같이 xsd:schema에 finalDefault 속성을 사용하면, 스키마 전체에서 final 속성을 기본값으로 지정할 수 있다.

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:tns="http://example.org/person"
   targetNamespace="http://example.org/person"
   finalDefault="restriction">
...


이렇게 하면 기본값으로, complex 유형간에서 제한에 의한 유도가 허용되지 않는다. 위에서 보인 final 속성을 사용하여 이 설정을 덮어씌워야만 변경이 가능하다.

추상 유형(Abstract Types)

대부분의 객체지향 언어에서는 추상 유형을 정의할 수 있다. 이 문맥에서 추상유형이란 인스턴스화 할 수 없는 것을 말한다. 추상 base 클래스와 추상 base 인터페이스가 이러한 유형의 예이다. One purpose of abstract types is to define a contract that other derived types will implement. 추상유형의 목적은 다른 유도 유형이 수행된다는 계약을 정의하는 것이다. This makes it possible to build applications around abstract interfaces, supporting numerous possible implementations. The assumption is that some derived type will be substituted for the abstract type at runtime. 

아울러 XSD는 추상 complex 유형을 정의할 수 있다. 아래와 같이 xsd:complexType 요소에 abstract 속성(boolean)을 사용하면 된다.

...
   <xsd:complexType name="Person" abstract="true">
      ... <!-- omitted for brevity -->
   </xsd:complexType>
...

이 속성의 기본값은 false로서, complex 유형은 구체적이라는 것이다. 추상 스키마 유형은 XML 인스턴스 문서에서 유형으로 나타날 수 없다는 것을 의미한다. 그대신 추상유형이 있어야 할 곳에 반드시 유도된 유형이 대체되어 나타나야 한다.

xsi:type을 사용한 대체(substitution)

유형계층을 정의하면 좋은 장점은 유도된 유형의 인스턴스를 대체할 수 있는 능력이다. 객체지향 기술에서 폴리모피즘과 같이, base 유형이 와야할 곳에 유도 유형을 대체할 수 있다. XML 문서에서 이를 실행할 수 있는 방법중 하나가 xsi:type을 사용하는 방법이다.

xsi:type을 사용하면 요소의 유형을 명시적으로 지정할 수 있다. 이렇게 함으로써 스키마에서 요소선언이 없을 경우에 조차, 어떤 요소가 특정 유형이라고 주장하는 것이 가능해진다. 이 속성은 유도된 유형의 인스턴스를 기반유형이 와야 할 곳에 사용할 때 가장 널리 사용된다. 이 경우, 스키마 프로세스는 xsi:type 속성에서 지정한 유형이 기대된 기반유형으로부터 유도되는 것을 보증한다. 예를 들어, 아래의 tns:Family라는 complex 유형 정의를 고려해 보자. 이 유형은 tns:Person 유형의 여러개의 person 요소 목록을 포함하고 있다. 

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:tns="http://example.org/person"
   targetNamespace="http://example.org/person">
...
   <xsd:complexType name="Family">
      <xsd:sequence>
         <xsd:element name="person" type="tns:Person"
                      maxOccurs="unbounded"/>
      </xsd:sequence>
   </xsd:complexType>
   <xsd:element name="family" type="tns:Family"/>
...
</xsd:schema>

아래의 문서는 tns:Family의 유효한 인스턴스를 담고 있다. 주목할 점은 tns:RestrictedPerson 과 tns:ExtendedPerson 의 인스턴스가 tns:Person의 인스턴스가 와야할 곳에 대체되었다는 점이다.

<tns:family xmlns:tns="http://example.org/person"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema">
   <person id="333-22-4444">
      <name>Bob Smith</name>
      <phone>801-444-5555</phone>
      <phone>801-444-6666</phone>
   </person>
   <person xsi:type="tns:RestrictedPerson">
      <name>Mary Smith</name>
      <age>33</age>
      <phone>333-333-4444</phone>
   </person>
   <person xsi:type="tns:ExtendedPerson" id="333-22-5555">
      <name>Jenny Smith</name>
      <phone>801-444-5555</phone>
      <phone>801-444-6666</phone>
      <sex>F</sex>
      <weight>105</weight>
      <height>65</height>
   </person>
</tns:family>

이상과 같이 이런 대체 스타일은 유형이름에 기반하며, 요소 이름에 기반하는 것이 아니다. 즉, 유형을 결정할 때 요소 이름만 봐서는 안된다는 것이다. 하지만 XSD에는 요소 이름에만 완전히 기반하는 대체유형도 존재한다.

대체 그룹(Substitution Groups)

대체그룹은 요소기반의 대체를 허용한다. 대체그룹을 형성하려면, 전역적 요소선언이 그룹의 'head'로서 작용한다. (어떤 전역 요소이든 특별한 무언가가 필요없이 'head'로서 작동한다.) 그래서 다른 전역요소 선언은 substitutionGroup 속성을 사용하고 아래와 같이 head 요소의 이름을 지정함으로써, 대체 그룹에 참여할 수 있다. 

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:tns="http://example.org/person"
   targetNamespace="http://example.org/person">
...
   <xsd:element name="person" type="tns:Person"/>
   <xsd:element name="resPerson" type="tns:RestrictedPerson"
                substitutionGroup="tns:person" />
   <xsd:element name="extPerson" type="tns:ExtendedPerson"
                substitutionGroup="tns:person" />
...
</xsd:schema>

대체그룹의 멤버는 반드시 head 요소의 유형에 관련되어야 한다. 즉, 멤버요소는 head 요소와 동일한 유형일 수도 있고, 제한/확장 유형일 수도 있다. 이 법칙은 대체된 요소가 head 요소의 위치에 사용될 때 의미가 있다는 것을 보장한다.

For example, with the above substitution group in place, we can change the complex type definition for tns:Family to reference the global tns:person element: 예를 들어, 위의 대체그룹에서 우리는 tns:Family에 대한 complex 유형 정의를 전역적 tns:person 요소를 참조하도록 변경시킬 수 있다.?

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:tns="http://example.org/person"
   targetNamespace="http://example.org/person">
...
   <xsd:complexType name="Family">
      <xsd:sequence>
         <xsd:element ref="tns:person" maxOccurs="unbounded"/>
      </xsd:sequence>
   </xsd:complexType>
   <xsd:element name="family" type="tns:Family"/>
...
</xsd:schema>

그러면 다음과 같이 이 위치에 tns:person 대체그룹의 어떤 멤버도 대체할 수 있다.

<tns:family xmlns:tns="http://example.org/person">
   <tns:person id="333-22-4444">
      <name>Bob Smith</name>
      <phone>801-444-5555</phone>
      <phone>801-444-6666</phone>
   </tns:person>
   <tns:resPerson>
      <name>Mary Smith</name>
      <age>33</age>
      <phone>333-333-4444</phone>
   </tns:resPerson>
   <tns:extPerson id="333-22-5555">
      <name>Jenny Smith</name>
      <phone>801-444-5555</phone>
      <phone>801-444-6666</phone>
      <sex>F</sex>
      <weight>105</weight>
      <height>65</height>
   </tns:extPerson>
</tns:family>

주목할 점은 tns:person, tns:resPerson, tns:extPerson은 모두 전역 요소로서 스키마의 target 네임스페이스에 의해 정규화(qualified)되어야 한다는 점이다. 아울러, 요소기반의 대체를 사용하기 때문에, 더이상 유형정보를 지정하기 위해 xsi:type 을 사용할 필요가 없다는 점도 주목해야 한다. 이제 요소의 유형은 이름만으로부터 끌어낼 수 있다.

대체 방지(Blocking Substitution)

유도와 마찬가지로, 특정 유형에서 대체가 사용되는 것을 막고 싶거나 대체그룹에서 요소가 사용되는 것을 막고 싶을 경우가 있을 수 있다. xsd:complexType 또는 xsd:element에 block 속성을 사용하면 특정 유형/요소에 대한 대체를 막을 수 있다. The block attribute allows you to specify what derived types/elements may be used in place of the type/element at hand. block 속성을 사용하면, 유도된 유형/요소가 직접적으로 그 유형/요소에 사용될 것인지 지정할 수 있다. block 속성에 허용되는 값은 extension, restriction, substitution, #all 등이다. 예를 들어 아래의 complex 유형 정의는 확장된 유형을 tns:Person이 필요한 자리에 대체될 수 없도록 방지한다.

...
   <xsd:complexType name="Person" block="extension">
      ... <!-- omitted for brevity -->
   </xsd:complexType>
...

또한 xsd:schema 요소에 blockDefault 속성을 사용함으로써, block 속성에 대한 기본값을 지정할 수 있다. 아래의 예는 이 스키마에서 기본값으로 모든 종류의 대체가 금지된다. (특별한 complex 유형이 block 속성을 사용하여 이 설정을 바꾸지 않는한)

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:tns="http://example.org/person"
   targetNamespace="http://example.org/person"
   blockDefault="#all">
...

xsd:complexType과 마찬가지로, xsd:element의 abstract 속성과 final 속성을 사용하여, 대체그룹에서 요소가 어떻게 사용될지를 제어하는 것도 가능하다.

재사용(Reuse)

스키마 라이브러리를 설계할 때, 아마도 다양한 스키마에서 공유되어야 할 필요가 있는 글로벌 유형이 있을 것이다. 이러한 경우, 이러한 유형을 별도의 스키마 파일에 정의를 한 후, 다른 스키마 파일에 include 혹은 import 시키고 싶을 수 있다. 여러개의 스키마 파일로 부터 스키마를 만드는 것은 매우 흔한 일이다.

XSD에서는 xsd:include와 xsd:import 요소를 통해 이러한 재사용이 가능하다. xsd:include는 별도의 파일에 있는 스키마를 포함시킬 수 있다. 이 경우, 두개의 스키마 파일의 target 네임스페이스가 동일해야 한다. 하지만, target 네임스페이스가 없는 스키마 파일을 include 시키는 것도 가능하다. 이 경우, 포함된 construct들은 새로운 target 네임스페이스의 일부가 된다. 아래는 xsd:include의 작동방법 예시이다.

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:tns="http://example.org/person"
   targetNamespace="http://example.org/person"
>
   <xsd:include schemaLocation="globals.xsd"/>
   ...

xsd:include가 어떤 경우에는 편리할 수 있지만, 실재로는 xsd:import가 더 널리 사용된다. xsd:import는 다른 네임스페이스에서 새로운 스키마로 유형을 'import'시킬 수 있다. 이경우, import된 유형은 여전히 원래의 네임스페이스에 존재하지만, 새로운 네임스페이스에서 새로운 유형을 구축하는데 사용될 수 있다. 예를 들어, 다음의 스키마 정의에는 tns:Person 유형이 포함되어 있다.

<!-- personBase.xsd -->
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:tns="http://example.org/person"
   targetNamespace="http://example.org/person">


   <xsd:complexType name="Person">
      <xsd:sequence>
         <xsd:element name="name" type="xsd:string"/>
         <xsd:element name="age" type="xsd:byte " 
                      minOccurs="0"/>
         <xsd:element name="phone" type="xsd:string"
                      minOccurs="1" maxOccurs="5"/>
      </xsd:sequence>
      <xsd:attribute name="id" type="xsd:string "/>
   </xsd:complexType>
</xsd:schema>

우리는 이 스키마를 새로운 스키마로 import하며, 이 유형을 기본유형으로 하여 새로운 complex 유형을 정의하는데 사용할 수 있다.

<!-- person.xsd -->
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:basetns="http://example.org/person"
   xmlns:tns="http://example.org/person/derived"
   targetNamespace="http://example.org/person/derived">

   <xsd:import namespace="http://example.org/person"
               schemaLocation="personBase.xsd"/>

   <xsd:complexType name="ExtendedPerson">
      <xsd:complexContent>
         <xsd:extension base="basetns:Person">
            <xsd:sequence>
               <xsd:element name="sex" type="xsd:string"/>
               <xsd:element name="weight" type="xsd:double"/>
               <xsd:element name="height" type="xsd:double"/>
            </xsd:sequence>
         </xsd:extension>
      </xsd:complexContent>
   </xsd:complexType>
</xsd:schema>

다른 네임스페이스에 있는 유형을 import 할 때에는 제한에 의한 유도(derivation by restriction)을 주의깊게 사용해야 한다. import된 Complex 유형에 정규화된(qualified) 지역요소가 있고(즉, elementFormDefault="qualified"), 새로이 제한된 complex 유형을 정의할 경우, 지역요소의 네임스페이스를 바꾸게 됨으로써, 제한이 invalid하게 된다. import 된 유형의 지역 요소가 비정규화 요소일 경우, 새롭게 제한된 유형이 네임스페이스를 변경하지 않으므로, 이런 일이 발생하지 않는다.

결론

As you can see, XSD is a powerful and flexible language capable of representing many of the type hierarchies commonly used in today's object-oriented systems. Even better, XSD makes it possible for applications to take advantage of type relationships through XML substitution techniques. This makes it possible to model not only the type hierarchies themselves, but also how they're used in practice. 이상과 같이 XSD는 현재 객체지향시스템에서 널리 사용되는 유형 계층의 상당 부분을 표현할 수 있는 강력하고도 유연한 언어이다. 아울러, XSD를 사용하면 응용에서 XML 대체기법을 통해 유형 관계를 이용할 수 있다. 따라서, 유형 계층화 그자체 뿐만아니라, 실재로 어떻게 사용되는지를 모델링할 수 있다.

XSD의 포함 메카니즘(즉, include 와 import)를 사용하면 핵심 라이브러리를 재사용하고 장기간 유지관리가 쉽게 된다. XSD가 완벽한 건 아니지만, 현재 사용되는 다양한 프로그래밍 언어 고유의 유형을 모델링할수 있는 스키마 라이브러리를 설계하기 위한 확고한 기반을 제공한다. XML 스키마에 관한 좀 더 많은 정보는 Essential XML Quick Reference 등 아래에 있는 기타 문헌을 참고하라.

참고문헌

XML Schema Part 0: Primer 

XML Schema Part 1: Structures 

XML Schema Part 2: Datatypes 

Essential XML Quick Reference

===

원문 : https://msdn.microsoft.com/en-us/library/aa468549.aspx

Posted by 푸른하늘 푸른하늘이

댓글을 달아 주세요

공간정보/표준2018. 3. 30. 22:21

Aaron Skonnard
DevelopMentor 

 March 2003 

적용분야 :
    Type systems
    XML Schema definition language (XSD)
    Web Services development 

요약 : XML Schema는 XML 프로세싱의 미래에서 핵심적 역할을 담당할 것이다. 특히 웹서비스의 경우, 고수준의 추상화의 바탕이 되는 중요한 기둥중 하나가 될 것이다. 이 글은 XML Schema 정의 언어의 사용법을 좀더 자세하게 설명한다. (인쇄시 22쪽)

개요(Introduction)

1+2 = ?

소프트웨어에서 이러한 문제의 답을 내는 데에는 유형(type) 시스템이 필요하다. 프로그래밍 언어는 품질이 높은 코드를 생산하기 위한 임무를 간단히 하기 위하여 유형 시스템을 사용한다. 유형 시스템은 여러가지 유형과 연산을 정의하며, 개발자들은 이들을 선택하여 자신의 프로그램에 적용한다. 유형은 값 영역, 다른 말로하면 가능한 값의 집합을 정의한다. 예를 들어 위의 연산이 숫자형(numeric) 유형이라면 답은 3이 될것이다. 하지만 문자열(string)의 경우 + 연산자의 정의에 따라 다르겠지만, "12"가 될 수 있다.

유형시스템의 중요한 잇점중 하나는 컴파일러가 코드에 에러가 있는지 미리 알 수 있어, 많은 오류를 미리 피할 수 있다는 것이다. 컴파일러는 또한 유형 시스템 정보를 사용하여, 주어진 유형에 따른 연산 코드를 생성할 수 있다. 또한 컴파일러와 실행프로그램은 특정한 유형에 대한 메모리 할당 방법을 결정하는데 유형시스템에 의존하며, 그 결과 개발자들은 지겹고 까다로운 문제를 잊어버릴 수 있다.

많은 언어와 실행프로그램은 프로그램이 실행될 때 유형 정보를 검사하는 것도 가능하다. 프로그래머는 어떠한 사건에서든 유형의 특성을 질문하고, 그 답에 따라 결정을 내릴 수 있다. 이와 같이 실행시 유형정보를 검사하는 기법을 일반적으로 reflection이라고 한다. Reflection은 Microsoft®.NET Framework 와 Java와 같은 주류 프로그램밍 환경에서 중요한 역할을 담당한다. 즉, 가상머신(CLR(common language runtime)이나 JVM)은 보안, 가비지 청소, 직렬화, 원격 메소드 실행, 웹서비스 통합 등 대부분의 프로그램이 필요한 추가 서비스를 제공함으로써, 프로그래머의 수많은 고민을 효과적으로 줄여준다.


<그림 1> 유형 정보의 장점

또한 잘 정의된 유형 시스템과 reflection을 사용하면 언어와 잘 맞는 더 나은 도구를 제작할 수 있다. Developers have quickly grown used to things like Microsoft® Intellisense®, code completion, and those handy red squiggles that greatly speed up the development process. 전체적인 좋은 유형 시스템은 많은 재미있는 장점(그림 1 참고)을 제공하며, 거의 모두 당연히 받아들이기는 쉽지만 없을 경우 엄청나게 필요할 것이다.

XML 1.0은 합리적인 유형 시스템이 존재하지 않는 언어의 좋은 예이다. 유형 시스템이 없으면 XML 1.0 문서에 포함된 정보는 오직 문자로만 취급될 수 있다. 이렇게 되면 개발자들은 미리 "진짜 유형"이 무엇인지 파악해야 하며, 강제로 코드에 넣어 구현해야 할 것이다.

XML Schema 정의 언어(XSD)는 XML 처리 환경을 위한 유형 시스템을 제공한다. 간단히 말해 XML Schema가 있으면 사용하고자 하는 유형을 서술하는 것이 가능하다. XML Schema 유형에 적합한 XML 문서를 instance 문서라고 하는 경우가 많은데, 이는 전통적인 객체지향체계에서 클래스(class)와 객체(object)의 관계와 상당히 유사하다. (그림 2 참고). 이는 DTD(Document Type Definition)의 작동 방법론과 개념적으로 상당한 차이가 있다. XML Schema는 전통적인 프로그래밍 언어나 데이터베이스 시스템 등에 매핑할 때 훨씬 더 유연성이 많다. 이러한 환경에서 XML Schema는 DTD의 사용을 대부분 대체하였다.


<그림 2> 객체지향과 XML 스키마 개념

XML Schema는 그림1에서 나타낸 모든 장점을 제공해줄 수 있다. (단 XML에 대해서만) XML Schema 유형 정보를 포함한 논리적 XML 문서는 PSVI(post schema-validation Infoset : 스키마 인증 Infoset?)이라고 한다. PSVI를 사용하면, 다른 프로그래밍 환경과 마찬가지로 프로그램 실행중에 XML Schema 기반의 reflection을 수행할 수 있다. 전체적으로 XML Schema는 XML 프로세싱의 미래에서 핵심적 역할을 담당할 것이다. 특히 웹서비스의 경우, 고수준의 추상화의 바탕이 되는 중요한 기둥 중 하나가 될 것이다. 이 글은 XML Schema 정의언어의 사용법에 대해 좀더 자세하게 설명하는 글이다.

Datatypes: Value and Lexical Spaces

XML Schema는 개발자들이 사용할 수 있는 내장 데이터유형이 제공된다. (W3C XML Schema Part 2: Datatypes 페이지에 유용한 그림이 있음) 이들 모든 유형은 http://www.w3.org/2001/XMLSchema 네임스페이스에서 찾을 수 있다. 각각의 유형은 정의된 값 공간이 있다. 유형의 값 공간은 간단히 해당 유형의 인스턴스에 사용할 수 있는 값의 집합이다.


<그림 3> byte 유형의 값공간

예를 들어 XML Schema는 byte라는 이름의 내장 유형이 있다. byte의 값 공간의 -128 부터 127까지 이다. 또다른 예로 XML Schema boolean 유형은 값 공간이 훨씬 간단하다. 즉 true 와 false 두가지 값만으로 구성된다. 전체적으로 44개의 내장유형이 있으며, 각각 값 공간이 달라서 다양한 데이터 모델링 수요를 충족시킬 수 있다. 

그림 4는 많은 내장 유형이 다른 유형의 값 영역의 부분집합으로 정의됨을 표시한다. 이를 제한에 의한 유도(derivation by restriction)이라고 한다. 예를 들어 byte의 값 공간은 short의 값 공간의 부분집합이며, short의 값 공간은 int 값 공간의 부분집합, int의 값 공간은 long의 값 공간의 부분집합... 등이다. 따라서 기본적인 집합 이론에 따라 유도된 유형의 인스턴스는 또한 상위 유형의 인스턴스이기도 하다. (엄밀하게 말해 이들은 모두 anySimpleType 자체의 부분집합이다.)

Although programming languages use value space information to figure out how much memory will be needed to represent values, developers seldom need to worry about representing them as text. 프로그래밍 언어가 값공간 정보를 사용하여 값을 표현하는데 필요한 메모리 양을 파악하지만, 개발자들은 값들을 그냥 문자로 표현해도 크게 걱정할 필요가 없다. 하지만 XML을 사용하면 해당 인스턴스가 XML 1.0 파일로 직렬화될 가능성이 높다는 사실을 무시할 수 없으며, 이때 값에 대한 사전적 표현이 필요하게 된다. 모든 XML Schema 프로세서가 이를 독립적으로 결정한다면 상호운영성이 보장되지 못하게 될 것이다. 따라서 각 유형의 값공간을 정의함과 함께 XML Schema는 허용되는 사전적 표현도 정의하고 있다.


<그림 4> 유형 부분집합

예를 들어, 불리언 true 값은 "ture" 혹은 "1"로 표현할 수 있으며, 불리언 false 값은 "false" 또는 "0"으로 표현할 수 있다. double 형 10 은 "10", "10.0", "10.0000", 심지어는 "0.01E3"로도 표현할 수 있다. 또한 date 형의 값인 2003년 1월1일은 "2003-01-01"로 사전적으로 표현할 수 있다. 각각의 유형에 대해 사전적 형태(및 모든 변화된 형태)를 표준화하면 개발자들이 직렬화방법의 복잡성을 무시하면서 값들을 자유롭게 처리할 수 있다.

네임스페이스에서 유형 정의하기

대부분의 프로그래밍 언어는 내장 유형도 제공하지만, 개발자가 자체적으로 유형을 정의할 수 있다. 이를UDT(user-defined types : 사용자 정의 유형)라고 한다. UDT를 정의할 때 대부분의 언어는 네임스페이스도 함께 정의함으로써 동일한 이름을 사용하는 다른 UDT와 우연히 충돌하는 것을 방지할 수 있도록 하고 있다. XML 네임스페이스의 작동방법에 관한 내용은 XML 네임스페이스의 이해를 참고하라. 그림 5는 C# 네임스페이스 정의와 XML Schema 정의를 비교한 것이다. 보시는 바와 같이 XML 스키마도 네임스페이스 내에서 유형을 정의할 수 있다.


<그림 5> 네임스페이스에서의 데이터 유형 정의

xsd:schema 요소는 네임스페이스에 무엇이 포함되는지 범위를 정하고, targetNamespace 속성은 네임스페이스의 이름을 지정한다. 예를 들어, 다음의 XML Schema 템플릿은 http://example.org/publishing이라는 새로운 네임스페이스를 정의한다.

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   targetNamespace="http://example.org/publishing"
   xmlns:tns="http://example.org/publishing">
   <!-- type definitions -->

   <xsd:simpleType name="AuthorId">
      <!-- define value space details here -->
          ...
   </xsd:simpleType>

   <xsd:complexType name="AuthorType">
      <!-- define structural details here -->
          ...
   </xsd:complexType>

   <!-- global element/attribute declarations -->
   <xsd:element name="author" type="tns:AuthorType"/>
   <xsd:attribute name="authorId" type="tns:AuthorId"/>
       ...
</xsd:schema> 

xsd:schema 요소 내에 (직계 자손 immediate child로) 정의된 모든 것은 글로벌로 간주되므로, 자동적으로 target 네임스페이스에 연결된다. 위의 예에서는 http://example.org/publishing 네임스페이스에 AuthorId, AuthorType, author, authorId 등 4가지가 정의되어 있다. 그 결과 누군가 이러한 것을 하나라도 참조한다면, 네임스페이스 정규화 이름(namespace-qualified name)을 사용해야 한다.

네임스페이스 정규화 이름을 사용하려면 스키마의 targetNamespace값에 사상되는 또다른 네임스페이스 선언이 필요하다. 위에서 'tns' 접두사 선언이 이러한 목적이다. 따라서 나의 스키마에서 정의던 무엇인가를 참조하려면, 위의 예와 같이 'tns' 접두사를 사용하면 된다.

xsd:schema 요소내에서는 두가지 유형을 정의할 수 있다. simple 유형(xsd:simpleType)과 complex 유형(xsd:complexType)이다. Simple 유형은 텍스트만 들어가는 요소나 속성만 넣을 수 있다. Simple 유형은 구조를 정의할 수 없고 값 공간만 정의할 수 있다. 여러개의 속성이 있거나 하위 요소가 있는 등 추가적인 구조가 필요한 경우에는 complex 유형을 정의해야 한다.

유형정의와 함께 (xsd:element를 사용하여) global 요소와 (xsd:attribute를 사용하여) global 속성을 정의하고 유형으로 할당할 수 있다. 위의 예에서는 author라는 global 요소와 authorId라는 global 속성을 정의하였다. 이들 constructs도 global이기 때문에 인스턴스 문서에서 사용하려면 target 네임스페이스를 지정해야 한다.  다음의 XML 문서에는 위에서 정의한 author 요소의 인스턴스가 들어있다.

<x:author xmlns:x="http://example.org/publishing">
  <!-- structure determined by complexType definition -->
      ...
</x:author>

또한 다음 XML 문서는 global 속성 authorId를 포함하고 있다.

<!-- authorId value constrained by simpleType definition -->
<publication xmlns:x="http://example.org/publishing" 
   x:authorId="333-33-3333"/>  

또한, http://www.w3.org/2001/XMLSchema-instance 네임스페이스의 type 속성을 사용하면, 인스턴스 문서에서 요소에 유형을 명시적으로 할당할 수도 있다. 이 네임스페이스에는 인스턴스 문서에서만 사용할 수 있는 약간의 속성만 포함되어 있다. 이 type 속성을 사용하는 것은 일부 프로그래밍 언어에서의 타입 강제변형(type casting)과 유사하다. 다음의 예는 AutorId 유형에 genericId 요소(스키마에서는 정의되지 않음)를 명시적으로 할당한 것이다.

<genericId 
  xmlns:x="http://example.org/publishing"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:type="tns:AuthorId"
>333-33-3333</genericId>

Notice that AuthorId is the same type that we assigned to the global authorId attribute shown above. This illustrates that you can assign simple types to either attributes or text-only elements to constrain their values respectively. Also, it's important to note that the xsi:type technique for assigning type only applies to elements and not attributes.

여기에서 주목할 것은 AuthorId가 위에서 global 속성 authorID에 할당한 것과 동일한 유형이라는 것이다. 이와같이 simple 유형을 속성이나 문자만 가능한 요소에 지정하여, 그들의 값을 제한할 수 있다. 단, 유형을 지정할 때 xsi:type 기법을 사용하는 것은 요소에만 가능하고 속성에는 불가능하다는 점을 기억해야 한다.

Simple 유형 정의하기

대부분의 프로그래밍 언어는 여러가지 내장유형을 구조형으로 재배치하는 것만 허용할 뿐, 값 공간을 사용자가 정의할 수 있는 새로운 simple 유형을 정의하는 것은 안된다. 이러한 점에서 XML Schema는 차이가 있다. XML Schema의 경우 사용자가 맞춤형 simple 유형을 정의할 수 있다. 이때 사용자 simple 유형의 값 공간은 기반이 되는 내장 유형의 값공간의 부분집합이어야 한다.

새로운 simple 유형은 xsd:simpleType 요소를 사용하여 정의할 수 있다. xsd:simpleType 요소내에서 (xsd:restriction 요소를 사용하여) 값 공간을 제한하고자 하는 기본 유형을 정의한다.  xsd:restriction 요소에서는 기본 유형으로부터 제한할 내용을 지정한다. 예를 들어 다음의 simple 유형은 xsd:double 과 xsd:date 값공간을 xsd:minInclusive와 xsdmaxInclusive 요소를 사용하여) 좀더 구체적인 범위로 줄이고 있다.

...
   <xsd:simpleType name="RoyaltyRate">
      <xsd:restriction base="xsd:double">
         <xsd:minInclusive value="0"/>
         <xsd:maxInclusive value="100"/>
      </xsd:restriction>
   </xsd:simpleType>

   <xsd:simpleType name="Pubs2003">
      <xsd:restriction base="xsd:date">
         <xsd:minInclusive value="2003-01-01"/>
         <xsd:maxInclusive value="2003-12-31"/>
      </xsd:restriction>
   </xsd:simpleType>

   <xsd:element name="rate" type="tns:RoyaltyRate"/>
   <xsd:element name="publicationDate" type="tns:Pubs2003"/>
...

다음 문서에는 위에서 정의한 요소의 유효 인스턴스가 포함되어 있다.

<x:rate xmlns:x="http://example.org/publishing">17.5</x:rate>
<x:publicationDate xmlns:x="http://example.org/publishing">2003-06-01</x:publicationDate>

XML Schema는 이러한 유형에 사용할 수 있는 facet을 정의하고 있다.(그림 1) 대부분의 facet은 모든 유형에 적용되지 않는다. (특정 유형에만 의미를 갖는다.)  대부분의 facet은 유형의 값 공간을 제한하지만, patter facet은 해당 유형의 사전공간(lexical space)을 제한한다. 값공간이나 사전공간을 제한하면 간접적으로 상대방도 제한하게 된다. (값공간을 제한하면 사전공간에 영향을 미치게 된다는 뜻) 위의 예에서는 기본 유형의 값 공간을 제한하고 있는데, 아래의 예에서는 regular expression을 사용하여 문자열의 사전공간을 제한한다.

...
   <xsd:simpleType name="SSN">
      <xsd:restriction base="xsd:string">
         <xsd:pattern value="\d{3}-\d{2}-\d{4}"/>
      </xsd:restriction>
   </xsd:simpleType>
   <xsd:simpleType name="PublisherAssignedId">
      <xsd:restriction base="xsd:string">
         <xsd:pattern value="\d{2}-\d{8}"/>
      </xsd:restriction>
   </xsd:simpleType>
   <xsd:simpleType name="Phone">
      <xsd:restriction base="xsd:string">
         <xsd:pattern value="\(\d{3}\)\d{3}-\d{4}"/>
      </xsd:restriction>
   </xsd:simpleType>

   <xsd:element name="authorId" type="tns:SSN"/>
   <xsd:element name="pubsAuId" type="tns:PublisherAssignedId"/>
   <xsd:element name="phone" type="tns:Phone"/>
...

다음 문서는 이렇게 정의된 요소들에 대한 적법한 인스턴스가 포함되어 있다.

<x:authorId xmlns:x="http://example.org/publishing">123-45-6789</x:authorId>
<x:pubsAuId xmlns:x="http://example.org/publishing">01-23456789</x:pubsAuId>
<x:phone xmlns:x="http://example.org/publishing">(801)390-4552</x:phone>

regular expression(pattern facet으로 지정된)에 맞는 문자열만 해당 유형의 유효 인스턴스로 간주된다.

<표 1> Facets

Facet 요소 

  설명

 xsd:enumeration

 해당 유형이 값은 나열된 값중 하나이어야 함

 xsd:fractionDigits

 소숫점 아랫자리의 수

 xsd:length

 문자열 기반 유형의 경우 문자의 수, binary 기반 유형의 경우 8진수(octet)의 수, 목록 기반 유형의 경우 아이템의 수

 xsd:maxExclusive

 유형의 값 공간중 제외할 상위 한도

 xsd:maxInclusive

 유형의 값 공간중 포함될 상위 한도

 xsd:maxLength

 문자열 기반 유형의 경우 문자의 최대수, binary 기반 유형의 경우 8진수(octet)의 최대수, 목록 기분 유형의 경우 아이템의 최대수

 xsd:minExclusive

 유형의 값 공간중 제외할 하위 한도

 xsd:minInclusive

 유형의 값 공간중 포함될 하위 한도

 xsd:minLength

 문자열 기반 유형의 경우 문자의 최소수, binary 기반 유형의 경우 8진수(octet)의 최소수, 목록 기분 유형의 경우 아이템의 최소수

 xsd:pattern

 유형이 매칭되어야 할 regular expression 기반의 패턴

 xsd:totalDigits

 숫자 기반의 유형에서 소숫점 이하 수의 최대 갯수

 xsd:whiteSpace

 공백문자 정규화 법칙

또다른 재미있는 facet으로는 xsd:enumeration이 있다. 이는 값공간을 나열된 값(enumerated values)로 제한하는 것이다. 다음은 xsd:NMTOKEN의 값공간을 4개의 지정된 나열값으로 제한하는 예이다.

...
   <xsd:simpleType name="PublicationType">
      <xsd:restriction base="xsd:NMTOKEN">
         <xsd:enumeration value="Book"/>
         <xsd:enumeration value="Magazine"/>
         <xsd:enumeration value="Journal"/>
         <xsd:enumeration value="Online"/>
      </xsd:restriction>
   </xsd:simpleType>
   <xsd:element name="pubType" type="tns:PublicationType"/>
...

아래 문서는 위에서 정의한 요소에 대한 유효 인스턴스를 담고 있다.

<x:pubtype xmlns:x="http://example.org/publishing">Online</x:pubtype>

<표 2> Simple 유형 구축 기법

 유도 유형 

 설명

 xsd:restriction

 새로운 유형은 기존 유형의 제한이다. 즉, 유효 값의 범위가 줄어든다.

 xsd:list

 새로운 유형은 다른 simple 유형의 공백문자로 구분된 목록이다.

 xsd:union

 새로운 유형은 2개 이상의 simple 유형의 union 이다.

유형의 값 공간을 제한하는 외에, 다른 유형의 list 또는 union인 새로운 simple 유형을 만들 수도 있다. xsd:restriction 대신 xsd:list 또는 xsd:union 요소를 사용하면 된다. (표 2 참조) xsd:list를 사용할 때 지정된 값공간으로부터 공백문자로 구분된 값 목록을 정의한다. 명심할 것은 xsd:list 또는 xsd:union을 사용할 때에는 xsd:restriction 과 같은 derivation hierarchy가 없기 때문에, 이 경우에는 유형 호환성이 성립되지 않는다는 것이다. 아래는 SSN 값의 목록으로서 AuthorList라는 새로운 유형을 정의하는 예이다.

...
   <xsd:simpleType name="AuthorList">
      <xsd:list itemType="tns:SSN"/>
   </xsd:simpleType>
   <xsd:element name="authors" type="tns:AuthorList"/>
...

다음 문서는 authors의 유효한 인스턴스를 담고 있다.

<x:authors xmlns:x="http://example.org/publishing">111-11-1111 222-22-2222 333-33-3333 444-44-4444</x:authors>

xsd:union의 경우, 여러개의 값 공간을 합한 새로운 값 공간의 새로운 유형을 생성할 수 있다. union 유형의 인스턴스는 지정된 값공간 중 어떤 하나로부터의 값을 가질 수 있다. 예를 들어, 다음의 AuthorId 유형은 SSN 값공간과 PublisherAssignedId 값공간을 결합하였다.

...
   <xsd:simpleType name="AuthorId">
      <xsd:union memberTypes="tns:SSN tns:PublisherAssignedId"/>
   </xsd:simpleType>
   <xsd:element name="authorId" type="tns:AuthorId"/>
...

다음 두가지는 모두 authorId 요소에 대한 유효한 인스턴스이다.

<x:authorId xmlns:x="http://example.org/publishing">111-11-1111</x:authorId>
<x:authorId xmlns:x="http://example.org/publishing">22-22222222</x:authorId>

XML Schema는 사용자정의 유형을 지원한다. 좀더 정확하게 말하자면 맞춤형 값/사전 공간을 지원한다. 이것이 XML의 강력한 기능중 하나이다. 대부분의 프로그래밍 언어는 이러한 기능을 허용하지 않으므로, 개발자들은 이러한 문제를 응용프로그램 코드 (일반적으로 property setter를 사용하여) 처리해야한다. 정확한 필요에 따라 맞춤형 값/사전 공간을 정의하는 능력이 있음으로써 오류 처리와 검증코드를 레이어 수준에서 처리가 가능하다.

Complex 유형 정의

XML Schema는 여러가지 simple 유형(이나 값 공간)을 배열하여 complex 유형이라고 하는 구조로 만들 수 있다. 새로운 complex 유형을 정의하려면 아래의 예와 같이 스키마의 target 네임스페이스내에서 xsd:complexType 요소를 사용하면 된다.

...
   <xsd:complexType name="AuthorType">
      <!-- compositor goes here -->
   </xsd:complexType>
...

xsd:complexType 요소는 compositor라는 것이 포함되어 있는데, 그것은 그 유형의 내용의 구성, 즉 콘텐트 모델을 서술한다. XML Schema는 3개의 compositor를 정의한다. 이들은 xsd:sequence, xsd:choice, xsd:all 을 포함한 complex 유형 정의에 사용될 수 있다.

Compositor 는 particle를 포함한다. particle은 다른 compositor, 요소 선언, wildcard, 모델 그룹 등을 포함한다. 속성 선언은 particle로 간주되지 않는다. 반복이 없기 때문이다. 따라서 속성 선언은 compositor 내에 위치하지 않고 complex type 선언 끝에 있는 compositor 이후에 위치한다.

<표 3> Complex 유형 Compositor

 Compositor

 설명

 xsd:sequence

 포함된 particle의 순서있는 sequence

 xsd:choice

 포함된 particle의 선택

 xsd:all

 모든 포함된 partile. 순서는 관계없음

An element declaration (xsd:element) is probably the most commonly used particle. The following complexType named AuthorType defines an ordered sequence of two element children and an attribute, each of a different simple type:

요소선언(xsd:element)는 가장 널리 사용되는 particle이다. 아래의 AuthrType 이라는 compelxType은 2개의 요소의 순서있는 sequence와 하나의 속성으로 구성된다. 각각은 simple 유형이다.

...
   <xsd:complexType name="AuthorType">
      <!-- compositor goes here -->
      <xsd:sequence>
         <xsd:element name="name" type="xsd:string"/>
         <xsd:element name="phone" type="tns:Phone"/>
      </xsd:sequence>
      <xsd:attribute name="id" type="tns:AuthorId"/>
   </xsd:complexType>

   <xsd:element name="author" type="tns:AuthorType"/>
...

xsd:complexType 요소내에 선언된 요소와 속성은 로컬로 간주된다. 로컬 요소와 속성은 정의된 해당 문맥 내에서만 사용될 수 있다. 이는 로컬 요소/속성이 인스턴스 문서에서 네임스페이스 정규화(qualified)가 필요한지에 관한 흥미로운 질문을 불러온다. 로컬 요소와 속성은 항상 target 네임스페이스로 정규화된 부모 요소(대부분 글로벌)내에 포함되므로, 정규화가 필요하지 않다고 주장할 수 있다. 이는 대부분의 프로그래밍 언어의 작동방식과 유사하다. 클래스를 네임스페이스 내에 선언하면, 클래스 이름만이 네임스페이스에 의해 정규화(qualified)되고, 로컬 멤버는 정규화되지 않는다. 

이러한 이유로 XML Schema에서 로컬 요소와 속성은 정규화하지 않는 것이 기본이다. 따라서, autho 요소의 적합한 인스턴스는 다음과 같은 형태를 갖는다.

<x:author xmlns:x="http://example.org/publishing"
   id="333-33-3333">
   <name>Aaron Skonnard</name>
   <phone>(801)390-4552</phone>
</x:author>

하지만 XML Schema에서는 로컬 요소/속성을 정규화할지 말지를 제어하는 방법이 있다. 아래 예와 같이 xsd:element/xsd:attribute 에 form 속성을 사용하거나, xsd:schema 에elementFormDefault/attributeFormDefault 를 사용하면 된다.

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   targetNamespace="http://example.org/publishing"
   xmlns:tns="http://example.org/publishing"
   elementFormDefault="qualified" 
   attributeFormDefault="qualified"
>
   ...
</xsd:schema>

이 스키마에 대해, 다음의 인스턴스는 유효한 인스턴스가 된다. (위에 있는 인스턴스는 유효하지 않다)

<x:author xmlns:x="http://example.org/publishing"
   x:id="333-33-3333">
   <x:name>Aaron Skonnard</x:name>
   <x:phone>(801)390-4552</x:phone>
</x:author>

대부분의 경우 스키마에 부합하기만 하면, 어떠한 네임스페이스 스타일을 사용하던 무방하다.

아울러 아래와 같이,  글로벌로 선언된 요소/속성을 complex 유형내에서 ref 속성을 사용하여 참조하는 방법도 가능하다.

...
   <!-- global definitions -->
   <xsd:attribute name="id" type="tns:AuthorId"/>
   <xsd:element name="name" type="xsd:string"/>
   <xsd:element name="author" type="tns:AuthorType"/>

   <xsd:complexType name="AuthorType">
      <!-- compositor goes here -->
      <xsd:sequence>
         <!-- reference to global element -->
         <xsd:element ref="tns:name"/>
         <xsd:element name="phone" type="tns:Phone"/>
      </xsd:sequence>
      <!-- reference to global attribute -->
      <xsd:attribute ref="tns:id"/>
   </xsd:complexType>
...

id와 name이 글로벌 요소이므로, 인스턴스 문서에서 정규화하여 사용해야 한다. "ref"를 사용하면 AuthorType 문맥 내에서 글로벌 요소를 사용할 수 있지만, 정규화 필요성은 변하지 않는다. phone 요소는 로컬로 정이되어 있으므로, form 을 어떻게 사용하느냐에 따라 정규화시켜야 할수도, 아닐 수도 있다. xsd:schema에서 elementFormDefault="unqualified"를 사용했다고 가정하면, 유효한 인스턴스는 아래와 같은 형태를 취한다.

<x:author xmlns:x="http://example.org/publishing"
   x:id="333-33-3333">
   <x:name>Aaron Skonnard</x:name>
   <phone>(801)390-4552</phone>
</x:author>

아래는 중첩된 complex 유형, 다른 compositer, 반복 particle을 사용하는 좀더 복잡한 예이다.

...
   <xsd:complexType name="AddressType">
      <xsd:all>
         <xsd:element name="street" type="xsd:string"/>
         <xsd:element name="city" type="xsd:string" minOccurs="0"/>
         <xsd:element name="state" type="tns:State" minOccurs="0"/>
         <xsd:element name="zip" type="tns:Zip"/>
      </xsd:all>
   </xsd:complexType>

   <xsd:complexType name="PublicationsListType">
      <xsd:choice maxOccurs="unbounded">
         <xsd:element name="book" type="xsd:string"/>
         <xsd:element name="article" type="xsd:string"/>
         <xsd:element name="whitepaper" type="xsd:string"/>
      </xsd:choice>
   </xsd:complexType>

   <xsd:complexType name="AuthorType">
      <xsd:sequence>
         <xsd:choice>
            <xsd:element name="name" type="xsd:string"/>
            <xsd:element name="fullName" type="xsd:string"/>
         </xsd:choice>
         <xsd:element name="address" type="tns:AddressType"/>
         <xsd:element name="phone" type="tns:Phone" 
            minOccurs="0" maxOccurs="unbounded"/>
         <xsd:element name="recentPublications"
            type="tns:PublicationsListType"/>     
      </xsd:sequence>
      <xsd:attribute name="id" type="tns:AuthorId"/>
   </xsd:complexType>

   <xsd:element name="author" type="tns:AuthorType"/>

이 예에서 AuthorType는 sequence와 속성으로 구성되는데, sequence 내에는 또다른 compositor인 choice와 3개의 요소가 포함된다. 이들 요소중 일부는 다른 사용자 정의 complex 유형인 AddressType 과 PublicationListType) 이기 때문에, 효과적으로 중첩된 구조를 정의하고 있다. choice란 "name" 또는 "fullName"요소 중 하나만 허용된다는 뜻이다. 마지막으로 AddressType에 있는 all 은 순서는 관계없다는 의미이다.

또한, phone 요소 선언은 minOccurs/maxOccurs 속성을 사용하여 횟수를 제한하고 있다. 횟수 제한은 complex 유형에 들어 있는 모든 particle에 적용할 수 있다. 기본 값은 1로서, 해당 particle이 지정된 위치에 정확하게 한번 등장해야 함을 의미한다. minOccurs="0"을 지정하면 해당 particle이 옵션이라는 뜻이며, maxOccurs="unbounded"는 particle이 얼마든지 반복될 수 있음을 의미한다. 아울러 minOccurs="3" 이나 maxOccurs="77"과 같이 임의의 한계를 설정할 수도 있다. occurence 제한을 compositor에 사용하면 해당 그룹 전체에 적용된다. (PublicationListType의 경우, choice에 횟수 제한을 적용하였다.) 아래는 새로운 AuthorType에 대한 유효한 인스턴스의 예이다.

<x:author xmlns:x="http://example.org/publishing"
   id="333-33-3333">
   <name>Aaron Skonnard</name>
   <address>
      <street>123 Main</street>
      <zip>84043</zip>
   </address>
   <phone>801-729-0924</phone>
   <phone>801-390-4555</phone>
   <phone>801-825-3925</phone>
   <recentPublications>
     <whitepaper>Web Service Abstractions</whitepaper>
     <book>Essential XML Quick Reference</book>
     <article>Web Services and DataSets</article>
     <article>Understanding SOAP</article>
     <book>Essential XML</book>
   </recentPublications>
</x:author>

기본으로 complex 유형은 폐쇄된(closed) 콘텐츠 모델이다. 이는 지정된 particle만이 인스턴스내에 나타나야 함을 의미한다. 하지만, XML Schema는 wildcard라는 것을 사용하여 개방형(open) 콘텐츠모델을 정의할 수 있다. complex 유형 내에 xsd:any를 사용하면, 해당 위치에 어떠한 요소도 들어갈 수 있음을 의미하여, 미리 예상할 수 없는 것에 대한 placeholder로 만들수 있다. 아울러 xsd:anyAttribute 를 사용하면 속성에 대한 placeholder도 정의할 수 있다.

...
   <xsd:complexType name="AuthorType">
      <!-- compositor goes here -->
      <xsd:sequence>
         <xsd:element name="name" type="xsd:string"/>
         <xsd:element name="phone" type="tns:Phone"/>
         <xsd:any minOccurs="0" maxOccurs="unbounded"/>
      </xsd:sequence>
      <xsd:anyAttribute/>
   </xsd:complexType>
   <xsd:element name="author" type="tns:AuthorType"/>
...

아래는 위에서 정의한 author 요소에 대한 유효한 인스턴스의 예이다.

<x:author xmlns:x="http://example.org/publishing"
   xmlns:aw="http://www.aw.com/legal/contracts"
   aw:auId="01-3424383"
>
   <!-- explicitly defined by the complexType -->
   <name>Aaron Skonnard</name>
   <phone>801-825-3925</phone>

   <!-- extra elements that replace wildcard -->
   <aw:contract xmlns:aw="http://www.aw.com/legal/contracts">
      <title>Essential Web Services Quick Reference</title>
      <deadline>2003-06-01</deadline>
   </aw:contract>
   ...
</x:author>

When using wildcards it's also possible to constrain the namespace the content actually comes from. Both xsd:any and xsd:anyAttribute come with an optional namespace attribute that may contain any of the values shown in Table 4. This makes it possible to be very specific about where the wildcard replacement content comes from. 

wildcard를 사용할 때, 내용이 올 네임스페이스를 한정하는 것도 가능하다. xsd:any와 xsd:anyAttribute 모두 옵션으로 네임스페이스 속성을 넣을 수 있는데, 표 4에 있는 값중 하나를 넣을 수 있다. 이렇게 하면, wildcard 내용을 한정할 수 있다.

<표 4> Wildcard 네임스페이스 속성

 Attribute 값 

 허용되는 요소

 ##any

 모든 네임스페이스의 요소

 ##other

 targetNamespace를 제외한 모든 네임스페이스의 요소

 ##targetNamespace

 targetNamespace에 있는 모든 요소

 ##local

 정규화되지 않은 요소(네임스페이스 없음)

 list of ns string

 네임스페이스 목록내에 있는 요소

wildcard를 사용할 경우, 스키마 프로세서가 검증과정에서 그 wildcard 내용을 어떻게 처리해야 하는지를 지정할 수 있다. xsd:any와 xsd:anyAttribute는 모두 processContents 속성이 있는데, lax/strict/skip 등 세가지 중 하나의 값을 가질 수 있다. 이값은 wildcard 위치에 들어오는 내용에 스키마 검증을 어떻게 수행해야 하는지를 나타낸다. Strict란 내용에 대해 반드시 검증해야 한다는 뜻이다. Lax는 schema 정보가 있을 경우에만 검증을 해야 함을 의미하고, skip은 schema 검증을 수행하지 말라는 의미이다.

 Let's look at an example that uses these attributes. The schema for SOAP 1.1 actually leverages wildcards and both of these attributes to define the structure of the soap:Header and soap:Body elements:

이들 속성을 사용하는 예를 살펴보자. SOAP 1.1 스키마는 실제로 wildcard를 활용하고 있으며, 이들 속성들을 soap:Header와 soap:Body 요소의 구조를 정의하고 있다.

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"       
  xmlns:tns="http://schemas.xmlsoap.org/soap/envelope/"         
  targetNamespace="http://schemas.xmlsoap.org/soap/envelope/" >
  ...
  <xs:element name="Header" type="tns:Header" />

  <xs:complexType name="Header" >
    <xs:sequence>
      <xs:any namespace="##other" minOccurs="0" 
       maxOccurs="unbounded" processContents="lax" />
    </xs:sequence>
    <xs:anyAttribute namespace="##other" 
     processContents="lax" />
  </xs:complexType>

  <xs:element name="Body" type="tns:Body" />

  <xs:complexType name="Body" >
    <xs:sequence>
      <xs:any namespace="##any" minOccurs="0" 
       maxOccurs="unbounded" processContents="lax" />
    </xs:sequence>
    <xs:anyAttribute namespace="##any" 
     processContents="lax" />
  </xs:complexType>
  ...
</xs:schema>

스키마에 따르면, soap:Header는 0개 이상의 요소를 포함할 수 있고, 속성도 갯수제한없이 포함시킬 수 있다. 요소나 속성 모두 targetNamespace가 아닌 네임스페이스에 속해야 한다. 반면 soap:Body의 경우 0개 이상의 요소와 갯수 제한없는 속성을 포함시킬 수 있는데, 네임스페이스는 어디라도 관계없다. 이 두가지 경우에서 ㄱ검증은 스키마 정보가 런타임으로 제공될 경우에만 수행된다. (lax) soap:Header 또는 soap:Body에 어떠한 내용이 들어올 지 예측할 수 있는 방법이 전혀 없기 때문에, wildcard는 유연하고도 개행된 프레임워크를 정의하는 방법을 제공한다.

스키마 찾기 및 관리

이 쯤에서 발생할 질문중의 하나는 XML Schema 프로세서가 주어진 인스턴스 문서에 대한 스키마 정의를 어떻게 실행중에 알아내는 방법이다. XML Schema 프로세서는 인스턴스 문서의 네임스페이스를 키로 해당하는 스키마를 찾아내지만, XML Schema 사양에는 정확히 어떻게 처리할지에 대해서는 정의되어 있지 않다. 대부분의 프로세서는 필요한 모든 스키마를 미리 스키마 캐시에 불러 올 수 있도록 허용한다. 그런 뒤 실행중에는 프로세서에게 스키마 캐시만 지정하면 특정 인스턴스에 필요한 스키마를 효과적으로 참조할 수 있다.

XML 스키마는 인스턴스문서에서 스키마 위치를 제공하는 방법도 정의하고 있다. 이는 아래와 같이 xsi:schemaLocation을 사용하면 된다.

<x:author xmlns:x="http://example.org/publishing"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://example.org/publishing pubs.xsd"
>
...

xsi:schemaLocation 속성은 네임스페이스명 목록과 URI 위치 쌍을 공백문제로 분리하여 제공할 수 있다. 이를 사용해 특정 스키마 파일을 찾아낼 수 있다. 하지만, 이것은 힌트에 불과할 뿐, 프로세서가 더 효과적인 메커니즘이 있을 경우, 다른 곳을 찾을 수도 있다.

결론

XML 스키마는 XML을 위한 표현력 짱 유형시스템을 제공하여, 아주 강력한 서비스를 제공할 수 있다. 이 글에서는 simple유형 및 complex 유형 정의를 포함한 기본적인 XML 스키마 정의에 대해 다루었다. Simple 유형 정의를 사용하면, 문자만이 가능한 유형 및 속성에 맞춤형 값공간을 정의할 수 있다. Complex 유형 정의를 사용하면 Simple 유형을 배열하여 구조체를 만들 수 있다.

XML Schema는 실제로 여기에서 논의한 것보다 훨씬 더 많은 기능이 있다. 예를 들어 complex 유형 정의는 기존의 유형을 확장하거나 제한하는 등의 유도 유형을 만들 수 있어, 객체지향의 클래스 상속성과 비슷한 방법으로 complex 유형의 계층화를 정의할 수 있다. Complex 유형 계층화를 사용하면, 인스턴스 문서에서 대체 기법도 가능하다. XML Schema는 또한 XML Schema 정의를 여러개의 파일과 네임스페이스로 분리한 후, 나중에 포함(include) 또는 수입(import)하는 방법을 통해 재사용성, 편의성 및 유지관리성이 증가시킬 수 있다. 이러한 고급 주제는 다음 글을 위해 남겨둔다.

XML Schema에 관한 좀더 자세한 내용은 Essential XML Quick Reference를 참고하라. XML Schema 챕터에는 각각의 구조와 데이터유형에 관한 간단한 설명과 예제가 포함되어 있다.

.===

원문 : https://msdn.microsoft.com/en-us/library/aa468557.aspx


Posted by 푸른하늘 푸른하늘이

댓글을 달아 주세요

공간정보/표준2018. 3. 22. 16:32

모든 XML 기술중에서 XML Schema는 소프트웨어 개발자에게 가장 중요하다. XML 문서에 유형(type) 정보를 넣을 수 있게 되었기 때문이다.

먼저, XML Schema 이전 상황부터 살펴보자. XML 1.0 사양은 XML 어휘를 서술하는 내장 문법인 DTD(Document Type Definitions) 와 함께 출현했다. XML 1.0 이 그 전신인 SGML (Standard Generalized Markup Language)의 문법을 물려받은 것을 고려할 때, DTD는 사실 상당한 기간을 살아남았다고 할 수 있다.

DTD를 사용하면 XML 문서의 구조를 서술할 수 있다. 예를 들어, 직원 정보를 서술하기 위해 다음과 같은 XML 어휘를 사용한다고 해보자.

<employee id="555-12-3434">
  <name>Monica</name>
  <hiredate>1997-12-02</hiredate>
  <salary>42000.00</salary>
</employee>

다음은 이 문서의 구조를 서술하는 DTD 이다.

<!-- employee.dtd -->
<!ELEMENT employee (name, hiredate, salary)>
<!ATTLIST employee
          id CDATA #REQUIRED>
<!ELEMENT name (#PCDATA)>
<!ELEMENT hiredate (#PCDATA)>
<!ELEMENT salary (#PCDATA)>

이 DTD는 DOCTYPE 선언을 통해 원래의 문서에 연결할 수 있다. 아래는 그 예이다.

<!DOCTYPE employee SYSTEM "employee.dtd">
<employee id="555-12-3434">
  <name>Monica</name>
  <hiredate>1997-12-02</hiredate>
  <salary>42000.00</salary>
</employee>

DTD를 사용하는 가장 큰 장점은 검증이다. 검증을 할 때, XML 1.0 파서는 이 XML 1.0 파일을 읽어들이면서 연계된 DTD도 함께 읽어들여, 정의에 합당한지 검증한다. DTD를 사용하여 검증을 하게 되면, 어플리케이션에서 다루어야할 많은 상당한 양의 오류 처리를 감소시킬 수 있다.

DTD가 많은 SGML 기반의 전자출판 응용에는 잘 어울리지만, 현재의 Web 환경과 같은 소프트웨어 개발 분야에 적용하면서 DTD의 한계는 금방 드러나게 되었다. DTD의 주요한 한계로는 DTD 문법이 XML 기반이 아니며, 네임스페이스를 지원하지 않고, 전형적인 프로그래밍 언어의 데이터타입을 지원하지 않으며, 맞춤형 유형을 정의할 수 없다는 것 등이다.

DTD 문법 자체가 XML이 아니기 때문에, 프로그램적으로 정의를 처리할 때, 표준 XML 도구들을 사용할 수 없다. 대부분의 XML 1.0 프로세서는 DTD 검증을 지원하기는 하나, DTD 문법의 복잡성으로 인해 DTD에 있는 정보에 대한 프로그램적 접근을 지원하지 않는다.

DTD는 XML 네임스페이스가 존재하기 전에 만들어졌으므로, 두가지가 함께 잘 작동하지 않는다는 건 놀라운 일이 아니다. 사실 DTD를 사용하여 네임스페이스를 지원하는 문서를 만든다는 것은 동그란 구멍에 네모난 통을 끼우려는 것과 비슷하다. 이 작업의 끔찍한 일면을 알고싶다면, 내가 네임스페이스 지원 DTD를 제공하는 XML Files 컬럼을 쓴 2001년 5월 작업을 확인하기 바란다. 결론적으로, 대부분의 개발자들은 DTD나 네임스페이스 둘중의 하나만 사용하였고, 둘 다 사용하는 경우는 거의 없었다.

DTD는 프로그램 데이터 유형이 존재하지 않는 문서 중심 시스템을 위해 개발되었다. 그 결과 속성을 기술하는 단 몇가지의 유형 식별자만이 존재한다. (그림 1 참고) 이러한 유형식별자도 일반적인 프로그램 언어에서 사용하는 유형과 전혀 다르다. 이 식별자들은 텍스트(CDATA)의 특별한 케이스에 불과하다. 아울러 이러한 유형은 텍스트만 있는 요소에는 적용할 수 없고 속성에만 적용할 수 있다.

<그림 1> DTD 유형의 종류

마지막으로 DTD 유형 시스템은 확장이 불가능하다. 즉, 그림 1에 있는 유형만 쓸수 있다는 것이다. 자신의 문제 영역에서 의미있는 맞춤형 유형을 생성하는 것은 DTD로는 불가능하다. 이러한 한계만으로도 XML Schema가 새롭고도 흥미로운 미래를 제안하자 XML 개발자는 DTD로부터 탈출할 충분한 이유가 되었다.

XML Schema 기본

XML Schema는 그 자체가 XML 어휘를 사용하여 XML 인스턴스 문서를 기술한다. "인스턴스(instance)"라는 용어는 스키마가 여러 문서의 클래스를 서술하고, 여러 개의 다른 인스턴스가 존재할 수 있기 때문이다. (그림 2) 이것은 오늘날 객체지형 시스템에서 클래스와 객체와의 관계와 비슷하다. 클래스는 스키마에 해당하고, 객체는 XML 문서에 해당한다. 따라서 XML Schema를 사용하는 동안 하나 이상의 문서와 작업을 하게 된다.


<그림 2> 네임스페이스 식별자 링크

스키마 정의에 사용되는 요소는 http://www.w3.org/2001/XMLSchema 네임스페이스에 들어 있다. 나는 이 문서에서 이 네임스페이스를 xsd로 결합할 것이다. 다음은 기본 스키마 템플릿이다.

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  targetNamespace="http://example.org/employee/">
  <!-- definitions go here -->
</xsd:schema>

스키마 정의에는 반드시 최상위 요소인 xsd:schema가 있어야 한다. xsd:schema 내에는 다양한 요소들이 중첩될 수 있는데, xsd:element, xsd:attribute, xsd:complexType 등이 그 예이다. 

스키마 정의 자체가 XML 문서이므로 DTD의 한계 중에서 첫번째 한계가 해결된다. 스키마 정의도 표준적인 XML 1.0 도구 및 서비스(예: DOM, SAX, XPath, XSLT 등)를 사용하여 처리할 수 있다. 이와 같은 간편성으로 인해 스키마 도구가 홍수처럼 쏟아져 나오게 되었다.

XML Schema 와 네임스페이스

xsd:schema 요소 내에 위치한 정의는 targetNamespace 속성에 정의된 네임스페이스로 자동적으로 연결된다. 위의 예의 경우, 스키마 정의는 http://example.org/employee 네임스페이스에 연계된다.

네임스페이스 식별자는 XML 문서와 해당 Schema 정의를 연결하는 키이다. (그림 2 참고) 예를 들어, 다음의 XML 인스턴스 문서는 http://example.org/employee/ 네임스페이스에서 온 employee 요소를 포함한다.

<tns:employee xmlns:tns="http://example.org/employee/" />

employee 요소의 네임스페이스는 스키마 정의의 targetNamespace와 동일하다.

employee 요소를 처리하면서 스키마의 장점을 활용하려면, 처리기가 올바른 스키마 정의를 찾을 필요가 있다. 스키마 처리기가 특정 네임스페이스를 위한 스키마 정의 파일을 찾는 방법은 사양에 정의되어 있지 않다. 그러나 대부분의 처리기는 스키마를 메모리 캐시에 불러들인 후, 문서 처리에 사용하는 것을 허용한다. 예를 들어 아래의 JScript® 기반 코드은 MSXML 4.0을 사용한 간단한 방법을 나타낸 것이다.

var sc = new ActiveXObject("MSXML2.XMLSchemaCache.4.0);
sc.add("http://example.org/employee/", "employee.xsd");
var dom = new ActiveXObject("MSXML2.DOMDocument.4.0");
dom.schemas = sc;

if (dom.load("employee.xml")) 
  WScript.echo("success: document conforms to Schema");   
else
  WScript.echo("error: invalid instance");

Microsoft® .NET 이나 기타 대부분의 XML Schema 처리기도 이와 비슷한 방법으로 작동한다.

아래(역자 주 : XML0204.exe 인데 링크가 깨져서 파일은 없음)는 명령어 방식의 검증 유틸리티로서, 이 글에 논의된 원칙들을 시험해 볼 수 있다. 이 검증 유틸리티에서는 검증하고자 하는 인스턴스 문서와 함께, 필요에 따라 많은 스키마 정의 파일을 지정할 수 있다. 명렁어 사용법은 다음과 같다.

c:>validate instance.xml -s schema1.xsd -s schema2.xsd ...

XML Schema는 아울러 schemaLocation 속성을 사용하여, 인스턴스 문서내에서 필요한 스키마 정의문서의 소재를 제공할 수도 있다. schemaLocation속성은 http://www.w3.org/2001/XMLSchema-instance 네임스페이스에 있으며, 이 네임스페이스는 인스턴스 문서에서만 사용되는 속성만 특별히 담고 있다. 나는 지금부터 이 네임스페이스를 xsi 접두사와 결합시켜 사용하겠다. xsi:schemaLocation 속성은 아래의 예와 같이 공백문자로 구분된 네임스페이스 식별자와 URL의 쌍으로 이루어진다.

<tns:employee xmlns:tns="http://example.org/employee/"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://example.org/employee/ 
                      http://develop.com/aarons/employee.xsd"
/>

이 경우, 처리기가 http://example.org/employee/ 네임스페이스를 위한 적절한 스키마 정의에 이미 접근하지 못했을 경우, http://develop.com/aarons/employee.xsd 로부터 다운로드 받을 수 있다.

요소와 속성(Elements and Attributes)

요소와 속성은 targetNamespace의 일부로서 정의될 수 있다. 각각 xsd:element와 xsd:attribute 요소를 사용한다. 예를 들어 아래와 같은 인스턴스 문서를 기술하려고 한다고 하자.

<tns:employee xmlns:tns="http://example.org/employee/"
  tns:id="555-12-3434">
  <tns:name>Monica</tns:name>
  <tns:hiredate>1997-12-02</tns:hiredate>
  <tns:salary>42000.00</tns:salary>
</tns:employee>

가장 간단한 방법은 다음과 같은 스키마 정의를 사용하면 된다.  

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  targetNamespace="http://example.org/employee/">
  <xsd:element name="employee"/>
  <xsd:element name="name"/>
  <xsd:element name="hiredate"/>
  <xsd:element name="salary"/>
  <xsd:attribute name="id"/>
</xsd:schema>

주목할 점은 xsd:element와 xsd:attribute 선언을 xsd:schema 요소에 넣기만 함으로써, 자동적으로 이들이 http://example.org/employee/ 네임스페이스에 연결되었다는 것이다. 이러한 선언은 스키마에서 global 로 간주된다. 이들이 최상위 xsd:schema 요소의 자식요소(child)이기 때문이다.

이 스키마에서는 이들 요소/속성이 http://example.org/employee/ 네임스페이스의 일부라고 지정하였기 때문에, (위에서 보인 원래의 인스턴스처럼) 인스턴스 문서에서 해당 네임스페이스에 연결시켜야 한다. 인스턴스에 네임스페이스를 미세하게 변경해도 인스턴스가 무효가 된다. 예를 들어, 다음의 문서는 무자격(unqualified) name, hiredate, salary 요소 그리고 무자격 id 속성이 포함되어 있다.

<tns:employee xmlns:tns="http://example.org/employee/"
  id="555-12-3434">
  <name>Monica</name>
  <hiredate>1997-12-02</hiredate>
  <salary>42000.00</salary>
</tns:employee>

위의 스키마 정의에서는 이들 요소/속성이 http://example.org/employee/ 네임스페이스에 속한다고 했지만, 여기에서는 이들 요소/속성이 네임스페이스에 연결되어 있지 않아 이 인스턴스가 무효가 된 것이다.

이번엔 훨씬 더 미세한 변화로서, 네임스페이스 접두사 대신 기본 네임스페이스 선언을 사용하는 경우를 살펴보자.

<employee xmlns="http://example.org/employee/"
  id="555-12-3434">
  <name>Monica</name>
  <hiredate>1997-12-02</hiredate>
  <salary>42000.00</salary>
</employee>

이 경우 모든 요소들은 기본 네임스페이스(http://example.org/employee/)에 연결되었지만, id 속성만은 여전히 무자격이다. 기본 네임스페이스는 속성에는 적용되지 않기 때문이다. 그 결과 이 문서 인스턴스도 무효로 간주된다.

보시는 바와 같이, XML 네임스페이스는 XML Schema의 가장 핵심에 있다. XML Schema를 사용하려면 네임스페이스의 작동방법에 대해 완전히 이해해야 한다. 인스턴스 문서가 스키마에 지정된 것과 일치하지 못하면 무효화되기 때문이다.

아울러 이 간단한 예제에는 요소의 내용 및 네임스페이스 내의 요소간의 구조적 관계등에 아무런 제한도 없다는 것도 알 수 있다. 이 스키마는 아래의 DTD와 동등하다. (단 속성 선언은 생략)

<!ELEMENT employee ANY>
<!ELEMENT name ANY>
<!ELEMENT hiredate ANY>
<!ELEMENT salary ANY>

따라서 다음의 XML 인스턴스 문서가는 전혀 이치에 닿지 않지만, 스키마에는 적합하다.

<tns:name xmlns:tns="http://example.org/employee/">
  <tns:employee>
    <tns:hiredate>42.000</hiredate>
    <tns:salary tns:id="555-12-3434">Monica</tns:salary>
  </tns:employee>
</tns:name>

XML Schema는 Complex 유형 선언을 통해 요소의 구조를 기술할 수 있다.

Complex 유형 선언 

DTD를 사용할 경우, 요소의 내용 모델은 다음과 같이 ELEMENT 선언에서 정의할 수 있다.

<!ELEMENT employee (name, hiredate, salary)>

이 ELEMENT 선언은 employee 요소에 name 요소, hiredate 요소, salary 요소 순으로 들어 있음을 말하고 있다.

XML Schema에서는 xsd:complexType 요소와 xsd:element 선언을 중첩시킴으로써 요소의 내용 모델을 정의할 수 있다. 다음은 그 예이다.

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  targetNamespace="http://example.org/employee/">
  <xsd:element name="employee">
    <xsd:complexType>
      <!-- employee's content model goes here -->
    </xsd:complexType>
  </xsd:element>
</xsd:schema>

XML Schema 모델은 변수에 유형선언을 결합한다는 의미에서 좀더 프로그래밍 언어와 비슷하다. xsd:complexType을 사용하면 어떤 구조를 가진 요소의 유형을 선언할 수 있다.  요소 선언 내에 xsd:complexType 을 중첩시키면 요소(변수와 같이)에 효과적으로 결합시킬 수 있다. 유형선언이 DTD로부터 XML Schema로의 중요한 패러다임 이동이다.

xsd:complexType 요소의 내부에 넣는 것은 DTD ELEMENT 선언 다음 괄호 안에 무엇을 넣는 것과 유사하다. 위에 있는 employee ELEMENT 선언은 name, hiredate, salary 요소의 순서있는 나열을 정의한다. 콤마 대신 pipe(|) 를 사용하면 하나의 요소를 선택한다는 의미이다.

<!ELEMENT employee (name | hiredate | salary)>

XML Schema에서는 compositor 요소를 통하여 내용모델의 특성을 정의할 수 있다. compositor는 xsd:complexType 요소의 자식요소로 중첩시켜 사용한다. XML Schema는 xsd:sequence, xsd:choice, xsd:all 등 세가지 compositor가 있다.

<그림 3> Complex 유형의 Compositor

Compositor 

 동등한 DTD 표현

 정의

 xsd:sequence

 콤마로 분리한 그룹

 아이템들의 순서있는 나열

 xsd:choice

 Pipe(|)로 분리한 그룹

 포함된 아이템중 하나의 선택

 xsd:all

 -

 순서에 관계없이 모든 아이템 포함


xsd:sequence와 xsd:choice 요소는 위에서 설명한 DTD 예제들과 동등하다. 하지만, xsd:all은 새로운 개념으로서, 순서에 관계없이 모든 아이템으로 구성되는 내용모델을 지정한다. 이는 DTD 문법에 정의되어 있지않다. 구지 DTD를 이용하여 이와 같은 의미론을 정의하려면 아래와 같이 모든 요소를 명시적으로 나열하면 된다.

<!ELEMENT employee ( (name, hiredate, salary) |
                               (name, salary, hiredate) |
                               (hiredate, name, salary) |
                               (hiredate, salary, name) |
                               (salary, name, hiredate) | 
                               (salary, hiredate, name) ) >

이와 같이, 순열과 조합으로 인해 짜증이 나기 시작할 것이다. XML Schema는 "all" compositor도 sequcen와 choice처럼 1급 compositor이기 때문에 훨씬 깔끔하다. 

Compositor 요소는 글로벌 요소선언, 로컬 요소 선언, 다른 compositor, 기타 와일드카드나 group 참조와 같은 기타 구조요소에 대한 참조를 포함할 수 있다. 그림 4에 표시한 예제 스키마는 xsd:complexType에서 다른 부분에 정의된 글로벌 요소를 참조하는 예이다.

<그림 4> 글로벌 요소 참조의 예

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:tns="http://example.org/employee/"
  targetNamespace="http://example.org/employee/">

  <xsd:element name="employee">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element ref="tns:name"/>
        <xsd:element ref="tns:hiredate"/>
        <xsd:element ref="tns:salary"/>
      </xsd:sequence> 
    </xsd:complexType>
  </xsd:element>

  <xsd:element name="name"/>
  <xsd:element name="hiredate"/>
  <xsd:element name="salary"/>
</xsd:schema>

이상에서 알 수 있는 것과 같이 ref 속성은 접두사가 있는 요소명을 취한다. 스키마에서 글로벌 요소를 선언하면, 이는 자동적으로 targetNamespace로 연계된다는 것을 기억하라. 글로벌요소를 이름으로 참조하면, 이들은 정규화 이름으로 취급된다. 만약 ref="tns:name" 대신 ref="name"을 사용한다면, 스키마 처리기는 아무런 네임스페이스에도 속하지 않는 name 요소 혹은 기본 네임스페이스에 있는 name 요소를 찾게 된다. 하지만 이 경우, name요소는 http://example.org/employee 네임스페이스에 속해 있으므로, 찾을 수 없게되고, 유효하지 못한 XML 문서가 된다.

http://example.org/employee/ 네임스페이스를 어떤 문서의 기본 네임스페이스로 지정할 경우, 그림 5와 같이 접두사를 사용하지 않고도 글로벌 요소를 참조할 수 있다. (즉, ref="name"이 적법)

<그림 5> 네임스페이스 접두사를 사용하지 않는 방법

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns="http://example.org/employee/"
  targetNamespace="http://example.org/employee/">

  <xsd:element name="employee">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element ref="name"/>
        <xsd:element ref="hiredate"/>
        <xsd:element ref="salary"/>
      </xsd:sequence> 
    </xsd:complexType>
  </xsd:element>

  <xsd:element name="name"/>
  <xsd:element name="hiredate"/>
  <xsd:element name="salary"/>
</xsd:schema>

그림 4와 그림 5의 스키마 샘플은 논리적으로 동등하다. 직렬화 형태가 다를 뿐이다. 두가지 모두 employee요소의 내용을 제한하고 있다. employee 요소는 name, hiredate, salary요소를 반드시 포함해야 하고, 이들 모두 http://example.org/employee/ 네임스페이와 연결되어 있어야 한다.

로컬요소 선언

인스턴스 문서에서 사용할 유일한 top-level 요소는 employee이므로 name, hiredate, salary를 글로벌 요소로 선언할 이유는 전혀 없다. 따라서 name, hiredate, salary요소를 employee 요소의 내용 모델 내에서 로컬로 선언할 수 있다.

예를 들어 그림 6에 있는 스키마에는 로컬 요소의 시퀀스를 포함하는 employee 요소 선언이 포함되어 있다. 이 예에서 name, hiredate, salary요소는 실제 employee요소의 일부로 선언되어 있어 이 인스턴스의 다른 곳에서는 사용할 수 없다. employee 요소 선언은 최상위 xsd:schema 요소의 자손으로 글로벌하게 나타나는 오직 하나의 요소이다. 이것은 재미있는 질문을 유도한다. 로컬요소는 targetNamespace에 연결되어 있는 것인가?

<그림 6> 로컬 요소 선언

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  targetNamespace="http://example.org/employee/">
  <!-- global element declarations -->
  <xsd:element name="employee">
    <xsd:complexType>
      <xsd:sequence>
        <!-- local element declarations -->
        <xsd:element name="name"/>
        <xsd:element name="hiredate"/>
        <xsd:element name="salary"/>
      </xsd:sequence> 
    </xsd:complexType>
  </xsd:element>
</xsd:schema>

로컬 스콥과 네임스페이스

이 질문에 대한 해답을 이해하기 쉽도록 C#과 같이 네임스페이스를 지원하는 프로그래밍 언어의 간단한 예를 생각해 보자. 아래의 C# 클래스 선언은 "example" 네임스페이스 내에 정의되어 있다.  

namespace example {
  public class employee {
    public string name;
    public string hiredate;
    public double salary;
  }
}

이 네임스페이스에서 어떤 식별자가 실제로 보일 것인가? 단하나! employee 뿐이다. name, hiredate, salary 식별자는 employee 클래스 내에서만 보인다. 따라서, 아래에서 보는 바와 같이 employee는 네임스페이스 식별자를 붙여 정규화(qualified)해야 하지만, name 등의 로컬 멤버는 불가능하다.

// employee is namespace-qualified
example.employee c = new example.employee();
// local members are unqualified

c.name = "Monica";
c.hiredate = "1997-12-02";
c.salary = 42000.00;

// this does not work, nor make sense
// c.example.name = "Monica";

XML 스키마 설계자는 로컬 스콥의 적용에 대해 고려한 것처럼 보인다. 기본적으로 이와 동일하게 작동되기 때문이다. XML Schema에서도 인스턴스 문서에서 글로벌 요소만 정규화(qualified) 시켜야 하며, 로컬 요소는 unqualified하게 남겨두어야 한다. 아래는 그림 6에서 보인 스키마의 유효한 인스턴스 문서의 예이다.

<!-- global element qualified -->
<tns:employee xmlns:tns="http://example.org/employee/">
  <!-- local elements unqualified -->
  <name>Monica</name>
  <hiredate>1997-12-02</hiredate>
  <salary>42000.00</salary>
</tns:employee>

이 인스턴스를 변경하여 name, hiredate, salary요소를 http://example.org/employee 네임스페이스에 정규화시킬 경우, 스키마에 맞지 않게 된다. 기본 네임스페이스 선언을 아주 미묘하게만 변화시켜도 이런 일이 발생함을 기억해야 한다.

이러한 방식을 모두다 좋아하는 건 아니기 때문에 XML Schema 설계자는 로컬 요소를 인스턴스에서 정규화(qualified)시킬 것인지 말것인지를 제어할 수 있도록 만들었다. 아래와 같이 form 속성을 사용하여 요소별로 제어하면 된다.

<xsd:element name="employee">
  <xsd:complexType>
    <xsd:sequence>
      <!-- local element declarations -->
      <xsd:element name="name" form="qualified"/>
      <xsd:element name="hiredate"/>
      <xsd:element name="salary" form="qualified"/>       
    </xsd:sequence> 
  </xsd:complexType>
</xsd:element>

이 employee 요소에 대한 적합한 인스턴스는 아래와 같이 자식요소로서 정규화 name 요소, 비정규화 hiredate 요소, 정규화 salary 요소가 순서대로 나와야 한다.

<tns:employee xmlns:tns="http://example.org/employee/">
  <tns:name>Monica</tns:name>
  <hiredate>1997-12-02</hiredate>
  <tns:salary>42000.00</tns:salary>
</tns:employee>

또, 아래와 같이 elementFormDefault 속성을 사용하면 스키마에 있는 모든 로컬요소 선언의 기본 설정을 뒤집을(toggle) 수 있다.

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  targetNamespace="http://example.org/employee/"
  elementFormDefault="qualified">
     •••
</xsd:schema>

이렇게 하면 기본으로 인스턴스에서 모든 로컬 요소를 정규화(qualified)시켜야 한다. (특정한 요소에 대해 form 속성으로 설정을 엎어쓰지 않았다는 가정하에), 다음은 그 예이다.

<tns:employee xmlns:tns="http://example.org/employee/">
  <tns:name>Monica</tns:name>
  <tns:hiredate>1997-12-02</tns:hiredate>
  <tns:salary>42000.00</tns:salary>
</tns:employee>

이 경우 모든 요소가 정규화요소이므로, 기본 네임스페이스 선언을 사용할 수 있고, 다음 인스턴스가 유효하게 된다.

<employee xmlns="http://example.org/employee/">
  <name>Monica</name>
  <hiredate>1997-12-02</hiredate>
  <salary>42000.00</salary>
</employee>

횟수 제한(Occurrence Constraints)

DTD에서는 *. +. ? 등의 변경자(modifier)를 사용하여 내용모델에서 요소의 등장횟수를 제어할 수 있다. XML Schema는 이러한 변경자를 사용하지 않고 단순히 minOccrs와 maxOccurs 등 두가지 속성을 정의한다. 이 속성들은 요소 선언, compositor, 기타 몇가지 스키마 구조에서 사용될 수 있다.

아이템이 등장할 최소횟수와 최대횟수는 각각 minOccurs와 maxOccurs를 사용하여 지정한다. 이 속성의 기본값은 모두 1이다. maxOccurs의 값으로 "unbounded"를 사용하면 등장회수를 제한하지 않는다는 뜻이다.

다음의 DTD ELEMENT 선언을 살펴보자:

<!ELEMENT employee ( (fname, (middle | mi)?, lname, lname?), (project, role)* )>

이 ELEMENT 선언은 그림 7과 같이 minOccurs/maxOccurs과 여러개의 중첩된 compositor를 사용하여 XML Schema로 다시 작성할 수 있다.

<그림 7> minOccurs/maxOccurs 사용 예

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  targetNamespace="http://example.org/employee/">
  <xsd:element name="employee">
    <xsd:complexType>
      <xsd:sequence>

        <xsd:sequence>
          <xsd:element name="fname/>
          <xsd:choice minOccurs="0">
            <xsd:element name="middle"/>
            <xsd:element name="mi"/>
          </xsd:choice>
          <xsd:element name="lname" maxOccurs="2"/>
        </xsd:sequence>

        <xsd:sequence minOccurs="0" maxOccurs="unbounded">
          <xsd:element name="project"/>
          <xsd:element name="role"/>
        </xsd:sequence>        

      </xsd:sequence> 
    </xsd:complexType>
  </xsd:element>
</xsd:schema>

Complex 유형과 속성

DTD의 경우, 속성은 특정 요소를 위해 정의된다. 다음의 ATTLIST 선언은 employee 요소의 id 속성에 연결되어 있다.

<!ELEMENT employee (name, hiredate, salary)>
<!ATTLIST employee id CDATA #REQUIRED>

DTD에서는 글로벌 속성을 정의하는 것이 불가능하다. DTD 속성은 위와같이 반드시 특정 요소에 연결시켜야 한다.

XML Schema는 요소와 마찬가지로 속성도 글로벌 또는 로컬로 선언할 수 있다. 글로벌 속성은 최상위 xsd:schema 요소 내에 xsd:attribute 를 사용하여 정의한다. 최초의 스키마 예제는 id라는 글로벌 속성을 정의하였다. 글로벌 속성은 어디에서 사용될지 모르는 경우를 위한 의도이다.

속성을 xsd:complexType 정의내에 포함시킬 수 있다. 이 경우에는 해당 유형의 로컬 속성이 된다. xsd:complex 요소 내부에 사용하면, xsd:attribute 요소는 반드시 child compositor뒤에 나와야 한다. 다음은 그 예이다.

  <xsd:element name="employee">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="name"/>
      </xsd:sequence>
      <xsd:attribute name="id"/>
    </xsd:complexType>
  </xsd:element>

글로벌 속성은 요소와 마찬가지로 인스턴스문서에서 정규화(qualify)해야 하며, 로컬 속성은 정규화해서는 안된다. 아래는 위에서 정의한 employee요소에 대한 유효한 인스턴스이다.

<tns:employee xmlns:tns="http://example.org/employee/"
       id='555-12-3434'>
    <name>Monica</name>
</tns:employee>

그러나 로컬 속성을 정규화시키고 싶을 경우, 요소와 마찬가지로 form 속성이나 attributeFormDefault 속성을 사용하여 이러한 방식을 변경시킬 수 있다. 

Named 유형과 재사용

이제까지 나는 요소의 유형(혹은 구조)를 xsd:complexType 정의를 사용하여 정의하였다. 그러나 이러한 유형정의는 named가 아니다. 새롭게 선언된 요소에 연결되기 때문이다. 이 접근법은 C++에서 anonymous 유형을 사용하는 것과 비슷하다. 예를 들어, 아래의 C++ 코드는 pt 변수를 anonymous 구조에 지정한 것이다.

struct {
  double x;
  double y;
} pt;

이러한 anonymous 유형은 명백한 단점이 있다. 재사용할 수 없다는 것이다. 따라서 대부분의 C++ 개발자들은 named 유형을 사용한다.

struct Point {
  double x;
  double y;
};
Point pt1;

XML 스키마는 named 유형도 지원한다. 대부분의 개발자들은 재사용 가능성때문에 이러한 접근법을 좋아한다. 하나의 스키마에서 named 유형을 재사용하는 것 뿐만 아니라, xsd:include와 xsd:import를 사용하면 여러 스키마에서 named 유형을 재사용할 수 있다.

이름은 xsd:complexType에서 name 속성을 통해 부여할 수 있다. 요소선언을 type 속성을 사용하면 named 유형에 결합할 수 있다. 아래의 스키마는 이러한 요소 바인딩의 예를 보인 것이다.

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:tns="http://example.org/employee/"
  targetNamespace="http://example.org/employee/">

  <xsd:complexType name="EmployeeType">
    <xsd:sequence>
      <xsd:element name="name"/>
      <xsd:element name="hiredate"/>
      <xsd:element name="salary"/>       
    </xsd:sequence> 
  </xsd:complexType> 

  <xsd:element name="employee" type="tns:EmployeeType"/>

</xsd:schema>

여기에서 xsd:complexType 정의는 이 스키마에서 글로벌이기 때문에, targetNamespace에 자동으로 연결된다. 즉, type 속성에서 EmployeeType을 참조하려면 반드시 정규화(qualified) 이름을 사용해야 한다는 뜻이다. 이 글 위쪽에서 정의한 anonymous xsd:complexType 을 named 유형으로 변경하는 것은 어렵지 않다. 이러한 두 기법간의 변경은 매우 쉽다.

named 유형을 사용하는 또다른 장점으로, 원하지 않는다면 스키마에서 글로벌 요소를 사용할 필요가 없다는 것이다. 그대신 인스턴스 문서에서 xsi:type 속성을 통해 요소의 type을 명시적으로 지정할 수 있다. xsi:sype 은 http://www.w3org/2001/XMLSchema-instance 네임스페이스에 있다. 예를들어, 이러한 임무를 수행하기 위해 아래와 같은 인스턴스를 고려해 보자.

<foo xsi:type="tns:EmployeeType"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:tns="http://example.org/employee/">

  <name>Monica</name>
  <hiredate>1997-12-02</hiredate>
  <salary>42000.00</salary>
</foo>

이 foo 요소는 스키마 어디에서도 정의되어 있지 않으나, 나는 이 유형을 명시적으로 지정하였다. 이것만으로도 XML 프로세서가 이 내용을 어떻게 처리해야 할 지 파악한다. 이 기법은 대부분의 프로그래밍 언어에서의 cast 기법과 유사하다.

데이터 유형 소개(Introducing Data Types)

이제까지 xsd:attribute, xsd:element, xsd:complexType 정의를 통해 문서의 자세한 구조를 서술하는 방법을 다뤘다. 하지만, 하지만, 지금까지 본 스키마에서는 name, hiredate, salary 요소 및 id 속성의 특성에 대해서는 설명하지 않았다. 지금 시점에는 이 요소들과 속성에는 아무것이나 들어가도 적법하다. name, hiredate, salary 요소와 id 속성은 특정한 형식에 따른 문자만 포함되어야 한다.

DTD에서는 #PCDATA 토큰을 통하여 어떤 요소에 오직 문자만이 포함되도록 지정할 수 있다.

<!ELEMENT name (#PCDATA)>

불행히도, 그 요소내에 포함된 문자열 형식은 아무 것도 지정할 수 없다.


<그림 8> XML Schema 내장 데이터 유형

이것이 XML Schema가 과거의 DTD에 비해 크게 약진한 것이다. (특히 소프트웨어 개발자에게) XML Schema는 텍트트 요소 및 속성의 내용을 제한하는데 사용할 수 있는 여러가지 데이터 유형을 정의한다. (그림 8) 각각의 데이터 유형은 명시적으로 정의된 값영역과, 명시적으로 정의된 사전 공간(lexical space : 다른 말로 XML 문서에 사용 가능한 문자열 포맷)이 있다. 예를 들어 double 값 4,200은 그림 9와 같이 다양한 방법으로 사전적으로 표현할 수 있다. 주어진 데이터 유형에 대한 값공간 및 사전 공간에 대한 자세한 내용은 XML Schema 사양 Part 2에 명시되어 있다. ("Recommended Reading" 사이드바에 있는 관련 URL 참고)


<그림 9> 사전적 표현

따라서, 어떤 요소나 속성에 사용되는 문자열을 제한하기 위해서는 적절한 값/사전적 공간을 선택하고, 아래와 같이 type 요소에 적용하면 된다.

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:tns="http://example.org/employee/"
  targetNamespace="http://example.org/employee/">

  <xsd:complexType name="EmployeeType">
    <xsd:sequence>
      <xsd:element name="name" type="xsd:string"/>
      <xsd:element name="hiredate" type="xsd:date"/>
      <xsd:element name="salary" type="xsd:double"/>       
    </xsd:sequence> 
    <xsd:attribute name="id" type="xsd:string"/>
  </xsd:complexType> 
  <xsd:element name="employee" type="tns:EmployeeType"/>

</xsd:schema>

스키마 프로세서가 이전 스키마의 인스턴스를 검증할 때 각각의 요소/속성에 포함된 문자가 정의된 유형의 사전적 표현에 적합한지 확인하게 된다.

그림 8에서 볼 수 있는 바와 같이 모든 상황에 맞는 데이터 유형이 있다. 그럼에도 불구하고, 내장 데이터 유형이 자신의 필요에 정확하게 맞지 않을 경우가 발생할 수 있다. 예를 들어 이전 스키마 정의에서 id 속성은 string 유형이지만, 실제 원하는 건 사회보장번호(Social Security Numer)일 수 있다. XML Schema 는 이러한 상황에 맞는 맞춤형 simple 유형을 정의할 방법이 있지만, 이건 이 글 후편을 기대하시라.

뒷 마무리글

XML Schema는 DTD의 한계와 약점을 모두 극복했다. XML Schema 문법은 XML 1.0 을 따른다. XML Schema는 네임스페이스를 완전히 지원하도록 설계되었다. 또한 가장 중요한 것은 XML Schema를 사용하면 전형적인 프로그래밍 언어의 데이터 유형 및 맞춤형 simple/complex 유형을 지원한다는 것이다.

비록 W3C 가 최근에 최종 XML Schema 권고사항을 발행했지만, (2001년 5월), 다양한 XML 및 Web 서비스 관련 인프라를 통해 이미 이 사양이 널리 지원받고 있다. 이 인프라에는 XML Schema를 기반으로 XML 프로세싱 코드를 자동적으로 생성하고, 실시간으로 동적 proxy/stubs를 build하며, 에디터와 기타 도구에 IntelliSense® 를 제공하며, 스키마 검증 기법을 통해 에러 처리를 간략히 하는 등이 포함된다. MSXML 4.0, SOAP 툴킷 2.0, .NET 등이 모두 XML Schema를 사용했을 때 성취할 수 있는 훌륭한 예들이다.

이번 달의 글은 기본 XML Schema만을 다루고 있다. 나는 DTD에서 제공한 모든 기능 및 몇몇 추가 기능을 설명하였다. 2부에서는 XML Schema의 고급 기능을 다루고자 한다.

===

원문 : https://msdn.microsoft.com/en-us/library/bb986126.aspx

Posted by 푸른하늘 푸른하늘이

댓글을 달아 주세요

공간정보/표준2017. 12. 24. 14:29

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 유형을 사용하기

  • 클래스/유형을 먼저 정의하고, 요소 정의를 재활용. 


===

원문 : https://www.w3schools.com/xml/schema_intro.asp 에서...

Posted by 푸른하늘 푸른하늘이

댓글을 달아 주세요

공간정보/표준2017. 12. 24. 12:06

이 글은 W3C 의 XML 투토리얼에 있는 내용을 간략히 정리한 것입니다. 

저는 현재 공간정보 표준들을 정리하는 중입니다. 지형지물목록이나 메타데이터 등의 많은 표준들이 XML 을 표준으로 사용하고 있기 때문에 어쩔 수 없이 이 글을 찾아보게 된겁니다. 

그런데... XML이 정보를 담기위한 목적이라는 것은 어렴풋이 알고 있었지만, 이렇게 광범위하게 사용될 수 있을지는 몰랐네요. 아주 간략하게 어떤 기능이 있는지 어떻게 활용할 수 있는지에 대해서만 수박 겉핥기 식으로 훝어봤습니다만, 많이 도움이 될 것 같습니다. 이 글을 방문하신 분들도 저처럼 도움이 되시길 바랍니다.

XML 이란

  • eXtensible Markup Language
  • HTML과 비슷한 마크업 언어
    • HTML은 표현. XML은 데이터 그 자체
    • XML에서는 tag가 미리 정의되어 있지 않음
  • 데이터를 저장하거나 전송하는 목적
    • 표현과는 관련이 없다.
  • self-descriptive (하나의 문서만으로 모든 것을 설명할 수 있게) 설계됨
  • W3C에서 추천함
    • 데이터 공유가 쉽다. 
    • 전송이 쉽다
    • 플랫폼에 독립적이다.
    • 데이터 사용을 쉽게 한다.

XML은 어떻게 사용하는가

  • 데이터와 표현을 분리한다. (XML에는 표현하기 위한 어떤 정보도 없다)
  • HTML에 보조하여 사용하기도 한다.
  • 별도의 XML 파일로 저장하고, JavaScript로 HTML에 읽어들일 수 있다.
  • 산업분야별로 정해진 XML 포맷이 있다. 이것을 사용하여 데이터를 전송한다.
    • 예를 들어 XML News 는 뉴스를 교환하기 위한 사양이다.
    • NOAA의 날씨 서비스는 XML Weather Service를 이용한다.

XML의 트리구조

  • root 엘리먼트 밑에 child 엘리먼트가 있다. 
  • parent - child - sibling
  • 모든 엘리먼트는 내용(text content)와 속성(attribute 예: category="cooking") 을 가질 수 있다.

XML의 구조 규칙 ("Well Formed")

  • 반드시 Root 엘리먼트(모든 엘리먼트의 parent)가 있어야 한다. 
  • prolog는 첫줄에 있어야 한다. (선택)
    • <?xml version="1.0" encoding="UTF-8"?>
    • UTF-8이 기존 문자인코딩이다. (HTML5, CSS, JavaScript, PHP, SQL 등에서도 UTF-8이 기본)
  • 모든 XML 엘리먼트는 끝 태그(closing tag)가 있어야 한다.
    • prolog의 경우엔 xml 문서요소가 아니므로 끝 태그가 없다.
  • XML 태그는 대소문자를 구분한다. 시작태그와 끝태그는 동일해야 한다.
  • 중첩순서가 맞아야 한다. - First in Last out
  • XML 속성값은 반드시 "따옴표" 로 묶어야 함.
    • <note date="12/11/2007">
  • 특수문자는... 
    • &lt;    &gt;    &amp;   &apos;   &quot;
  • 코멘트는 
    • <!-- 이렇게 하면 코멘트 -->
  • XML에서는 blank를 여러개 사용해도 무방하다.

XML 엘리먼트

  • 시작태그와 끝태그 사이에 있는 모든 것. (시작태그와 끝태그도 포함
  • 엘리먼트는 다음과 같은 것들을 가질 수 있다.
    • text
    • attribute
    • 다른 element
  • Empty Element도 존재할 수 있고, 속성을 가질 수 있다. 아래 두가지 형태 모두 허용
    • <element></element>
    • <element />
  • XML 명명 규칙
    • 대소문자 구분. 시작은 문자또는 underscore
    • xml,XML,Xml 등으로 시작할 수 없음
    • 문자, 숫자, 하이픈, underscore, 마침표(. period)를 포함해도 된다.
    • 공백은 포함할 수 없다.
  • 이름 지을때 주의할 점
    • 마이너스, 마침표, 콜론 등은 사용하지 않는 게 좋고, plain 알파벳을 사용하는 것이 좋다.
  • 명명 스타일은 정해진 게 없다
    • 전체소문자, 전체대문자,_로 연결, Pascal case, Camel case 모두 허용
    • 무엇을 사용하던 일관성있게 사용하라.
  • Element는 확장 가능하다.
    • 확장하여 추가하더라도, 어플쪽엔 아무런 문제도 없다.

XML 속성

  • 반드시 따옴표 사용. 홑따옴표, 곁따옴표 모두 OK
    • <person gender="female">
    • <person gender='female'>
  • 따옴표 내에 따옴표 있을 경우, 다른 것을 사용하던지 &quot;를 사용
  • 무엇을 속성으로 할지, 엘리먼트로 할지는 정해진 것이 없음. 편한대로. 정보도 동일함
  • 되도록이면 ATTRIBUTE 보다는 Element를 사용
    • 엘리먼트는 값을 여러개 가질 수도 있고, 트리구조를 가질 수 있고, 쉽게 확장할 수 있음.

XML 네임스페이스

  • 다른 응용에 속한 XML 문서를 찹치려고 하면 충돌이 발생할 수 있음
  • 이름접두어(name prefix)를 사용하면 해결가능 <h:table> <h:tr> ... </h:tr> </h:table>
  • 접두어를 사용하려면 네임스페이스를 반드시 정의해야 함.
    • <h:table xmlns="namespaceURI"> <h:tr> ... </h:tr> </h:table> 등으로 사용.
    • xmlns 는 속성. 이 속성이 이하에 있는 h: 접두어에 대해 적법한 네임스페이스를 지정함
    • 네임스페이스를 어떤 엘리먼트에 정의하면, 그 prefix를 사용하는 모든 자식 엘리먼트는 해당 네임스페이스에 속하게 됨.
  • 네임스페이스를 root 엘리먼트에 한꺼번에 정의할 수도 있음
    • 단, 여기에 있는 URI는 parser가 사용하지 않음. 고유한 이름을 지정하는 목적일 뿐.
    • 하지만, 네임스페이스 정보가 담긴 웹페이지를 가르키는 포인터로서 네임스페이스를 사용하는 경우가 많음.

<root xmlns:h="http://www.w3.org/TR/html4/"
xmlns:f="https://www.w3schools.com/furniture"
>

<h:table>
  <h:tr>
    <h:td>Apples</h:td>
    <h:td>Bananas</h:td>
  </h:tr>
</h:table>
<f:table>
  <f:name>African Coffee Table</f:name>
  <f:width>80</f:width>
  <f:length>120</f:length>
</f:table>
</root>

  • default 네임스페이스를 사용하면 각 엘리먼트마다 접두사를 붙일 필요없음
    • <table xmlns="namespaceURI"> <tr> ... </tr> </table>

XML 디스플레이

  • xml 파일을 그냥 브라우저에서 보면, 브라우저 별로 다르게 보인다. 
  • 소스보기를 하면 원래 파일의 내용을 볼 수 있다.
  • xml 파일에 오류가 있으면 오류를 표시하기도 하고, 아무것도 안보이기도 한다.
  • 이렇게 제각각으로 보이는 것은 XML에 표시에 관한 아무런 정보도 없기 때문이다.
  • CSS 를 이용해서 보이는 방법도 있지만, 추천되는 방법은 아니다.

XML HttpRequest

  • 대부분의 최신 브라우저는 서버로부터 데이터를 요청하는 XMLHttpRequest 오브젝트가 있다. 이를 사용하면 다음과 같은 장점이 있다.
    • 페이지를 새로 부르지 않고 페이지를 갱신할 수 있음
    • 페이지가 전송된 후 데이터를 전송하고 수신할 수 있다.
    • 백그라운드로 서버에 데이터를 송신할 수 있다.
  • 자세한 내용은 이 블로그의 글을 참조

XML 해석기

  • 대부분의 브라우저는 XML 해석기(parser)가 내장되어 있음. 아래와 같이 사용가능

<script>
var text, parser, xmlDoc;

text = "<bookstore><book>" +
"<title>Everyday Italian</title>" +
"<author>Giada De Laurentiis</author>" +
"<year>2005</year>" +
"</book></bookstore>";

parser = new DOMParser(); 
xmlDoc = parser.parseFromString(text,"text/xml");

document.getElementById("demo").innerHTML =
xmlDoc.getElementsByTagName("title")[0].childNodes[0].nodeValue;
</script>

  • XMLHttpRequest 객체는 XML 해석기가 내장되어 있음
    • responseText 프로퍼티는 string 형식의 응답이 들어있음
    • responseXML 프로퍼티에는 XML 형식의 응답이 들어 있음

XML DOM

  • DOM(Document Object Model)은 플랫폼/언어 중립적 인터페이스로서, 이를 통해 프로그램이나 스크립트에서 문서의 내용과 구조, 스타일을 동적으로 접근/갱신할 수 있다.
  • HTML이나 XML을 트리구조로 표현
    • getElementById() 등의 함수를 이용해 접근가능

XML 과 XPath

  • XPath는 XSLT 표준의 중요 요소이다.
  • XPath는 XML 문서에서 엘리먼트와 속성을 방문하는데 사용된다.


    • XPath는 XML 문서의 부분을 정의하는 문법이다.
    • XPath는 XML 문서를 방문하기 위한 경로표현식(path expression)을 사용한다.
    • XPath는 표준 함수의 라이브러리를 포함한다.
    • XPath는 W3C에서 추천한다.
 
  • XPath는 경로 표현식(Path Expression)을 사용하여 XML 문서의 노드를 선택한다. 이 경로표현식은 컴퓨터 파일시스템의 경로와 비슷한 형태이다.
  • XPath는 JavaScript, Java, XML Schema, PHP, Python, C, C++ 등 많은 언어에서 사용된다.
  • XSLT에서도 사용된다. XPath를 알면 XSL을 잘 활용할 수 있다.
  • 예제
    • /bookstore/book[1]    -> bookstore 엘리먼트의 자손들중 첫번째 book 엘리먼트 선택
    • /bookstore/book[last()-1)     -> ... 끝에서 두번째 엘리먼트 선택
    • /bookstore/book[postion()<3]     -> ... 처음 두개의 엘리먼트 선택
    • //title[@lang='en']            -> "lang" 속성이 "en"인 모든 title 엘리먼트 선택
    • //bookstore/book[price>35.00]/title          -> price 엘리먼트의 값이 35.00보다큰 모든 book 엘리먼트의 title 엘리먼트를 선택하라.
  • XPath 투토리얼

XML 과 XSLT

  • XSLT는 XML 문서를 HTML로 변환하는데 사용한다.
  • XSLT(eXtensible Stylesheet Language Transformations)는 XML을 위한 추천 스타일시트 언어
  • CSS 보다 훨씬 복잡함. XSLT를 사용하면 출력 파일로부터 엘리먼트나 속성을 추가/제거할 수 있음 재배열, 정렬도 가능하고, 테스트도 가능, 어떤 요소를 숨길지 표시할지 결정할 수 있음
  • XSLT는 XPath를 사용하여 XML 문서에서 정보를 찾아냄
  • XSLT 투토리얼

XML과 XQuery

  • XQuery는 SQL로 데이터베이스를 검색하는 것과 같은 역할을 한다.
  • XQuery는 XML데이터를 query할 수 있도록 설계되었다.
  • 예제 : SQL과 비슷하다.

for $x in doc("books.xml")/bookstore/book
where $x/price>30
order by $x/title
return $x/title

  • XQuery란
    • XML 데이터를 qurey 하기 위한 언어
    • SQL : 데이터베이스 = XQuery : XML
    • XQuery는 XPath 표현식을 기반으로 한다.
    • XQuery는 중요한 Database에서 지원한다.
    • XQuery는 W3C에서 추천한다. 
  • XQuery로 할 수 있는 일
    • Web서비스에서 정보추출에 사용
    • 요약 보고서 생성
    • XML 데이터를 XHTML로 변환
    • 웹 문서에서 관련 정보를 검색
  • W3C의 추천
    • XML, 네임스페이스, XSLT, XPath, XML Schema 등과 같은 W3C 표준과 호환된다.
    • XQuery 1.0은 2007년에 W3C의 추천으로 등록됨
  • XQuery Tutorial

XML 과 XLink. 그리고 XPointer

  • XLink는 XML 문서에서 하이퍼링크를 생성하는데 사용한다.
  • XML 문서중 모든 요소를 링크처럼 만들 수 있다.
  • XLink를 사용하면 링크가 문서 바깥에 존재한다.
  • WLink는 W3C에서 추천
  • XML 문서에 대한 XLink를 지원하는 브라우저는 없다.
    • 하지만, 중요 브라우저는 모두 SVG에서 XLink를 지원한다.
  • XLink 문법
    • HTML에서는 <a> 태그로 하이퍼링크를 만들지만, XML에서는 어떤 엘리먼트는 사용할 수 있으므로, 어떤 요소이름이 하이퍼링크가 될지 알 수 없다. 
    • 아래와 같은 방식으로 XLink를 만든다.
      • XLink기능을 사용하려면 XLink 네임스페이스를 선언해야 한다. 
        • xmlns:xlink="http://www.w3.org/1999/xlink"
        • xlink:type , xlink:href 속성은 XLink 네임스페이스에서 온 것이다.
        • xlink:type="symple" 을 사용하면 HTML 형식의 링크를 만들 수 있다.

<?xml version="1.0" encoding="UTF-8"?>
<homepages xmlns:xlink="http://www.w3.org/1999/xlink">
  <homepage xlink:type="simple" xlink:href="https://www.w3schools.com">Visit W3Schools</homepage>
  <homepage xlink:type="simple" xlink:href="http://www.w3.org">Visit W3C</homepage>
</homepages>

  • XPointer

    • XPointer를 사용하면 XML 문서 특정부분에 링크를 생성할 수 있다.
    • XPointer는 XPath 표현식을 사용하여 XML 문서를 방문한다.
    • XPointer는 W3C 추천.
  • XPointer의 브라우저 지원
    • XPointer를 지원하는 브라우저는 없다. 하지만, 다른 XML 언어에서는 사용된다.

XML Validator

  •  XML 문법 체크
    • root 요소가 반드시 존재해야 한다.
    • 모든 요소는 끝태그가 있어야 한다.
    • 모든 태그는 대소문자 구분
    • XML 요소들이 올바르게 중첩되어야 한다.
    • 속성 값은 반드시 "따옴표"로 묶어야 한다.
  • XML 의 경우 절대 오류가 있어서는 안된다!!!

XML DTD

  • 문법에 맞는 XML 문서는 "Well Formed"라고 함
  • DTD에 대해 검증받은 XML 문서는 "Well Formed" 하며 "Valid" 함 
    • 아래에서 !DOCTYPE 선언이 외부파일 Note.dtd를 참조하고 있음

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note SYSTEM "Note.dtd">
<note>
    <to>Tove</to>
    <from>Jani</from>
    <body>Don't forget this weekend!</body>
</note>

<!DOCTYPE note                        ->root 엘리먼트
[
<!ELEMENT note (to, from, body)> -> note 요소는 반드시 to, from, body 요소를 포함해야 함
<!ELEMENT to (#PCDATA)>          ->to 요소는 "#PCDATA" 유형이어야 함. 
<!ELEMENT from (#PCDATA)>      -> #PCDATA란 parse-able text data (파싱 가능한 텍스트)
<!ELEMENT body (#PCDATA)>
]>

  • DOCTYPE은 특수문자를 정의하는데 사용할 수도 있음
    • <!ENTITY writer "Writer: Donald Duck."> 이렇게 정의한 뒤
    • <body> &writer;</body> 라고 사용하면 이 부분이 위 정의로 대체된다.
  • DTD/schema를 사용하면
    • 여러 그룹들이 표준 DTD를 사용하여 자료교환 가능
    • 외부에서 받은 데이터가 유효한지 확인할 수 있음
    • DTD로 자신의 데이터도 확인할 수 있음
  • 다만, 아직 추천사항도 아니고, XML의 요구조건도 아니므로, 구지 사용할 필요 없음.
  • DTD Tutorial 참고

XML Schema

  • XML Schema는 XML 문서의 구조를 설명함
  • XML Schema는 XML 기반으로 DTD 대체.

<xs:element name="note">                    -> note라는 요소를 정의함
<xs:complexType>                                -> note는 complex 유형임
    <xs:sequence>                                 -> 이 complex 유형은 요소들이 나열된 형태임
        <xs:element name="to" type="xs:string">         ->"to" 요소는 string 유형임
        <xs:element name="from" type="xs:string">
        <xs:element name="body" type="xs:string">
    </xs:sequence>
</xs:complexType>
</xs:element>

  • XML Schema는 DTD보다 훨씬 강력하다.
    • XML Schema 자체가 XML로 작성됨
    • 쉽게 추가할 수 있음
    • datatype을 지원함
    • 네임스페이스를 지원함
  • XML Schema를 사용해야 하는 이유
    • 해당 XML 파일에 대한 설명을 제공
    • 여러 그룹에서 표준으로 자료교환 가능
    • 데이터 검증이 가능
  • XML이 데이터유형을 지원한다는 것은??
    • 문서 내용을 쉽게 설명할 수 있다.
    • 데이터의 정확성을 쉽게 검증할 수 있다.
    • 데이터 제한사항을 쉽게 정의할 수 있다.
    • 다른 유형으로 쉽게 변환할 수 있다.
  • XML Schema는 XML 문법을 사용한다. 따라서
    • 새로운 언어를 배울 필요 없고
    • XML 에디터로 스키마 파일을 편집할 수 있고
    • XML parser로 스키마 파일을 해석할 수 있고
    • XML DOM으로 처리할 수 있으며
    • XSLT로 자료를 변환할 수 있다. 아주 좋은 점이 많다는 말씀. DTD를 쓰는 건 말이 안됨.
  • XML Schema Tutorial 을 참고할 것

XML Server

  • XML 파일은 단순한 텍스트 파일. 웹서버로 저장/생성하기 쉽다.
  • PHP로 생성하는 것도 어렵지 않고. (다만 header("Content-type: text/xml")로... 지정해야 한다.
  • asp로 생성하는 것도 물론 가능하고
  • Database로부터 생성할 수도 있다.

XML 예제 파일들


Posted by 푸른하늘 푸른하늘이

댓글을 달아 주세요