[카테고리:] <span>XML.NET</span>

XML 스키마는 표준 XML 문서 구조의 정의입니다. 이를 이용하면 유효성 검사를 할 수 있고 판독하는 등의 강력한 기능을 사용할 수 있습니다.

 .NET Framework 에서는 스키마를 만들거나 유효성을 검사할 수 있는 스키마 개체 모델(SOM) API를 제공하고 있습니다.

 XML 스키마 파일을 작성할 때는 XmlSchema 클래스를 비롯하여 다양한 클래스를 사용합니다.

  프로그램 메모리에 XML 스키마를 만들 때는 XmlSchema 개체를 생성합니다. 그리고 XML 스키마 개체에 스키마 요소를 표현하기 위해 XmlSchemaElement개체를 만들어 원하는 내용으로 설정하고 XmlSchema 개체의 멤버 Items 컬렉션 속성에 추가합니다.

XmlSchema schema = new XmlSchema();
// <xs:element name="book" type="string"/>
XmlSchemaElement elem_book = new XmlSchemaElement();
schema.Items.Add(elem_book);
elem_book.Name = "book";
elem_book.SchemaTypeName = new XmlQualifiedName(
                                      "string",
                                      "http://www.w3.org/2001/XMLSchema");

 그리고 이렇게 만든 XmlScema 개체들을 XmlSchemaSet에 추가하여 컴파일 과정을 거쳐 유효성 테스트를 할 수 있습니다.

XmlSchemaSet schemaSet = new XmlSchemaSet();
schemaSet.ValidationEventHandler += new ValidationEventHandler(ValidationCallbackOne);
schemaSet.Add(schema);
schemaSet.Compile();

 다음은 유효성 검사에서 위배했을 때 처리하는 이벤트 핸들러의 예입니다.

public static void ValidationCallbackOne(object sender, ValidationEventArgs args)
{
    Console.WriteLine(args.Message);
}

 그리고 XmlSchema 개체는 Write 메서드를 제공하고 있어 XML 스키마 파일을 만들 수 있습니다.

FileStream fs = new FileStream("data.xsd",FileMode.Create);
compiledSchema.Write(fs);
fs.Close();

 다음의 예제 코드는 책과 앨범을 포함하는 컨텐츠를 스키마로 표현한 예제 코드입니다.

 예제 코드에서는 XmlShema 개체를 생성한 후에 책 요소와 앨범 요소에 관한 XmlSchemaElement 개체를 생성하여 XmlSchema 개체의 Items 컬렉션에 추가하는 것으로 출발합니다. 그리고 책 요소와 앨범 요소를 하위 요소로 포함할 수 있는 컨텐츠 집한 요소에 관한 XmlSchemaElement 개체를 생성하여XmlSchema 개체의 Items 컬렉션에 추가합니다.

 컨텐츠 집합 요소에 관한 XmlSchemaElement 개체는 복합 타입임을 지정하고 자식 요소로 책 요소와 앨범 요소를 포함할 수 있음을 지정합니다. 이 후에XmlSchemaSet 개체를 생성하여 XmlShema 개체를 추가한 후에 컴파일을 통해 유효성 검사를 수행합니다. 마지막으로 유효성 검사에 통과한 XmlSchema개체를 파일로 저장하고 있습니다.

using System;
using System.Xml.Schema;
using System.Xml;
using System.IO;

