분류 전체보기 (328)
.NET (111)
S/W tip (35)
etc (63)
DB (34)
HOT item~! (48)
Disign pettens (4)
UX (6)
나의 S/W (2)
개발관련 이슈 (16)
Diary (1)
웹플러스 (1)
calendar
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
tags
archive
link
ColorSwitch 00 01 02

http://blog.naver.com/dolmoon/60051473626
 

객체 직렬화와 관련된 일반적인 사항들은 다음 사이트를 참고한다.

http://en.wikipedia.org/wiki/Serialization

http://msdn.microsoft.com/ko-kr/library/system.serializableattribute.aspx



Serialization(직렬화) : WikiPedia에 나와 있는 정의를 대충(?) 요약하면 다음과 같다.

In computer science, in the context of data storage and transmission, serialization is the process of saving an object onto a storage medium (such as a file, or a memory buffer) or to transmit it across a network connection link in binary form. The series of bytes or the format can be used to re-create an object that is identical in its internal state to the original object (actually, a clone).

This process of serializing an object is also called deflating or marshalling an object. The opposite operation, extracting a data structure from a series of bytes, is deserialization (which is also called inflating or unmarshalling).

직렬화는 객체를 저장매체(파일이나 메모리와 같은)에 저장하거나 바이너리(이진) 형태로 네트워크를 통해 전달하기 위해 저장하는 과정이다. 이(객체를 직렬화한) 연속된 바이트나 포맷은 다시 원래 객체가 가지고 있던 상태로 객체를 재생성하는데 사용할 수 있다. 이렇게 객체를 직렬화하는 과정은 디플레이팅(deflating) 또는 마샬링(marshalling)이라고도 부른다. 직렬화와는 반대로 연속된 바이트로부터 어떤 데이터 구조를 추출해내는 과정을 역직렬화(deserialization)라고 한다. 역직렬화는 인플레이팅(inflating) 또는 언마샬링(unmarshalling)이라 불리기도 한다.

 

간단한 직렬화 예제

C#에서 객체 직렬화가 가능한 클래스를 만들기 위해서는 다음 한 가지만 처리하면 된다.

  • SerializableAttribute 특성을 클래스에 적용한다.

다음은 클래스에 SerializableAttribute 특성을 적용하여 직렬화하고 역 직렬화하는 예제이다.

using System;
using System.Runtime.Serialization.Formatters.Soap; //SOAP Formatter를 이용하여 직렬화, 역직렬화할 경우에 사용한다.
//using System.Runtime.Serialization.Formatters.Binary; //Binary Formatter를 이용하여 직렬화, 역직렬화할 경우에 사용한다.
using System.IO;


namespace Infodigm
{
    [Serializable()]   //클래스에 SerializableAttribute 특성을 적용하여 직렬화 가능한 클래스로 지정한다.
    class SerializablePeople
    {
        private string _name;

        private readonly string _socialSecurityNumber;


        public string Name //public 멤버는 직렬화에 포함된다.
        {
            get { return _name; }
            set { _name = value; }
        }


        public string SocialSecurityNumber
        {
            get { return _socialSecurityNumber; }
        }


        public SerializablePeople(string name, string socialSecurityNo)
        {
            _name = name;
            _socialSecurityNumber = socialSecurityNo;
        }


        public override string ToString()
        {
            return "Name = " + _name + ", SocialSecurityNo = " + _socialSecurityNumber;
        }
    }


    static class Program
    {
        static void Main(string[] args)
        {

            //클래스 오브젝트 생성
            SerializablePeople people = new SerializablePeople("홍길동", "111111-1111111");
            Console.WriteLine("원본 : " + people.ToString());

            //직렬화해서 저장할 파일스트림을 연다.
            Stream stream = File.Open("data.xml", FileMode.Create);

            //SOAP Formatter 개체를 만든다.
            SoapFormatter soapFormatter = new SoapFormatter();
            //BinaryFormatter binaryFormatter = new BinaryFormatter();

            //오브젝트를 SOAP Formatter로 직렬화하여 파일스트림으로 내보낸다.
            soapFormatter.Serialize(stream, people);
            //binaryFormatter.Serialize(stream, people);

            //파일 스트림을 닫는다.
            stream.Close();

            people.Name = "DESERIALIZED";
            Console.WriteLine("직렬화 후 원본변경 : " + people.ToString());
            people = null;

            //직렬화된 파일을 연다.

            stream = File.Open("data.xml", FileMode.Open);

            //파일로부터 역직렬화하여 원래 오브젝트로 캐스팅한다.
            SerializablePeople deSerializedPeople = (SerializablePeople)soapFormatter.Deserialize(stream);
            //SerializablePeople deSerializedPeople = (SerializablePeople)binaryFormatter.Deserialize(stream);
            stream.Close();
            Console.WriteLine("직렬화된 데이터 복원 : " + deSerializedPeople.ToString());

            Console.ReadLine();
        }
    }
}


※ SoapFormatter를 사용했을 때 주의할 점은 .NET Framework 버전의 호환이 되지않는다는 점이다.

이점과 관련해서는 MSDN에 다음과 같이 설명되어 있다

  • SoapFormatter는 .NET Framework 버전 간의 serialization 호환성을 지원하지 않습니다. 따라서 Framework 버전 1.1 형식과 2.0 형식 간의 serialization은 실패할 수 있습니다. 이 문제를 해결하려면 다음을 수행합니다.

http://blog.naver.com/dolmoon/60051507361

다음 사이트에는 앞서 대충 살펴본 직렬화에 대한 좀 더 자세한 설명이 나온다.

http://www.codeproject.com/KB/cs/NetSerialization.aspx

위 사이트의 내용 중 Serialization을 이해하는데 도움이 될만한 내용만 추렸다.


직렬화의 장단점

직렬화의 주요한 장점은

  • DOM을 이용하지 않고 XML  문서를 수정할 수 있다.
  • 어떤 어플리케이션으로부터 다른 어플리케이션으로 객체를 전달할 수 있다.
  • 어떤 도메인으로부터 다른 도메인으로 객체를 전달할 수 있다.
  • 객체를 XML 문자열의 형태로 방화벽을 거쳐(통과해) 전달할 수 있다(방화벽에 제약을 받지 않고 객체를 전달할 수 있다).

반면 직렬화의 주요한 단점은

  • 직렬화와 역직렬화 과정에서 자원(CPU와 IO 장치)의 소모가 많다.
  • 네트워크를 통해 객체를 전달할 경우 지연 문제가 발생할 수 있다(직렬화 과정은 상당히 느리다).
  • XML로 직렬화하는 것은 안전하지 않으며(XML 문서의 형태로 저장할 경우 다른 프로그램이나 사용자가 실수나 고의로 문서의 내용을 변경할 수도 있다.), 많은 저장 공간을 차지하고, public 클래스에 대해서만 직렬화가 이루어질 수 있으므로 private 클래스 또는 internal 클래스는 직렬화할 수 없다(프로그래머로 하여금 직렬화를 지원하는 클래스를 만들기 위해 불필요한 public 클래스를 양산할 수도 있다).

SerializableAttribute 특성

Part II에서 직렬화 가능한 클래스를 만들기 위해서는 클래스에 SerializableAttribute 특성을 적용해야 한다고 했다. 이 특성이 적용된 클래스는 직렬화가 가능하다. 하지만, 그 클래스의 멤버 중 NonSerializableAttribute 특성이 적용된 멤버를 제외한 나머지 모든 멤버가 직렬화가 가능해야 한다. NonSerializableAttribute 특성이 적용된 멤버는 직렬화할 때 무시된다. SerializableAttrbute 특성이 적용된 클래스의 private 멤버와 public 멤버는 기본적으로 직렬화된다.


        [Serializable]
        public class Employee
        {
            public int empCode;
            public string empName;
        }


직렬화의 유형

직렬화는 다음과 같은 유형으로 나뉜다.

  • Binary Seralization
  • SOAP Serialization
  • XML Serialization
  • Custom Serialization

Binary Serialization

Binary Serialization은 출력 스트림에 데이터를 기록하는 메커니즘으로 이 출력 스트림은 객체를 자동으로 재구성하는데 사용할 수 있다. binary라는 용어가 저장매체에 저장되어 있는 객체와 동일한 복사본을 생성하는데 필요한 필수적인 정보라는 뜻을 가지고 있다. binary serialization과 XML serialization간의 주목할만한 차이는 binary serialization이 인스턴스의 identity(instance identity)를 가지고 있는 반면에 XML serialization은 그렇지 않다는 점이다. 다시 말하자면, binary serialization은 객체의 모든 상태값을 저장하고 있는 반면, XML serialization은 객체가 가지고 있는 데이터의 일부분만을 저장하고 있다는 것이다. binary serialization은 동일한 객체를 여러 곳에서 참조하는 그래프(graphs-object graphs; 역자주: object graphs의 정확한 의미를 모르겠다. 다만, 여기서는 순환참조와 같이 복잡한 참조 관계를 의미한다고 보면 이해하는데 큰 무리가 없을 것 같다)를 다룰 수 있다; XML serialization은 각 참조를 어떤 유니크한 객체에 대한 참조로 바꾼다.(?? XML serialization will turn each reference into a reference to a unique object).

