[XML.NET] 18. XmlReader 개체로 데이터 분석(요소 읽기)

 XmlReader 클래스에서는 요소 읽기 작업에 관한 6가지 메서드와 1가지 속성을 제공하고 있습니다.  먼저 이들의 역할과 원형을 간략히 살펴봅시다.

 현재 노드가 시작 요소인지 확인할 때는 IsStartElement 메서드를 사용합니다.

public bool IsStartElement ();
public bool IsStartElement (string name);
public bool IsStartElement (string local_name, string ns);

 현재 노드가 시작 요소일 때 요소를 읽기 위해 ReadStartElement 메서드를 제공합니다.

public void ReadStartElement ();
public void ReadStartElement (string name);
public void ReadStartElement (string local_name, string ns);

  현재 노드가 종료 요소일 때 읽기 위해 ReadEndElement 메서드를 제공합니다.

public void ReadEndElement ();

  현재 노드가 시작 요소이고 값이 문자열일 때 값을 읽기 위해 ReadElementString 메서드를 제공합니다.

public string ReadElementString ( );
public string ReadElementString (string name );
public string ReadElementString (string local_name, string ns );

 원하는 하위 요소로 이동할 때는 ReadToDescentdant 메서드를 사용합니다.

public bool ReadToDescendant (string name);
public bool ReadToDescendant (string local_name, string ns_uri);

 원하는 형제 요소로 이동할 때는 ReadToNextSibling 메서드를 사용합니다.

public bool ReadToNextSibling(string name);
public bool ReadToNextSibling(string name, string ns_uri);

  마지막으로 비어있는 요소인지 확인할 때 IsEmptyElement 속성을 사용합니다.

public bool IsEmptyElement
{
    get;
}

  다음은 XmlReader 개체를 이용하여 요소를 읽는 예제입니다. 예제 코드에서는 도서 목록이 작성되어 있는 원본 XML 파일에서 도서 정보를 읽어와서 도서 개체를 만들고 있습니다.

 먼저 XmlReader 개체의 Read 메서드를 반복 호출하여 “book” 요소가 시작하는 태그인지 확인하여 맞다면 Book 클래스의 정적 메서드인 MakeBook메서드를 통해 Book 개체를 생성합니다. 이 때 “book” 요소가 시작하는 태그인지 확인하기 위해 IsStartElement 메서드를 호출하고 있습니다.

 MakeBook 메서드에서는 하위 요소 중에 “title” 위치로 이동할 때 ReadToDescendant 메서드를 호출하고 있으며 “title” 요소는 값으로 문자열을 갖고 있어서 ReadElementString 메서드 호출을 통해 도서 제목을 얻어옵니다.

 그리고 “title”의 형제 요소인 “price” 요소로 이동하기 위해 ReadToNextSibling 메서드를 호출하고 있으며 시작 요소를 읽기 위해 ReadStartElement메서드를 호출합니다. 그리고 값을 얻어오기 위해 XmlReader 개체의 속성 Value를 사용합니다.

using System;
using System.Xml;
using System.Collections;

namespace 예제_XmlReader_개체로_요소_읽기
{
    class Book
    {
        internal string Title
        {
            get;
            private set;
        }
        internal int Price
        {
            get;
            private set;
        }
        internal static Book MakeBook(XmlReader xr)
        {            
            string title = string.Empty;
            int price = 0;
            xr.ReadToDescendant("title");
            title = xr.ReadElementString("title");

            xr.ReadToNextSibling("price");
            xr.ReadStartElement("price");
            price = int.Parse(xr.Value);
            
            return new Book(title, price);            
        }
        Book(string title, int price)
        {
            Title = title;
            Price = price;
        }
        public override string ToString()
        {
            return Title;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            ArrayList ar = new ArrayList();

            XmlReader reader = XmlReader.Create("data.xml");
            while (reader.Read())
            {
                if (reader.IsStartElement("book"))
                {
                    Book book = Book.MakeBook(reader);
                    if (book != null)
                    {
                        ar.Add(book);
                    }
                }                
            }

            Console.WriteLine("도서 개수:{0}", ar.Count);
            foreach (Book book in ar)
            {
                Console.WriteLine("도서명:{0} 가격:{1}", book.Title, book.Price);
            }
        }
    }
}