namespace 예제_XML_스키마_작성
{
    class Program
    {
        static void Main(string[] args)
        {
            XmlSchema schema = new XmlSchema();

            // <xs:element name="book" type="string"/>
            XmlSchemaElement elem_book = new XmlSchemaElement();
            schema.Items.Add(elem_book);
            elem_book.Name = "book";
            elem_book.SchemaTypeName = new XmlQualifiedName(
                                              "string",
                                              "http://www.w3.org/2001/XMLSchema");

            // <xs:element name="albumn" type="string"/>
            XmlSchemaElement elem_albumn = new XmlSchemaElement();
            schema.Items.Add(elem_albumn);
            elem_albumn.Name = "albumn";
            elem_albumn.SchemaTypeName = new XmlQualifiedName(
                                                "string",
                                                "http://www.w3.org/2001/XMLSchema");                     

            // <xs:element name="contents">
            XmlSchemaElement elem_contents = new XmlSchemaElement();
            schema.Items.Add(elem_contents);
            elem_contents.Name = "contents";

            // <xs:complexType>
            XmlSchemaComplexType complexType = new XmlSchemaComplexType();
            elem_contents.SchemaType = complexType;

            // <xs:choice minOccurs="0" maxOccurs="unbounded">
            XmlSchemaChoice choice = new XmlSchemaChoice();
            complexType.Particle = choice;
            choice.MinOccurs = 0;
            choice.MaxOccursString = "unbounded";

            // <xs:element ref="book"/>
            XmlSchemaElement ref_book = new XmlSchemaElement();
            choice.Items.Add(ref_book);
            ref_book.RefName = new XmlQualifiedName("book");

            // <xs:element ref="albumn"/>
            XmlSchemaElement ref_albumn = new XmlSchemaElement();
            choice.Items.Add(ref_albumn);
            ref_albumn.RefName = new XmlQualifiedName("albumn");

            XmlSchemaSet schemaSet = new XmlSchemaSet();
            schemaSet.ValidationEventHandler += ValidationCallbackOne;
            schemaSet.Add(schema);
            schemaSet.Compile();

            XmlSchema compiledSchema = null;

            foreach (XmlSchema schema1 in schemaSet.Schemas())
            {
                compiledSchema = schema1;
            }

            XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable());
            nsmgr.AddNamespace("xs", "http://www.w3.org/2001/XMLSchema");            
            FileStream fs = new FileStream("data.xsd",FileMode.Create);
            compiledSchema.Write(fs);
            fs.Close();
            
        }
        public static void ValidationCallbackOne(object sender, ValidationEventArgs args)
        {
            Console.WriteLine(args.Message);
        }
    }        
}

 다음은 예제 코드로 만들어진 “data.xsd” 파일의 내용입니다.

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="book" type="xs:string" />
  <xs:element name="albumn" type="xs:string" />
  <xs:element name="contents">
    <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="book" />
        <xs:element ref="albumn" />
      </xs:choice>
    </xs:complexType>
  </xs:element>
</xs:schema>

 이렇게 작성한 XML 스키마 파일은 XML 데이터 파일을 로딩할 때 유효성 검사에 사용할 수 있습니다. 이미 3장에서 XML 스키마 파일을 이용하여 유효성 검사를 하는 예제를 보여준 적이 있는데 다시 한 번 확인해 봅시다. 여기에서는 스키마 파일인 “data.xsd”에 정의한 스키마에 맞게 작성한 “data.xml” 파일과 스키마에 위배한 요소가 있는 “data2.xml” 파일의 내용을 XmlReader 개체로 읽어오는 예제를 보여드릴게요.

 다음은 “data.xml” 문서의 내용입니다.

<?xml version="1.0" encoding="utf-8"?>
<contents xmlns="xs">
  <book>XML.NET</book>
  <albumn>My Way</albumn>
  <book>ADO.NET</book>
</contents>

다음은 “data2.xml” 문서의 내용입니다.

<?xml version="1.0" encoding="utf-8"?>
<contents xmlns="xs">
  <book>XML.NET</book>
  <albumn>My Way</albumn>
  <books>ADO.NET</books>
</contents>

다음은 소스 코드입니다.

using System;
using System.Xml.Schema;
using System.Xml;

namespace 예제_스키마_파일에_의거하여_데이터_읽기
{
    class Program
    {
        static void Main(string[] args)
        {
            XmlSchemaSet sc = new XmlSchemaSet();
            sc.Add("xs", "data.xsd");

            XmlReaderSettings settings = new XmlReaderSettings();
            settings.ValidationType = ValidationType.Schema;
            settings.Schemas = sc;
            settings.ValidationEventHandler += ValidationCallBack;

            TestLoading("data.xml",settings);
            TestLoading("data2.xml",settings);           
        }

        private static void TestLoading(string path, XmlReaderSettings settings)
        {
            XmlReader reader = XmlReader.Create(path, settings);
            XmlWriter xwriter = XmlWriter.Create(Console.Out);
            xwriter.WriteNode(reader, false);
            xwriter.Close();
            Console.WriteLine();
            reader.Close();
        }

  

        //유효성 위배가 있을 시 콜솔에 출력
        private static void ValidationCallBack(object sender, ValidationEventArgs e)
        {
            Console.WriteLine("Validation Error: {0}", e.Message);
        }

    }
}
실행 화면

XML.NET