관리되는 환경(managed environment)에서의 Binary Serialization의 주요한 장점은 객체를 직렬화한 그대로 역직렬화할 수 있다는 점이다(객체가 원래 가지고 있던 값들을 그대로 복원할 수 있다). 더구나, 속도가 빠른만큼 더 나은 성능을 보일 뿐만 아니라 복합적인 객체를 지원하고, 읽기전용(readonly) 속성과 순환참조(circular references)도 지원하는 등 더 강력하다. 하지만, 다른 플랫폼으로 이식하는 것이 쉽지 않다는 단점이 있다.


다음 코드는 Binary Serialization의 예이다.


        public void BinarySerialize(string filename, Employee emp)
        {
            FileStream fileStreamObject;

            try
            {

                fileStreamObject = new FileStream(filename, FileMode.Create);
                BinaryFormatter binaryFormatter = new BinaryFormatter();
                binaryFormatter.Serialize(fileStreamObject, emp);
            }

            finally
            {
                fileStreamObject.Close();
            }
        }


        public static object BinaryDeserialize(string filename)
        {
            FileStream fileStreamObject;

            try
            {
                fileStreamObject = new FileStream(filename, FileMode.Open);
                BinaryFormatter binaryFormatter = new BinaryFormatter();
                return (binaryFormatter.Deserialize(fileStreamObject));
            }

            finally
            {
                fileStreamObject.Close();
            }
        }

SOAP Serialization

SOAP 프로토콜은 서로 다른(heterogeneous) 아키텍쳐를 가지는 어플리케이션 간의 통신에 이상적이다. .NET에서 SOAP Serialization을 이용하려면 어플리케이션이 System.Runtime.Serialization.Formatters.Soap을 참조해야 한다. SOAP Serializaion의 기본적인 장점은

이식성이다. SoapFormatter는 객체를 직렬화해서 SOAP 메시지로 바꾸거나, SOAP 메시지로를 파싱해서 직렬화된 객체를 추출해낸다.


다음은 SOAP Serialization의 예제이다.


        public void SOAPSerialize(string filename, Employee employeeObject)
        {
            FileStream fileStreamObject = new FileStream(filename, FileMode.Create);
            SoapFormatter soapFormatter = new SoapFormatter();
            soapFormatter.Serialize(fileStreamObject, employeeObject);
            fileStreamObject.Close();
        }

        public void SOAPSerialize(string filename, Employee employeeObject)
        {
            FileStream fileStreamObject = new FileStream(filename, FileMode.Create);
            SoapFormatter soapFormatter = new SoapFormatter();
            soapFormatter.Serialize(fileStreamObject, employeeObject);
            fileStreamObject.Close();
        }


XML Serialization

MSDN에 따르면, "XML serialization은 어떤 오브젝트의 공용 필드와 속성 또는 메서드의 매개변수와 반환값을 명시적인 XML 스키마 정의 언어 문서(XSD; XML Schema definition language)에 맞는 XML 스트림으로 변환(직렬화)한다. XML serialization의 결과로 전송이나 저장을 위해 순차적인 포맷(여기서는 XML)으로 변환된, 공용 속성과 필드들을 가진 강력한 형식의 클래스(strongly typed classes)가 만들어진다. XML은 개방형 표준이기 때문에, 그 XML 스트림은 어떤 플랫폼이 어떤 프로그램에서도 처리될 수 있다."라고 되어 있다.

.NET에서 XML Serialization을 구현하는 것은 아주 쉽다. serializatin과 de-serialization을 위해 필요한 기본 클래스는 XmlSerializer이다. Web 서비스는 통신에 SOAP 프로토콜을 사용하는데, 이 XmlSerializer 클래스를 이용하여 반환형과 매개변수를 모두 직렬화한다. XML Serialization은 Binary Serialization과 비교하면 상당히 느리다.


        [XmlAttribute("empName")] //클래스의 멤버에 대해 개별적으로 XmlAttribute 특징을 적용할 수 있다.
        public string EmpName
        {
            get
            {
                return empName;
            }

            set
            {
                empName = value;
            }
        }


        public void XMLSerialize(Employee emp, String filename)
        {
            XmlSerializer serializer = null;
            FileStream stream = null;

            try
            {
                serializer = new XmlSerializer(typeof(Employee));
                stream = new FileStream(filename, FileMode.Create, FileAccess.Write);
                serializer.Serialize(stream, emp);
            }

            finally
            {
                if (stream != null)
                    stream.Close();
            }
        }


        public static Employee XMLDeserialize(String filename)
        {
            XmlSerializer serializer = null;
            FileStream stream = null;
            Employee emp = new Employee();

            try
            {
                serializer = new XmlSerializer(typeof(Employee));
                stream = new FileStream(filename, FileMode.Open);
                emp = (Employee)serializer.Deserialize(stream);
            }

            finally
            {
                if (stream != null)
                    stream.Close();
            }
            return emp;
        }


Formatters 활용하기

formatter는 객체의 직렬화 포맷을 결정한다. 다시 말하자면, 객체를 스트림으로 직렬화하거나 스트림을 역직렬화하여 객체를 재생성해내는 것을 제어한다. formatter는 객체를 네트워크를 통해 전송하기 전에 암호화하고 적합한 포맷으로 직렬화하는데 사용된다. formatter는 IFormatter라는 인터페이스를 노출시킨다(구현하고 있다). IFormatter의 중요한 메서드로는 실제 직렬화와 역직렬화를 수행하는 Serialize와 De-Seialize 메서드가 있다. .NET은 BinaryFormatter와 SoapFormatter라는 2개의 formatter 클래스를 제공한다. 이 두 클래스 모두 IFormatter 인터페이스를 구현하고 있다.


Binary Formatter

Binary formatter는 이진(binary) 인코딩을 이용한 직렬화하는 방법을 제공한다. BinaryFormater 클래스는 .NET의 Remoting기술에서 흔히 사용되는 이진 직렬화(binary serialziation)를 책임지고 있다. 이 클래스는 데이터가 방화벽을 통해 전달되어야 할 경우에는 적합하지 않다.

SOAP Formatter

SOAP formatter는 SOAP 프로토콜을 이용하는 객체의 직렬화에 사용된다. SOAP formatter는 Soap envelop을 생성는데 사용되고 결과를 생성하기 위해 객체 그래프(object graph; 인스턴스들 간의 참조 관계)이용한다(?? It is used to create a Soap envelop and it uses an object graph to generate the result). SOAP formatter는 객체를 직렬화해서 SOAP 메시지로 바꾸거나 SOAP 메시지를 파싱해 직렬화된 객체를 추출해내는 역할을 한다. SOAP formatter는 .NET에서 WebServices에 널리 사용된다.



기억해야 할 것

  • 어떤 형(클래스)에 SerializableAttribute 특성을 적용하면, 그 클래스의 모든 인스턴스 필드(private, public, protected, 기타)가 자동적으로 직렬화된다.
  • XMLSerializer는 ISerializable 인터페이스를 사용하지 않으며, 대신 IXmlSerializable 인터페이스를 사용한다. XmlSerializer 클래스는 BinaryFormatter클래스가 ISerializable 인터페이스를 이용하여 private 필드도 직렬화하는 것에 반하여, 해당 클래스의 public 속성들만 직렬화할 수 있다.
  • SerializableAttribute 특성은 어떤 클래스를 직렬화할 수 있게 만들기 위해서는 반드시 필요하다. 그 클래스가 ISerializable 인터페이스를 구현하든 하지 않든 상관없이.
  • 어떤 클래스를 직렬화할 때, 다른 클래스를 참조하는 객체가 그 클래스에 포함되어 있어도 그 객체가 직렬화가 가능하다고 표시되어 있으면 같이 직렬화된다. public, private 또는 protected 멤버를 포함하여 모든 멤버들이 직렬화된다.
  • 심지어 binary serialization을 이용하면 순환참조(circular references)도 직렬화할 수 있다.
  • 읽기전용 속성은 그 속성이 컬렉션 클래스의 객체인 경우를 제외하고는 직렬화되지 않는다는 점을 주의해야 한다(Note that read only properties are not serialized except the collection class objects). binary serialization을 이용하면 읽기전용 속성도 직렬화 할 수 있다.
  • XmlSerializer를 이용하여 어떤 클래스를 직렬화할 때, 그 클래스의 특정한 속성을 직렬화하지 않을 필요가 있다면, 그 속성에 XmlIgnoreAttribute 특성을 적용하여야만 한다. SoapFormatter를 사용하는 경우에는 SoapIgnoreAttribute 특성을 사용하여 직렬화하지 않도록 처리할 수 있다.
  • XmlSerializer를 Web Service에 이용할 경우에 XmlSerializer는 각 타입(형)에 대해 최초로 호출될 때마다 최적화된 in-memory 어셈블리를 생성한다. 이 작업은 많은 시간이 걸린다. 이 문제를 해결하기 위해서 sgen.exe 툴을 이용하여 그 serialization 어셈블리를 미리 생성해 놓는 방법을 사용할 수 있다.

