우선, XSDObjectGen.exe와 스키마 상속 처리에 대한 부분을 진행하기에 앞서, 관련된 사전 지식을 익혀보도록 하겠습니다.
소규모 시스템이라면 몰라도, 웬만한 인트라넷 시스템만 해도 무수한 Type들이 정의되게 됩니다.
수많은 Complex Type들이 생성되는 데, 과연 그것들을 "하나의 XSD 파일" 안에 모두 관리하는 것이 효율적일까요?
물론, 대답은 "No"입니다.
그렇다면, 스키마를 일관성 있는 규칙 아래 나눠야 할 텐데요. 우선, 제가 원하는 기능을 구현하기 전에 "스키마 상속"에 대한 부분부터 설명해 보겠습니다.
예제는, 계속해서 지난번 토픽에서 소개했던 스키마를 그대로 이어서 설명하겠습니다. (지난번 예제와 틀린 점이 있다면, namespace 관련 부분을 기본값인 "tempuri.org"가 아닌 "https://www.sysnet.pe.kr/DataTypes.xsd"를 사용했다는 것 뿐입니다.)
===== DataTypes.xsd ======
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="DataTypes"
targetNamespace="https://www.sysnet.pe.kr/DataTypes.xsd" elementFormDefault="qualified"
xmlns="https://www.sysnet.pe.kr/DataTypes.xsd" xmlns:mstns="https://www.sysnet.pe.kr/DataTypes.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="TFSAddItemT">
<xs:attribute name="Name" type="xs:string" />
<xs:attribute name="Port" type="xs:int" />
<xs:attribute name="Protocol" type="ProtocolEnum" />
</xs:complexType>
<xs:simpleType name="ProtocolEnum">
<xs:restriction base="xs:short">
<xs:enumeration id="HTTP" value="80" />
<xs:enumeration id="HTTPS" value="8080" />
</xs:restriction>
</xs:simpleType>
<xs:element name="CollectionDef">
<xs:complexType>
<xs:sequence>
<xs:element name="TFSAddItemList" type="TFSAddItemT" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
그럼, 가정을 해볼까요. 위의 스키마 파일의 내용과 전혀 무관한 다른 업무의 Complex Type, 또는 위의 스키마가 너무 복잡해져서 다른 파일을 하나 생성한다고 여기고, 또 다른 스키마 파일을 하나 생성해 보겠습니다.
========== DerivedSchema.xsd ==============
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="DerivedSchema"
targetNamespace="https://www.sysnet.pe.kr/DerivedSchema.xsd" elementFormDefault="qualified"
xmlns="https://www.sysnet.pe.kr/DerivedSchema.xsd" xmlns:mstns="https://www.sysnet.pe.kr/DerivedSchema.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="DerivedLocation">
<xs:sequence>
<xs:element name="Location" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:schema>
그런데, 우리는 위에서 정의한 Location 요소를 DataTypes.xsd에 정의되어 있는 TFSAddItemT를 사용하고 싶습니다. 자, 그럼 어떻게 해야 할까요? ^^
하나씩 단계별로 수정해 보도록 하겠습니다.
1. DataTypes.xsd 스키마를 import 시킵니다. 다음과 같은 구문으로 가능합니다.
<xs:import id="dtypes" namespace="https://www.sysnet.pe.kr/DataTypes.xsd" schemaLocation="DataTypes.xsd">
</xs:import>
2. DataTypes.xsd의 네임스페이스, 즉 "https://www.sysnet.pe.kr/DataTypes.xsd"에 대한 네임스페이스 이름을 지정합니다. 이를 위해서 xs:schema에 네임스페이스를 정의합니다.
<xs:schema id="DerivedSchema"
targetNamespace="https://www.sysnet.pe.kr/DerivedSchema.xsd" elementFormDefault="qualified"
xmlns="https://www.sysnet.pe.kr/DerivedSchema.xsd" xmlns:mstns="https://www.sysnet.pe.kr/DerivedSchema.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:dtypes="https://www.sysnet.pe.kr/DataTypes.xsd">
xmlns:dtypes의 "dtypes" 이름은 어느 것으로 주어도 상관없습니다. 원하는 이름을 자유롭게 사용하실 수 있습니다.
3. Location 요소의 타입을 변경합니다. 네임스페이스 이름과 함께 string을 TFSAddItemT로 바꿔줍니다.
<xs:sequence>
<xs:element name="Location" type="dtypes:TFSAddItemT" />
</xs:sequence>
자, 이제 모든 변경은 완료되었습니다. 최종 스키마 내용과, VS.NET 2005의 XSD Designer로 확인한 화면은 아래와 같습니다.
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="DerivedSchema" targetNamespace="https://www.sysnet.pe.kr/DerivedSchema.xsd" elementFormDefault="qualified" xmlns="https://www.sysnet.pe.kr/DerivedSchema.xsd" xmlns:mstns="https://www.sysnet.pe.kr/DerivedSchema.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:dtypes="https://www.sysnet.pe.kr/DataTypes.xsd">
<xs:import id="dtypes" namespace="https://www.sysnet.pe.kr/DataTypes.xsd" schemaLocation="DataTypes.xsd">
</xs:import>
<xs:complexType name="DerivedLocation">
<xs:sequence>
<xs:element name="Location" type="dtypes:TFSAddItemT" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="TFSAddExT">
<xs:complexContent>
<xs:extension base="dtypes:TFSAddItemT">
<xs:sequence />
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
물론, 요소뿐만 아니라 Complex Type 자체도 상속을 받아서 정의하는 것이 가능합니다. 예를 들어 다음과 같은 경우입니다.
<xs:complexType name="TFSAddExT">
<xs:complexContent>
<xs:extension base="dtypes:TFSAddItemT">
<xs:sequence />
</xs:extension>
</xs:complexContent>
</xs:complexType>
자, 다음번에는 실제로 XSDObjectGen.exe에서 이를 어떻게 처리하는지 알아보도록 하겠습니다.
첨부된 솔루션은, 지난번 예제에서 단지 DerivedSchema.xsd 파일만 더 추가된 예제입니다.