XML을 순차적으로 읽고 쓰기
XML을 읽고 쓰는 전통적인 방식으로 XmlReader, XmlWriter 클래스(System.Xml)를 사용하는 방식이 있는데, 이 클래스들은 XML을 순차적으로 한 노드씩 읽고 쓰게 된다. XML DOM 방식을 사용하는 XmlDocument 클래스와 비교해 보면, XmlDocument가 파일을 오픈하면서 모든 XML 내용을 메모리로 로딩하는 반면, XmlReader은 Forward-only 방식으로 캐쉬없이 순차적으로 처리한다는 차이가 있다. XmlReader, XmlWriter는 XML DOM 방식보다 사용이 불편하긴 하지만 사이즈가 큰 XML 파일을 핸들링할 때 유용하다. 예를 들어, 2 GB의 XML 파일을 핸들링 한다면, XmlReader/XmlWriter가 더 적합할 것이다.
XmlWriter : XML 파일 쓰기
XmlWriter 클래스는 XML 파일을 순차적으로 쓸 때 사용하는 클래스이다. XmlWriter 클래스는 Abstract클래스로서 이를 구현한 클래스로 XmlTextWriter 클래스가 있지만, XmlTextWriter를 사용하는 대신 XmlWriter.Create() 메서드를 사용할 것을 권장한다 (새로운 기능을 더 지원함).
XML 파일을 생성하기 위해서는 XmlWriter.Create(파일명) 과 같이 Create() 정적메서드에 XML 파일명을 지정하면 된다. XML을 실제 쓰기 위해서 여러 종류의 Write* 메서드들이 있는데, 가장 먼저 새로운 XML 문서를 시작하기 위해 WriteStartDocument() 를 사용하고, 이 메서드와 Pair를 이루는 WriteEndDocument() 메서드를 마지막에 써주게 된다. 문서가 시작된 후 WriteStartElement() 메소드를 써서 새로운 XML Element를 시작하면서 새 XML 노드를 만들게 되고, 물론 이와 Pair를 이루는 WriteEndElement() 를 매칭해서 나중에 써주게 된다. WriteStartElement()와 WriteEndElement() 사이에는 여러 자식 노드(자식 Element)들을 만들 수 있다. 자식노드는 또한 또다른 자식노드들을 Nested 방식으로 계속 가질 수 있다. 만약 하나의 Element가 자식이 없는 경우, 간단히 WriteElementString() 메서드를 사용할 수 있다. 또한 Element가 Attribute 를 갖으면 이는 WriteStartElement()와 WriteEndElement() 사이에 WriteAttributeString() 메서드를 사용하여 지정할 수 있다.
아래 예제는 간단한 Employee 데이타를 XML로 작성한 예이다.
XML 파일을 생성하기 위해서는 XmlWriter.Create(파일명) 과 같이 Create() 정적메서드에 XML 파일명을 지정하면 된다. XML을 실제 쓰기 위해서 여러 종류의 Write* 메서드들이 있는데, 가장 먼저 새로운 XML 문서를 시작하기 위해 WriteStartDocument() 를 사용하고, 이 메서드와 Pair를 이루는 WriteEndDocument() 메서드를 마지막에 써주게 된다. 문서가 시작된 후 WriteStartElement() 메소드를 써서 새로운 XML Element를 시작하면서 새 XML 노드를 만들게 되고, 물론 이와 Pair를 이루는 WriteEndElement() 를 매칭해서 나중에 써주게 된다. WriteStartElement()와 WriteEndElement() 사이에는 여러 자식 노드(자식 Element)들을 만들 수 있다. 자식노드는 또한 또다른 자식노드들을 Nested 방식으로 계속 가질 수 있다. 만약 하나의 Element가 자식이 없는 경우, 간단히 WriteElementString() 메서드를 사용할 수 있다. 또한 Element가 Attribute 를 갖으면 이는 WriteStartElement()와 WriteEndElement() 사이에 WriteAttributeString() 메서드를 사용하여 지정할 수 있다.
아래 예제는 간단한 Employee 데이타를 XML로 작성한 예이다.
예제
// using System.Xml;
using (XmlWriter wr = XmlWriter.Create(@"C:\Temp\Emp.xml"))
{
wr.WriteStartDocument();
wr.WriteStartElement("Employees");
// Employee#1001
wr.WriteStartElement("Employee");
wr.WriteAttributeString("Id", "1001"); // attribute 쓰기
wr.WriteElementString("Name", "Tim"); // Element 쓰기
wr.WriteElementString("Dept", "Sales");
wr.WriteEndElement();
// Employee#1002
wr.WriteStartElement("Employee");
wr.WriteAttributeString("Id", "1002");
wr.WriteElementString("Name", "John");
wr.WriteElementString("Dept", "HR");
wr.WriteEndElement();
wr.WriteEndElement();
wr.WriteEndDocument();
}
/* 출력파일 Emp.xml
<?xml version="1.0" encoding="utf-8"?>
<Employees>
<Employee Id="1001">
<Name>Tim</Name>
<Dept>Sales</Dept>
</Employee>
<Employee Id="1002">
<Name>John</Name>
<Dept>HR</Dept>
</Employee>
</Employees>
*/
using (XmlWriter wr = XmlWriter.Create(@"C:\Temp\Emp.xml"))
{
wr.WriteStartDocument();
wr.WriteStartElement("Employees");
// Employee#1001
wr.WriteStartElement("Employee");
wr.WriteAttributeString("Id", "1001"); // attribute 쓰기
wr.WriteElementString("Name", "Tim"); // Element 쓰기
wr.WriteElementString("Dept", "Sales");
wr.WriteEndElement();
// Employee#1002
wr.WriteStartElement("Employee");
wr.WriteAttributeString("Id", "1002");
wr.WriteElementString("Name", "John");
wr.WriteElementString("Dept", "HR");
wr.WriteEndElement();
wr.WriteEndElement();
wr.WriteEndDocument();
}
/* 출력파일 Emp.xml
<?xml version="1.0" encoding="utf-8"?>
<Employees>
<Employee Id="1001">
<Name>Tim</Name>
<Dept>Sales</Dept>
</Employee>
<Employee Id="1002">
<Name>John</Name>
<Dept>HR</Dept>
</Employee>
</Employees>
*/
XmlReader : XML 파일 읽기
XmlReader 클래스는 XML 파일을 순차적으로 읽을 때 사용하는 클래스이다. XmlReader 클래스는 Abstract클래스로서 이를 구현한 클래스로 XmlTextReader 클래스가 있지만, XmlWriter와 마찬가지로 XmlTextReader를 사용하는 대신 XmlReader.Create() 메서드를 사용할 것을 권장한다.
XML 데이타를 읽기 위해 여러 종류의 Read* 메서드들이 있는데, 모두 뒤로 이동할 수는 없으며 앞으로 계속 전진하면서(forward only) 처리하게 된다. Read 메서드들 중 몇가지를 살펴보면, 우선 Read()는 XML 파일을 오픈한 후 처음 호출해야 하는 메서드인데, 이 메서드 호출로 XML의 첫 노드로 이동하게 된다. Read() 메서드는 순차적으로 XML 노드들로 이동하면서 true를 리턴하는데, 만약 XML 의 끝을 만나면 false 를 리턴한다.
XML Element의 Attribute 를 읽기 위해서는 GetAttribute() 메서드를 사용할 수 있으며, 또는 (아래 예제에서 처럼) 좀 더 간단하게 인덱서를 사용할 수 있다.
XML Element의 내용을 문자열로 읽기 위해서는 ReadElementContentAsString() 메서드를 사용한다 (주: 이 메서드와 비슷한 ReadElementString() 메서드가 있는데, ReadElementContentAsString() 메서드를 사용할 것을 권장). 이 메서드는 현재 Element 위치에 있다는 전제에서 Content를 읽고 다음 노드로 이동한다.
아래 예제는 위의 XmlWriter 에서 생성한 XML 파일을 읽는 예이다.
XML 데이타를 읽기 위해 여러 종류의 Read* 메서드들이 있는데, 모두 뒤로 이동할 수는 없으며 앞으로 계속 전진하면서(forward only) 처리하게 된다. Read 메서드들 중 몇가지를 살펴보면, 우선 Read()는 XML 파일을 오픈한 후 처음 호출해야 하는 메서드인데, 이 메서드 호출로 XML의 첫 노드로 이동하게 된다. Read() 메서드는 순차적으로 XML 노드들로 이동하면서 true를 리턴하는데, 만약 XML 의 끝을 만나면 false 를 리턴한다.
XML Element의 Attribute 를 읽기 위해서는 GetAttribute() 메서드를 사용할 수 있으며, 또는 (아래 예제에서 처럼) 좀 더 간단하게 인덱서를 사용할 수 있다.
XML Element의 내용을 문자열로 읽기 위해서는 ReadElementContentAsString() 메서드를 사용한다 (주: 이 메서드와 비슷한 ReadElementString() 메서드가 있는데, ReadElementContentAsString() 메서드를 사용할 것을 권장). 이 메서드는 현재 Element 위치에 있다는 전제에서 Content를 읽고 다음 노드로 이동한다.
아래 예제는 위의 XmlWriter 에서 생성한 XML 파일을 읽는 예이다.
예제
using (XmlReader rd = XmlReader.Create(@"C:\Temp\Emp.xml"))
{
while(rd.Read())
{
if (rd.IsStartElement())
{
if (rd.Name == "Employee")
{
// attribute 읽기
string id = rd["Id"]; // rd.GetAttribute("Id");
rd.Read(); // 다음 노드로 이동
// Element 읽기
string name = rd.ReadElementContentAsString("Name", "");
string dept = rd.ReadElementContentAsString("Dept", "");
Console.WriteLine(id + "," + name + "," + dept);
}
}
}
}
{
while(rd.Read())
{
if (rd.IsStartElement())
{
if (rd.Name == "Employee")
{
// attribute 읽기
string id = rd["Id"]; // rd.GetAttribute("Id");
rd.Read(); // 다음 노드로 이동
// Element 읽기
string name = rd.ReadElementContentAsString("Name", "");
string dept = rd.ReadElementContentAsString("Dept", "");
Console.WriteLine(id + "," + name + "," + dept);
}
}
}
}