※ 객체 그래프(Object Graph)란?

Object Graph는 Wikipedia에 다음과 같이 설명되어 있다.

An Object Graph is a view of an object system at a particular point in time. Whereas a normal data model details the relationships between objects, the object graph relates the instances.

객체 그래프는 어떤 특정 시점의 객체 시스템에 대한 뷰이다. 보통 Data Model이 객체들 간의 관계를 상세히 설명하는데 비해, 객체 그래프는 인스턴스들 간의 관계를 설명한다.

즉, 객체 그래프는 어떤 특정 시점의 인스턴스들 간의 참조 관계를 말하는 것으로 볼 수 있겠다.


▣  xml spy를 이용한 XSD - .NET/C# - 2009. 5. 12. 14:41
xml spy를 이용한 XSD 기초활용..
1-3+XSD.doc

사진 미출력시 원본을 다운받아 사용하시오..

 

============================================================================

1-3 XSD (XML Schema Definitions)

 

XML 문서의 형태를 정의하기 위한 DTD에는 지원되지 않는 기능들이 많다. 대표적인 것이 태그 중복을 허용하지 않고, 데이터 타입의 정의에 제약이 많다는 것들이다. 이런 것들은 DTD의 치명적인 결함이 되었고, 따라서 여러 업체와 기구들은 DTD의 제약을 넘어서는 XML 문서를 정의하는 규약을 만들기 시작했다.

 

XML 1.0이 발표되기 전에 마이크로소프트는 XML-Data라는 스키마 언어를 만들었다. 그 후에 IBM과 마이크로소프트가 공동으로 DCD(Document Content Description)이라는 스키마 언어를 만들었으며 CommerceOpen에서는 XML-Dev에서 DDML (Document Definition Markup Language)를 만들었다. XML을 위한 여러 스키마 언어들이 난립하였다. 여러 스키마 언어들이 난립하게 되자 W3C에서는 표준을 지정할 필요성을 느끼게 되었고, W3C는 XML Schema를 만들기 시작했다. 

 

XML Schema는 표준화 단계를 거쳐 2000년 10월에 Candidate Recommendation 버전으로 발표되었다. XML Schema는 B2B, EDI, 모바일, 데이터베이스등의 IT 기업에서 촉각을 곤두세우고 주시하고 있는 분야이다. 특히 DTD는 다양한 데이터 타입을 지원하지 않기 때문에 데이터베이스와 XML의 매끄러운 연결이 어려웠는데, XML Schema는 다양한 데이터 타입을 지원하므로 Microsoft, Oracle, IBM등의 데이터베이스 벤더에서 특별한 지원을 아끼지 않고 있다.

 

가.    DTD와 XML Schema

 

XML DTD가 있는데 XML Schema가 왜 등장하였을까? 우선, XML DTD는 XML형식이 아니다. XML DTD는 SGML의 DTD 형식을 그대로 가져왔다. 그러므로 XML DTD는 XML 형식이 아니므로 공통된 형식의 타입 정의가 불가능하고 또한 데이터 타입이나 요소의 반복의 형식 등이 제한적이어서 문서의 구성에 필요한 형식을 구성하는데 제한 사항이 많다. 이러한 단점들을 극복하기 위하여 XML Schema가 제안되었다. XML DTD와 XML Schema의 차이점을 구체적으로 살펴보면 다음과 같다.

 

n        XML Schema는 XML과 같은 문법을 사용한다.

XML DTD는 XML Schema보다 월등하게 간단하고 사용이 편리하다. 하지만 XML DTD는 XML의 문법을 사용하지 않는다. XML DTD는 문서 구조를 정의하는 부분과 문서를 사용하는 부분에 대한 표현이 틀리다. 하지만 XML Schema는 XML Schema 그 자체가 XML 문서이기도 하다. (XML Schema는 그 자체로 웹 브라우저에서 프리젠테이션 되어질 수 있다) XML Schema를 사용하면 XML 문서의 구조를 정의하는 부분과 실제적으로 문서를 구성하는 부분의 표현이 같아지게 되므로 XML Schema와 그에 맞게 작성된 XML 인스턴스 문서들이 더욱 잘 조합될 수 있다.

 

n        XML Schema는 데이터 형식의 표현이 자유롭다

XML DTD는 문서에서 정의할 수 있는 데이터의 형식이 제한적이다. XML DTD는 숫자와 알파벳 문자밖에 사용할 수 없다. 또한 사용자가 원하는 형태의 데이터타입을 지정하여 사용할 수 없다. XML DTD가 범용적이긴 하지만 데이터베이스와의 연동등을 감안 할 때 값에 대한 유효성등을 파악할 수 없게 된다. XML Schema는 데이터 형식에 대하여 강력하고 유연하며, 또한 재 사용적인 측면에서도 뛰어난 문서의 형식을 구현할 수 있다. XML Schema는 45개의 기본적인 데이터타입을 지원하고 사용자 정의 데이터타입을 선언하여 사용할 수 있다.

 

n        XML Schema는 반복 횟수에 대한 제한을 설정할 수 있다.

XML DTD는 요소들이 반복하여 정의될 수 있는지 없는지의 여부만을 제한할 수 있다. 하지만 XML Schema는 정확하게 몇 번까지 반복하는지, 또는 최소한 몇 번 반복하여야 하는지 등에 대한 상세한 제한을 둘 수 있다.

 

n        XML Schema는 네임스페이스를 사용하여 다양한 타입 정의를 포함할 수 있다.

 

XML Schema는 현재 1.0까지 나와있으며, 1.1이 개발중이다. MSXML은 Microsoft XML Core Service 4.0 SP1 에서 지원하며 http://www.w3.org/XML/Schema를 항상 참조하여 개발안을 참조 하기로 한다.

 

XML DTD는 XML Schema로 쉽게 변경할 수 있다. 에디터를 이용하여 수동으로 변환할 수도 있지만 XML SPY같은 대부분의 XML 도구들이 자동 변환을 지원한다. XML SPY를 이용하여 DTD를 XML Schema로 변환하여 보자.

 

XML SPY를 이용하여 XML DTD를 XML Schema로 변환하려면 변환할 XML DTD가 유효한 XML DTD 이어야 한다. Lab 2에서 작성하였던 Books.dtd를 XML SPY를 이용하여 연다.

 

<그림 3-01.gif> Books.dtd

 

XML SPY는 DTD, DCD, XML-Data, BizTalk Schema, W3C Schema등 여러 종류의 XML Schema로의 변환을 지원한다. XML SPY의 DTD/Schema 메뉴에서 Convert DTD/Schema를 선택한다.

 

<그림 3-02.gif> Convert DTD/Schema 대화상자

 

DTD/Schema file format 그룹박스에서 W3C Schema를 선택하고 OK 버튼을 클릭한다. XML DTD가 XML Schema로 변환되고 새 XSD 문서가 나타난다.

 

<그림 3-03.gif> 변환된 XSD 파일

 

XML SPY같은 XML 도구를 사용하면 작성된 XSD를 사용하여 예제 XML 파일을 생성할 수 있다. 우선 작성된 새 XSL 파일을 저장한 다음, XML SPY 메뉴의 DTD/Schema를 선택하고 Generate Sample XML File을 선택한다. Generate sample XML File 대화상자가 나타난다.

 

<그림 3-04.gif> Generate sample XML file 대화상자

 

Generate sample XML file 대화상자에서 OK를 클릭한다. 클릭하면 XML 문서가 생성된다.

 

<그림 3-05.gif> 생성된 XML 파일

 

나.    XSD 데이터 형식

 

A. XSD 기본 데이터 형식

 

XML Schema는 기본적으로 48가지의 데이터 형식을 사용한다. 다음은 XML Schema가 기본적으로 제공하는 48가지의 데이터 타입이다. (http://www.w3.org/TR/2001/REC-xmlschema-0-20010502/#POSchema 에서 2003년 7월 참조)

 

simpleType

사용 예 (콤마로 구분)

설명

String

Confirm this is Electric

문자열

normalizedString

Confirm this is Electric

문자열

token

Confirm this is Electric

문자열

byte

-1, 126

바이트 타입

unsignedByte

0, 126

부호화 되지 않은 바이트 타입

base64Binary

GpM7

64 비트 바이너리

hexBinary

0FB7

16진수 바이너리

integer

-126789, -1, 0, 1, 126789

16비트 정수형

positiveInteger

1, 126789

16비트 양의 정수형

negativeInteger

-1, -126789

16비트 음의 정수형

nonNegativeInteger

0, 1, 126789

0을 포함하는 16비트 양의 정수형

nonPositiveInteger

0, -1, -126789

0을 포함하는 16비트 음의 정수형

Int

-1, 126789675

32비트 정수형

unsignedInt

0, 1267896754

부호화 되지 않은 32비트 정수형

long

-1, 12678967543233

64비트 정수형

unsignedInt

0, 12678967543233

부호화 되지 않은 64비트 정수형

short

-1, 12678

8비트 정수형

unsignedShort

0, 12678

부호화 되지 않은 8비트 정수형

decimal

-1.23, 0, 123.4, 1000.00

단정도 고정 소수점 형

float

-INF, -1E4, -0, 0, 12.78E-2, 12, INF, NaN

32비트 단정도 부동 소수점 형

double

-INF, -1E4, -0, 0, 12.78E-2, 12, INF, NaN

64비트 배정도 부동 소수점 형

boolean

True, false, 0, 1

Boolean 타입

time

13:20:00.000, 13:20:00.000-05:00

시간

datetime

1999-05-31T13:20:00.000-05:00

날짜와 시간

duration

P1Y2M3DT10H30M12.3S

예는 1년 2개월 3일 10시간 30분 12.3 초의 기간을 나타냄

date

1999-05-31

날짜

gMonth

__05__

gYear

2003

gYearMonth

2003-02

연 월

gDay

___31

gMonthDay

__05_31

월 일

Name

shipTo

XML 1.0의 Name 타입

QName

po:USAddress

XML Namespace QName

NCName

USAddress

XML Namespace NCName

anyURI

http://www.example.com/

유효한 URI

language

en-GB, en-US, fr

XML 1.0 에서 지정한 인코딩 규약

ID

 

XML 1.0 ID 속성 타입

IDREF

 

XML 1.0 IDREF 속성 타입

IDREFS

 

XML 1.0 IDREFS 속성 타입

ENTITY

 

XML 1.0 ENTITY 속성 타입

ENTITES

 

XML 1.0 ENTITIES 속성타입

NOTATION

 

XML 1.0 NOTATION 속성 타입

NMTOKENS

US, Brésil

XML 1.0 NMTOKEN 타입

NMTOKENS

US UK,
Brésil
Canada Mexique

XML 1.0 NMTOKES 타입

 

위 표의 48가지의 데이터 타입을 사용하여 요소의 형식을 정의할 수 있으며 데이터 타입을 사용하여 새로운 사용자 정의의 데이터 타입을 생성할 수 있다. (C#의 Structure와 비슷하다)

 

B. 사용자 정의 데이터 타입

 

XSD 에서는 <simpleType>과 <complexType>을 사용하여 문서 정의에 사용할 데이터의 형식을 정의할 수 있다. <simpleType>과 <complexType>을 사용하는 방법에 대하여 자세히 알아본다.

 

<simpleType> 정의

 

XSD 정의에서 <simpleType>은 위에서 정의한 XML Schema에서 사용할 수 있는 기본 데이터 타입을 사용하여 새로운 데이터 형식을 만들 때 사용한다. C#의 Structure와 비슷하게 사용된다고 생각해도 무방하다. XSD에서 <simpleType>을 정의하는 기본 문법은 다음과 같다.

 

<simpleType name=type_name>

       <restriction base=built-in-data-type>

                    <facet value=value />

                   

       </restriction>

</simpleType>

 

XML 문서에서 요소로 사용되기 위한 Book 타입의 요소를 정의한다고 생각해보자. Book 타입은 문자열로 구성되며, Business, Computer, Novel 중 하나가 선택되어야 할 경우 Book 요소는 다음과 같이 <simpleType>으로 작성될 수 있다.

 

타입의 이름을 Book으로 선언한다.

 

<simpleType name=Book>

 

restriction은 사전적으로 제한, 한정을 의미한다. Book 요소는 문자열로 표시될 것이므로 XML Schema가 제공하는 기본 데이터 타입 중 string으로 표시될 수 있다. restriction은 다음과 같이 표현한다.

 

<restriction base=string>

 

<facet>는 지정한 기본 데이터 타입을 바탕으로 제약 조건을 한정할 수 있게 한다. 지정할 수 있는 제약조건은 데이터 타입 마다 다르다. Book 요소는 Business, Computer, Novel중 하나만 지정될 수 있으므로 열거형 facet를 사용할 수 있다. 다음과 같이 구성된다.

 

<enumeration value=Business />

<enumeration value=Computer />

<enumeration value=Novel />

 

정의된 전체 Book 요소의 XSD는 다음과 같다.

 

<simpleType name=Book>

       <restriction base=string>

                    <enumeration value=Business />

<enumeration value=Computer />

<enumeration value=Novel />

                           </restriction>

             </simpleType>

 

XML 문서에서 사용하기 위한 우편 번호 요소를 생성하는 경우를 살펴보자. 우편번호는 xxx-xxx의 형식이 되어야 한다. 그리고 한국의 우편번호는 반드시 7문자가 되어야 한다. 이런 경우 다음과 같이 <simpleType>을 지정할 수 있다.

 

<simpleType name=PostNumber>

       <restriction base=string>

                    <length value=7 />

                    <pattern value=\d{3}-\d{3} />

       </restriction>

</simpleType>

 

지정되어야 하는 실내 온도가 20도에서 28도 사이라면 integer 타입을 사용하여 <simpleType>을 지정하고 제한을 줄 수 있다.

 

<simpleType name=Tempersture>

       <restriction base=integer>

                    <minInclusive value=20 />

                    <maxInclusive value=28 />

       </restriction>

</simple>

 

위에서 살펴본 바와 같이 기본 데이터 타입을 이용하여 다양한 사용자 정의된 데이터 타입을 생성할 수 있다. 위에서 살펴본 바와 같이 enumeration, length, pattern, minInclusive, maxInclusice등의 facet를 사용하여 사용자가 원하는 형태로 제약조건을 지정할 수 있다. 다음 표는 각 데이터 타입별로 사용할 수 있는 facet를 나타낸 것이다.

 

<! 첨부된 facetList.doc 문서의 표 삽입 -->

<표 3-1> 제공되는 데이터 타입에 따른 facet 리스트

 

3-1에서 알 수 있듯이 모든 데이터 타입이 동일한 facet를 사용할 수 있는 것은 아니다. binary 같은 데이터 타입의 경우, 문자열 처럼 5자로 제한 같은 규약을 줄 수 없음은 당연하다. 또한 유의하여야 할 점은 enumeration 과 pattern 같은 facet는 or 관계를 가지고 다른 facet들은 and 관계를 가진다는 것이다. enumeration과 pattern으로 정의된 여러 항목들은 정의된 여러 항목 중 하나만을 선택하여 사용될 수 있다. 다음과 같이 <simpleType>이 정의되었다고 하자.

 

<simpleType name=Book>

       <restriction base=string>

                    <maxLength=20 />

                    <enumeration value=Business />

<enumeration value=Computer />

<enumeration value=Novel />

                           </restriction>

</simpleType>

 

선언한 사용자 정의 데이터타입 Book은 20자가 넘는 텍스트로 지정될 수 없다. 그리고 요소는 반드시 Business, Computer, Novel 셋 중의 하나의 데이터로 선택되어야 한다. 다시 말하면, maxLength와 enumeration, 두 가지 facet는 반드시 요소내에서 사용되어야 하고, enumeration은 선언된 세 가지중 하나만을 사용하여야 한다는 뜻이 된다.

<complexType> 정의

 

<complexType>은 XSD에서 자식 요소들에 대한 정보와 속성에 관현 정보들을 하나의 이름을 가진 데이터 형식으로 선언할 수 있는 기능을 제공한다. 앞장의 DTD를 잘 이해하였으면 <complexType>을 무리 없이 이해할 수 있을 것이다. C#에서는 Structure를 사용자 정의 데이터타입으로 정의하고 정의된 Structure를 Class에서 데이터 타입으로 지정하여 사용할 수 있다. 또한 Class는 다른 Class를 Class의 멤버로 사용할 수 있다. 좁은 의미로만 한정 지어 생각하면 <complexType>은 C#의 Class, <simpleType>은 C#의 Structure로 생각할 수 있다.

 

facet만 잘 이해하면 되는 <simpleType>과는 달리 <complexType>은 기능이 많은 만큼 정의도 복잡하다. <complexType>은 DTD에서 자식 요소를 포함하는 요소를 선언하는 기능과 비슷하고, (<complexType>은 sequence를 지정할 수 있다), DTD에서 처럼 attribute를 포함할 수 있고, DTD에서 #PCDATA와 요소를 동시에 포함할 수 있었던 것처럼 <complexContent>를 사용하여 타입의 데이터를 표현할 수 있고, <extension>을 사용하여 타입의 확장이 가능하며, <restriction>을 사용하여 타입을 제한할 수 있다.

 

DTD에서 sequence와 attribute를 사용하여 요소를 선언하는 방식과 동일하게 XSD의 <complexType>을 선언하는 기본 문법은 다음과 같다.

 

<complexType name=name>

       <sequence>

                    <element name=element_name type=type_name />

                   

       </sequence>

       <attribute name=attribute_name type=type_name use=uses value=value />

</complexType>

 

XML DTD에서 Book 요소와 그 요소의 선언은 다음과 같이 할 수 있다.

 

<!ELEMENT Book (Title, Publisher, Price, Author*)>

<!ATTLIST Book

       isbn NMTOKEN #REQUIRED

>

 

XML DTD선언을 XSD의 <complexType>으로 선언하면 다음과 같이 할 수 있다. 우선, 새로 선언할 <complexType>의 이름을 Book으로 지정한다.

 

<complexType name=Book>

 

선언된 Book 타입의 자식 요소들을 선언한다. 자식 요소들은 XML DTD에서와 마찬가지로 sequence로 선언된다. XSD에서 이것은 <sequence>로 선언된다. 위 XML DTD에서 Author요소는 Book요소 내에서 자식 요소로 선언되어 존재하여도 되고, 없어도 되며, 개수에 대한 제한은 두지 않게 선언되었다. XSD에서는 facet를 사용하여 아래와 같이 선언된다.

 

<sequence>

       <element name=title type=string />

       <element name=publisher type=string />

       <element name=price type=decimal />

       <element name=author minOccurs=0 maxOccurs=unbounded />

</sequence>

 

XML DTD에서 선언한 속성은 <complexType>내부에서 정의할 수 있다. 선언은 요소의 선언과 거의 비슷한 방식으로 할 수 있다.

 

<attribute name=isbn type=string />

 

Book이라는 이름을 가지는 <complexType>의 전체 선언은 다음과 같다.

 

<complexType name=Book>

<sequence>

                    <element name=title type=string />

                    <element name=publisher type=string />

                    <element name=price type=decimal />

                    <element name=author minOccurs=0 maxOccurs=unbounded />

</sequence>

<attribute name=isbn type=string />

</complexType>

 

이러한 방식으로 <complexType>은 이름으로 요소를 사용할 수 있도록 하는 가장 간단한 형식으로 사용될 수 있다. Book 타입은 title, publisher, price, author 네 개의 자식 요소를 가지고 isbn 속성을 가진다.

 

위와 같이 선언된 <complexType>은 <extension>과 <restriction>을 사용하여 확장 가능하다. 우선 <extension>은 미리 정의된 <complexType>을 사용하여 타입을 확장한다. <complexType>이 선언되면 그 내부에서 <complexContent>를 선언하고 <complexContent>내부체 <extension>을 선언하여 이미 선언된 타입을 확장할 수 있다. <extension>을 사용하여 기본 <complexType>을 확장하여 선언하는 방법은 다음과 같다.

 

<complexType name=complexType_name>

       <complexContent>

                    <extension base=이미_선언된_complexType_name>

                                 <sequence>

                                              <element name=element_name type=type_name />

                                             

                                 <sequence>

                    </extension>

       </complexContent>

</complexType>

 

위에서 <complexType>으로 선언한 Book 타입을 확장하여 <ComputerBook>을 선언하여 보자.

 

우선, 새 <complexType>을 ComputerBook이라는 이름으로 선언한다.

 

<complexType name=ComputerBook>

 

<complexType>내부에 <complexContent>를 선언한다. <complexContent>는 말 그대로 내부에 삽입될 내용의 정의를 의미한다.

 

<complexContent>

 

<complexContent>내부에 확장될 타입을 선언한다. 확장될 타입은 <extension>을 사용하여 선언될 수 있다. 여기서는 위에서 선언한 Book 타입을 확장한다.

 

<extension base=Book>

 

Book타입이 요소들을 더하며 확장될 것이라면, 또 여러 개의 요소를 순서대로 확장할 것이라면 <sequence>를 선언한다. <sequence>내부에 여러 요소들을 추가할 수 있다.

 

<sequence>

       <element name=Type type=string />

       <element name=SubType type=string />

</sequence>

 

열린 요소들을 모두 닫으면 Book타입을 확장한 ComputerBook 타입이 선언된다. 아마 C#이나 Java같은 언어에서의 클래스 상속이 떠오를 것이다. ComputerBook 타입의 전체 선언은 다음과 같다.

 

<complexType name="ComputerBook">

       <complexContent>

                    <extension base="Book">

                                 <sequence>

                                              <element name="Type" type="string" />

                                              <element name="SubType" type="string" />

                                 </sequence>

                    </extension>

       </complexContent>

</complexType>

 

<complexType>에서 <extension>을 사용하는 것이 아니고 <restriction>을 사용하면 기존의 <complexType>을 제한할 수 있다. 재정의할 수 있다고 생각하는 책도 있지만 객체 지향 언어에서의 메소드 오버라이딩 처럼 재정의 할 수 있는 것은 아니다. <restriction>은 이미 선언되었던 <complexType>의 자식 요소들의 반복 횟수와 같은 속성들을 정의하는데 사용된다. <restriction>을 사용하여 선언된 타입을 제한하는 것의 기본 문법은 다음과 같다.

 

<complexType name=type_name>

       <complexContent>

                    <restriction base=이미_선언된_제한할_타입이름>

                                 <element name=element_name type=type_name />

                                

                    </restriction>

       </complexContext>

</complexType>

 

<complexContent>내부의 element는 <restriction>의 base에 지정된 요소의 자식 요소이며 자식 요소의 개수 같은 기본적인 형식은 재 정의될 수 없지만 반복 횟수와 같은 속성은 재 정의될 수 있다. 위에서 선언한 Book 형식을 SimpleBook 이라는 이름의 타입으로 제한하여 보자.

 

우선 <complexType>을 선언한다.

 

<complexType name="SimpleBook">

 

complexContent를 선언한다.

 

<complexContent>

 

<restriction>을 선언하고 base 속성에 제한할 타입의 이름을 지정한다.

 

<restriction base="Book">

 

하위 요소들의 순서들을 지정하기 위해 sequence를 선언하고 하위 요소들을 선언하여 제한한다.

 

<sequence>

       <element name="title" type="xs:string" minOccurs="1" maxOccurs="1" />

</sequence>

 

Book 타입의 제한된 타입인 SimpleBook 타입의 전체 선언은 다음과 같다.

 

<complexType name="SimpleBook">

       <complexContent>

                    <restriction base="Book">

                                 <sequence>

                                              <element name="title" type="xs:string" minOccurs="1" maxOccurs="1" />

                                 </sequence>

                    </restriction>

       </complexContent>

</complexType>

 

XML Schema에서 제공하는 <complexType>은 사용자에게 유연성을 제공하는 타입의 선언을 가능하게 한다. <complexType>을 사용하면 자식 요소나 속성을 가진 타입을 정의할 수 있다. 이렇게 정의된 데이터 타입을 Derived Type 이라고 한다. 또한 complexType은 <extension>과 <restriction>을 사용하여 선언된 타입을 확장하거나 제한할 수 있다.

 

. XSD 구성요소

 

XML DTD가 그렇듯이 XML Schema 가장 기본적인 구성 요소를 이루는 부분은 요소이다. XML DTD는 요소를 선언하는 방식이 하나로 고정되어 있었지만 XML Schema에서는 크게 세 가지로 구분되어 사용된다. XML DTD에서는 <!ELEMENT>로 선언하는 방식과 같이 <element>로 선언하는 방식, <element>, <complexType>으로 선언하는 방식, <element>, <simpleType>으로 선언하는 방식 등이 그것이다. XML Schema는 여러가지의 기능을 사용자에게 제공하고 또한 XML Schema를 최적으로 설계하는 데는 많은 지식이 필요하다.

 

Schema 요소

 

XML Schema는 루트 요소를 필요로 한다. XML Schema는 XML의 문법을 따르므로 문서 전체를 감싸는 루트 요소가 반드시 있어야 하고, 이 루트 요소로 Schema요소를 사용한다. Schema 요소에서는 schema전체에서 사용할 기본 네임 스페이스를 (네임 스페이스에 대한 자세한 설명은 5장에서 다룬다) xs 또는 xsi 접두어를 사용하여 선언해 주고, 사용자 정의 네임 스페이스를 사용할 경우에는 targetNamespace 속성을 사용하여 사용자 정의 네임 스페이스의 URL을 명시하여 선언한다. Schema 요소 선언의 기본 문법은 다음과 같다.

 

<xs:schema xmlns:xs=http://www.w3.org/2001/XMLSchema>

</xs:schema>

 

위와 같이 xmlns 속성을 사용하여 XSD에서 사용될 네임 스페이스를 xs로 선언하였다면 XSD내에서 선언되는 모든 요소, 속성, 타입들은 지정된 네임 스페이스에 대한 접두어를 필요로 한다. 네임 스페이스에 대한 자세한 내용은 5장에서 다루기로 하고, 지금은 문법만을 기억하도록 하자.

 

Schema요소는 속성들을 지정하여 XSD에서 요소등이 어떻게 지정될 것인가를 제한하는데, schema요소에서 사용되는 속성들은 다음과 같은 것들이 있다.

 

속성

설명

attributeFormDefault

Attribute가 네임 스페이스에 정의 되어 있는지의 여부를 qualified, unqualified 로 나타낸다.

finalDefault

요소나 complexType의 final 값을 결정한다. (확장, 재 정의 가능한지 등의 여부)

elementFormDefault

Element가 네임 스페이스에 정의 되어 있는지의 여부를 qualified, unqualified 로 나타낸다.

id

스키마 id를 나타낸다.

targetNamespace

사용자 정의 네임 스페이스를 선언한다.

Xmlns

기본 네임 스페이스를 선언한다.

version

버전 정보를 표시한다.

 

<element> 정의

 

XML Schema에서 요소를 정의하는 기본 문법은 다음과 같다.

 

<element name=element_name type=element_type minOccurs=최소반복횟수 maxOccurs=최대반복횟수 />

 

element의 name 속성은 요소의 이름을 지정한다. 다음과 같이 지정하면 element의 이름은 Books 가 된다.

 

<element name=Books />

 

type 속성은 XML Schema에서 많은 역할을 한다. Type 속성의 값을 지정함으로써 XML Schema에서는 자식 요소에 대한 선언을 할 수 있고 또한 리프 요소인 경우 데이터의 형식을 지정할 수 있다. 다음은 데이터의 형식이 HourCount인 요소의 선언이다.

 

<element name=Hour type=HourCount />

 

XML Schema에서는 데이터의 형식의 제한이 자유롭다. 다음과 같이 SimpleType 요소를 선언하여 사용하면 0에서 59까지의 숫자로 제한된 HourCount 타입의 요소를 생성할 수 있다.

 

<simpleType name="HourCount">

       <restriction base="integer" >

                    <minInclusive value="0" />

                    <maxInclusive value="59" />

       </restriction>

</simpleType>

 

XML Schema에서 요소의 자식 요소를 정의하는 것도 type을 선언한다. Type이 ComplexType으로 작성되었다면 그 타입은 특정 요소의 자식 요소가 된다. XML Schema는 XML DTD보다 월등한 제약 조건을 작성할 수 있다.

 

<element name=Book type=BookType />

 

위의 Book 요소의 타입은 BookType 으로 정의되었다. BookType이 ComplexType으로 정의되었다면 XML DTD에서 요소 타입을 자식 요소로 지정한 것과 같은 동작을 하게 할 수 있다.

 

<complexType name=BookType>

       <sequence>

                    <element name=Title type=string />

                    <element name=Author type=string />

       </sequence>

</complexType>

 

XML Schema는 이런 형식이므로 선언한 타입의 재사용이 아주 용이하다. 자식 요소를 complexType 으로 선언하였을 경우 여러 요소들이 그 타입을 사용하기 간편하고 리프 노드인 경우에는 simpleType으로 선언한 데이터 타입을 사용할 수 있다. 마치 C#에서 Structure나 Class를 사용하는 것처럼 편리하다.

 

<element>, <complexType>과 함께 정의

 

<element> 태그 속에 <complexType> 태그를 직접 포함해서 정의할 수 있다. 이런 형태를 사용하면 요소가 자식 요소들에 대하여 정의할 내용을 직접 <complexType>을 사용하여 정의할 수 있다.

 

XML Schema에서 complexType 요소를 정의하는 기본 문법은 다음과 같다.

 

<element name=element_name minOccurs=최소반복횟수 maxOccurs=최대 반복 횟수>

       <complexType>

      

       </complexType>

</element>

 

<element>와 <complexType>을 같이 사용하여 요소를 선언하는 방식은 type 속성을 지정하지 않는다. <element>만을 사용하는 요소는 type 속성을 사용하여 자식 요소 또는 데이터 형식을 포함하였는데 이 방식은 <element> 선언 내부에 <complexType>요소를 사용하여 자식 요소로 포함될 요소들을 직접 선언한다. Book 요소를 <element>와 <complexType>을 이용하여 선언하면 다음과 같다.

 

<element name=Book minOccurs=1 maxOccurs=unbound>

       <complexType>

                    <element name=title type=string />

                    <element name=publisher type=string />

                    <element name=price type=decimal />

                                        <element name=Author type=string />

                           </complexType>

</element>

 

complexType을 선언하여 자식 요소들을 선언하면 선언한 자식 요소들은 재 사용할 수 없게된다. 자식 요소들은 complexType내부에 선언되었지 독립적으로 선언된 것이 아니기 때문이다. <element>와 <complexType>을 같이 사용하여 요소를 선언하면 명시적으로 자식 요소들에 대한 정보를 포함하므로 XML Schema를 이해하기는 쉬워지지만 재 사용성 적인 측면에서는 효율이 떨어진다는 단점이 있다.

 

<element>와 <simpleType> 함께 정의

 

<element>와 <simpleType>을 함께 사용하여 리프 요소를 선언할 수 있다. 이 방식은 <element>와 <complexType>을 함께 사용하는 방식과 동일하게 <element>요소 내부에 <simpleType>을 정의하여 사용한다.

 

XML Schema에서 simpleType 요소를 정의하는 방식은 다음과 같다.

 

<element name=element_name minOccurs=최소반복횟수 maxOccurs=최대반복횟수>

       <simpleType>

                    <restriction base=element_type>

                   

                    </restriction>

       </simpleType>

</element>

 

name 속성은 요소의 이름을 지정한다. minOccurs 속성은 선언한 요소가 XML 문서내에서 최소한 몇 번 반복하여야 하는지의 여부를 정수 값으로 나타내고 maxOccurs 속성은 최대한 몇 번까지 반복할 수 있는지의 값을 나타낸다.

 

<element>와 <simpleType>을 사용하여 Title 요소를 선언하면 다음과 같이 된다.

 

<element name=Title minOccurs=1 maxOccurs=1>

       <simpleType>

                    <restriction base=string />

       </simpleType>

</element>

 

simpleType으로 선언된 요소 역시 독립적으로 선언된 요소가 아니므로 다른 외부 요소에서 참조할 수 없다. 가독성은 뛰어나지만 재 사용성적인 측면에서는 활용도가 떨어진다.

 

속성 선언

 

앞서 속성의 선언예를 몇 번 보인적이 있다. XSD에서 속성의 선언은 DTD에서 ATTLIST의 선언과 동일하다. XSD에서의 attribute는 XML DTD에서와 같이 요소에 종속되게 된다. 선언 방법도 비슷하고 사용 방법도 비슷하지만 XML DTD에서 확장된 XSD답게 다양한 타입을 지정할 수 있다. XML Schema에서 속성을 지정하는 기본 문법은 다음과 같다.

 

<attribute name=attribute_name type=type_name use=(Optional | Prohibited | Required) value=value />

 

attribute_name은 당연히 속성의 이름을 가리킨다. Type은 XML Schema에서 지원하는 기본 데이터 타입을 사용할 수 있다. (XML Schema는 빠른 속도로 변화하고 있으므로 W3C 웹 페이지를 항상 참조 하여야 한다.)  use 속성은 요소의 필수적인 속성인지 또는 아닌지를 표시하고 value 속성은 기본값을 나타낸다.

 

Book 요소의 isbn 속성은 다음과 같이 정의할 수 있다.

 

<attribute name=isbn type=string use=required />

 

isbn 속성이 특정한 형식에 맞추어 지정되어야 한다면 <simpleType>을 사용하여 정의할 수 있다. 속성을 지정할 때 <simpleType>을 사용하여 특정 형식을 사용하고 싶다면 다음과 같이 할 수 있다.

 

<attribute name="isbn" use="required">

       <simpleType>

                    <restriction base="string">

                                 <pattern value="\d{2}-\d{3}-\d{4}-\d{1}" />

                    </restriction>

       </simpleType>

</attribute>

 

XSD에서 요소의 속성을 선언할 때는 반드시 모든 자식 요소를 다 선언한 후 가장 마지막에 선언하여야 한다. 선언된 속성은 자식 요소들에는 적용되지 않는다.

 


<Lab 3-1> 유효한 XML / XSD 문서 작성

 

이 연습에서는 다음과 같은 작업들을 실행한다.

1. Lab 2 에서 작성한 XML DTD의 XML SPY를 이용한 자동변환

2. 정의된 요구 사항에 맞는 XSD 작성

3. 작성된 XSD를 기반으로 하는 XML 문서 작성

 

Lab 2 에서 작성한 XML DTD의 XML SPY를 이용한 XSD로의 자동변환

1.       Lab 2 에서 작성한 Books.dtd 파일을 XML SPY를 이용하여 연다.

2.       XML SPY 메뉴의 DTD/Schema에서 Convert DTD/Schema를 선택한다.

3.       나타난 Convert DTD/Schema 대화상자에서 W3C Schema를 선택하고 OK 버튼을 클릭한다.

4.       Untitled1.xsd 파일이 생성된다.

 

<Lab3-1-01.gif> DTD에서 변환된 XSD

 

5.       Text View 버튼을 눌러 텍스트 모드로 전환한다.

6.       Books 요소의 선언을 찾아 내용을 확인한다.

 

<xs:element name="Books">

       <xs:complexType mixed="true">

                    <xs:choice minOccurs="0" maxOccurs="unbounded">

                                 <xs:element ref="Book"/>

                    </xs:choice>

       </xs:complexType>

</xs:element>

 

7.       Books.dtd 창을 선택하여 연다.

8.       Text View 버튼을 눌러 텍스트 모드로 전환환다.

9.       Books 요소의 선언을 찾아 내용을 확인한다.

 

<!ELEMENT Books (#PCDATA | Book)*>

 

10.   XML DTD에서의 Books 요소 선언이 XSD에서 어떻게 선언되었는지 확인하고 검토한다.

11.   Untitled1.xsd 파일을 저장하지 않고 닫는다.

12.   Books.dtd 파일에서 Enhanced Grid View 버튼을 클릭하여 Grid View 모드로 전환한다.

13.   Grid View 모드에서 Books 요소를 선택하고 Element 창의 sequence of 를 더블릭하여 요소 타입을 변경한다.

14.   Books.dtd 파일을 저장한다.

15.   XML SPY 메뉴의 DTD/Schema에서 Convert DTD/Schema를 선택한다.

16.   나타난 Convert DTD/Schema 대화상자에서 W3C Schema를 선택하고 OK 버튼을 클릭한다.

17.   Untitled2.xsd 파일이 생성된다.

 

<Lab3-1-02.gif> DTD에서 변환된 XSD

 

18.   Text View 버튼을 눌러 텍스트 모드로 전환환다.

19.   Books 요소의 선언을 찾아 내용을 확인한다.

 

<xs:element name="Books">

       <xs:complexType>

                    <xs:sequence>

                                 <xs:element ref="Book"/>

                    </xs:sequence>

       </xs:complexType>

</xs:element>

 

20.   XML DTD에서의 Books 요소 선언이 XSD에서 어떻게 선언되었는지 확인하고 검토한다.

21.   변환된 XSD 파일을 ConvertedBooks.xsd 라는 이름으로 저장한다.

 

<그림 Lab3-1-03.gif> 파일의 저장

 

22.   열린 파일을 모두 닫는다.

23.   XML SPY를 종료한다.

 

정의된 요구사항에 맞는 XSD 작성

이 연습에서는 Lab 2 에서 작성했던 요구에 맞는 XSD를 작성한다. 요구사항은 다음과 같다.

n       여러 권의 책에 대한 정보를 포함할 수 있어야 한다.

n       책의 ISBN(International Standard Book Number)를 유효한 세가지 형식에 맞게 속성으로 반드시 포함할 수 있어야 한다.

n       책의 제목에 대한 정보를 반드시 포함하여야 하며 책의 부제는 포함될 수도, 안될 수도 있어야 한다.

n       출판사에 대한 정보는 반드시 포함되어야 한다.

n       책의 가격에 대한 정보는 반드시 포함되어야 한다.

n       저자에 대한 정보는 포함 될 수도 안 될 수도 있다. 저자는 두 명 이상 포함될 수 있어야 한다.

 

1.       XML SPY를 실행한다.

2.       XML SPY 메뉴의 File -> new를 선택하여 나타난 Create new document 대화상자에서 xsd W3C XML Schema를 선택하고 OK를 클릭한다.

3.       Untitled1.xsd 파일이 생성된다.

 

<그림 Lab3-1-04.gif> 생성된 XSD 파일

 

4.       Text View 버튼을 클릭하여 Text View 모드로 전환하고 XSD의 내용을 확인한다.

 

<?xml version="1.0" encoding="UTF-8"?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">

       <xs:element name="ENTER_NAME_OF_ROOT_ELEMENT_HERE">

                    <xs:annotation>

                                 <xs:documentation>Comment describing your root element</xs:documentation>

                    </xs:annotation>

       </xs:element>

</xs:schema>

 

5.       schema 요소를 제외한 모든 요소들을 삭제한다. 삭제한 후의 XSD 문서는 다음과 같이 될 것이다.

 

<?xml version="1.0" encoding="UTF-8"?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"

elementFormDefault="qualified" attributeFormDefault="unqualified">

 

</xs:schema>

 

6.       Author 요소를 작성한다. Author 요소는 문자열로 표시될 것 이므로 XML Schema가 제공하는 string 타입으로 지정한다.

7.       Price 요소를 작성한다. Price 요소는 책의 가격을 표시할 것이므로 XML Schema가 제공하는 decimal 타입으로 지정한다.

8.       Publisher 요소를 작성한다. Publisher 요소는 출판사를 문자열 형식으로 표시할 것이므로 XML Schema가 제공하는 string 타입으로 지정한다.

9.       Title 요소를 작성한다. Title 요소는 책의 제목을 문자열 형식으로 표시할 것이므로 XML Schema가 제공하는 string 타입으로 지정한다.

10.   SubTitle 요소를 작성한다. SubTitle 요소는 책의 부제를 문자열 형식으로 표시할 것이므로 XML Schema가 제공하는 string 타입으로 지정한다.

11.   현재 까지 작성한 XSD는 다음과 같을 것이다.

 

<?xml version="1.0" encoding="UTF-8"?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"

elementFormDefault="qualified" attributeFormDefault="unqualified">

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

                    <xs:element name="Price" type="xs:decimal" />

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

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

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

</xs:schema>

 

12.   Book 요소를 작성한다. Book 요소는 책의 제목에 대한 정보, 출판사에 대한 정보, 가격에 대한 정보를 반드시 포함하여야 한다. 다음과 같이 작성할 수 있을 것이다.

 

<xs:element name="Book">

                    <xs:complexType>

                                  <xs:sequence>

                                              <xs:element ref="Title" />

                                               <xs:element ref="Publisher" />

                                              <xs:element ref="Price" />

                                 </xs:sequence>

                    </xs:complexType>

</xs:element>

 

13.   Book 요소는 부제에 대한 정보를 포함할 수도 있고 아닐 수도 있다. 또한 만약에 포함한다면 반드시 하나만을 포함하여야 한다. SubTitle 요소는 다음과 같이 포함될 수 있다.

 

<xs:element ref="SubTitle" minOccurs=0 maxOccurs="1" />

 

14.   Book 요소는 저자에 대한 정보를 포함할 수도 있고 아닐 수도 있다. 만약에 포함한다면 포함되는 저자의 명수는 관계하지 않는다.

 

<xs:element ref="Author" minOccurs="0" maxOccurs="unbounded" />

 

15.   Book 요소의 isbn 속성을 선언한다. isbn 속성은 반드시 포함하여야 하며 지정한 세가지 패턴에 맞게 지정되어야 한다. isbn 속성은 다음과 같이 선언될 수 있다.

 

<xs:attribute name="isbn" use="required">

                    <xs:simpleType name="">

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

                                              <xs:pattern value="\d{2}-\d{3}-d{4}-d{1}" />

                                              <xs:pattern value="\d{1}-\d{5}-\d{3}-d{1}" />

                                              <xs:pattern value="\d{10}" />

                                 </xs:restriction>

                    </xs:simpleType>"

       </xs:attribute>

 

16.   선언된 Book 요소는 다음과 같을 것이다.

 

<xs:element name="Book">

                    <xs:complexType>

                                 <xs:sequence>

                                              <xs:element ref="Title" />

                                              <xs:element ref="SubTitle" minOccurs=0 maxOccurs="1" />

                                              <xs:element ref="Publisher" />

                                              <xs:element ref="Price" />

                                              <xs:element ref="Author" minOccurs="0" maxOccurs="unbounded" />

                                 </xs:sequence>

                                 <xs:attribute name="isbn" use="required">

                                              <xs:simpleType name="">

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

                                                                         <xs:pattern value="\d{2}-\d{3}-d{4}-d{1}" />

                                                                         <xs:pattern value="\d{1}-\d{5}-\d{3}-d{1}" />

                                                                         <xs:pattern value="\d{10}" />

                                                            </xs:restriction>

                                              </xs:simpleType>"

                                 </xs:attribute>

                    </xs:complexType>

       </xs:element>

 

17.   XML SPY 메뉴바의 Check Well-formedns 버튼을 클릭하여 XSD 문서의 Well-Formd 여부를 조사한다.

18.   에러가 발생하면 수정한다.

19.   XML SPY 메뉴바의 Validate File 버튼을 클릭하여 XSD 문서의 Valid 여부를 조사한다.

20.   에러가 발생하면 수정한다.

 

21.   Books 요소를 선언한다. Books 요소는 다수의 Book 요소를 포함할 수 있다. Book 요소는 <element>와 <complexType>으로 선언될 수 있다.

 

<xs:element name="Books">

       <xs:complexType>

                    <xs:sequence>

                                 <xs:element ref="Book" minOccurs="1" />

                    </xs:sequence>

       </xs:complexType>

</xs:element>

 

22.   XML SPY 메뉴바의 Check Well-formedns 버튼을 클릭하여 XSD 문서의 Well-Formd 여부를 조사한다.

23.   에러가 발생하면 수정한다.

24.   XML SPY 메뉴바의 Validate File 버튼을 클릭하여 XSD 문서의 Valid 여부를 조사한다.

25.   에러가 발생하면 수정한다.

26.   작성한 XSD 파일을 Books.xsd 로 저장한다.

27.   XML SPY를 종료한다.

 

작성된 XSD를 기반으로 하는 XML 문서 작성

이 연습에서는 다음과 같은 작업들을 행한다.

n        XML SPY를 이용한 자동 문서 생성

n        새로 생성하는 XML 파일에 XSD 적용

 

XML SPY를 이용한 XML 파일 자동 생성

1.       XML SPY를 실행한다.

2.       File -> Open 메뉴에서 이전에 작성한 Books.xsd 파일을 연다.

3.       XML SPY 메뉴바의 DTD/Schema 메뉴에서 Generate sample XML file을 선택한다.

4.       나타나는 Generate sample XML file 대화상자에서 OK 버튼을 클릭한다.

5.       Untitled1.xml 파일이 생성된다.

 

<그림 Lab3-1-05.gif> 자동 생성된 xml 파일

 

6.       XML SPY 메뉴바의 Check Well-formednes 버튼을 클릭하여 XML 파일의 Well-formd 여부를 체크한다.

7.       XML SPY Validate file 버튼을 클릭하여 XML 파일의 Valid 여부를 체크한다. 오류가 발생한다.

 

<그림 Lab3-1-06.gif> Invalid XML Document

 

8.       Book 요소의 isbn 속성에 맞는 값을 지정한다. XSD에서 속성을 지정한 패턴에 맞는 값이어야 한다.

 

<Book isbn="11-111-1111-1">

 

9.       XML SPY Validate file 버튼을 클릭하여 XML 파일의 Valid 여부를 체크한다. 오류가 발생한다.

10.   Price 요소는 반드시 decimal 값으로 지정되어야 한다. Price 요소의 값을 decimal 로 명시한다.

 

<Price>30000</Price>

 

11.   XML SPY Validate file 버튼을 클릭하여 XML 파일의 Valid 여부를 체크한다. 오류가 발생하면 수정한다.

12.   XML SPY 메뉴바의 Browser View 버튼을 클릭하여 웹 브라우저에서 보이는 모습을 확인한다.

 

<그림 Lab3-1-07.gif> 웹 브라우저에서 확인한 XML 파일

 

13.   Untitled2.xml 파일을 저장하지 않고 닫는다.

14.   XML SPY를 닫는다.

 

새로 생성하는 XML 파일에 XSD 적용

1.       XML SPY를 실행한다.

2.       XML SPY 메뉴바에서 File -> New File을 선택한다.

3.       나타난 Create new document 대화상자에서 xml XML Document 를 선택하고 OK 버튼을 클릭한다.

4.       나타난 New file 대화상자에서 Schema를 선택하고 OK 버튼을 클릭한다.

 

<그림 Lab3-1-09.gif> DTD, Schema 선택 대화상자

 

5.       나타난 XML SPY 대화상자에서 앞서 작성한 Books.xsd를 선택하고 OK 버튼을 클릭한다.

 

<그림 Lab3-1-10.gif> XSD 파일 선택 대화상자

 

6.       Untitled1.xml 파일이 생성된다.

 

<그림 Lab3-1-11.gif> 생성된 XML 파일

 

7.       툴바의 Text View 버튼을 클릭하여 Text View 모드로 전환한다.

8.       Book 요소의 isbn 속성에 알맞은 값을 입력하고 Price 요소에 decimal 값을 입력한다.

9.       Validate file 버튼을 클릭하여 XML 파일의 Valid 여부를 체크한다. 오류가 발생하면 수정한다.

 

10.   각 요소에 적당한 값을 입력한다.

 

<?xml version="1.0" encoding="UTF-8"?>

<Books xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="C:\Code\Books.xsd">

       <Book isbn="1111111111">

                    <Title>마이크로소프트의 도전</Title>

                    <SubTitle>X박스와 게임의 미래</SubTitle>

                    <Publisher>푸른 미디어</Publisher>

                    <Price>38000</Price>

       </Book>

</Books>

 

11.   Validate file 버튼을 클릭하여 XML 파일의 Valid 여부를 체크한다. 오류가 발생하면 수정한다.

 

12.   적당한 데이터를 입력하여 Book 요소를 하나 더 추가한다.

 

<Book isbn="11-111-1111-1">

              <Title>살아있는 신화</Title>

              <SubTitle>Microsoft CEO 스티브 발머</SubTitle>

              <Publisher>한국 경제 신문사</Publisher>

              <Price>12000</Price>

</Book>

 

13.   Validate file 버튼을 클릭하여 XML 파일의 Valid 여부를 체크한다. 오류가 발생한다.

14.   Book.xsd 파일을 열고 Books 요소가 여러 개의 Book 요소를 가질 수 있게 다음과 같이 수정한다.

 

<xs:element name="Books">

                    <xs:complexType>

                                 <xs:sequence>

                                              <xs:element ref="Book" maxOccurs="unbounded" />

                                 </xs:sequence>

                    </xs:complexType>

       </xs:element>

 

15.   Untitled1.xml 파일에서 Validate file 버튼을 클릭하여 XML 파일의 Valid 여부를 체크한다. 에러가 발생하지 않는다.

 

16.   Untitled1.xml 파일에서 추가한 두 번째의 요소에서 Title 요소를 제거하고 Validate file 버튼을 클릭하여 XML 파일의 Valid 여부를 체크한다. 에러가 발생한다.

17.   Ctrl + Z 버튼을 클릭하여 작업을 취소한다.

18.   추가한 두 번째의 Book 요소에서 SubTitle 요소를 제거하고 Validate file 버튼을 클릭하여 XML 파일의 Valid 여부를 체크한다. 오류가 발생하지 않는다.

19.   추가한 두 번째의 Book 요소에서 Author 정보를 포함한다.

 

<Author>프레드릭 맥스웰</Author>

 

20.   Validate file 버튼을 클릭하여 XML 파일의 Valid 여부를 체크한다. 오류가 발생하지 않는다

21.   추가한 두 번째의 Book 요소에서 또 하나의 Author 요소를 포함한다.

 

<Author>안진환</Author>

 

22.   Validate file 버튼을 클릭하여 XML 파일의 Valid 여부를 체크한다. 오류가 발생하지 않는다

 

23.   파일을 Books.xml 이라는 이름으로 저장한다.

24.   열린 파일을 닫는다.

25.   XML SPY를 종료한다

http://blog.naver.com/war333?Redirect=Log&logNo=20013335955


articles
recent replies
recent trackbacks
notice
Admin : New post