Home Full Site
XmlDocument : XML 쓰기

XmlDocument 클래스는 XML을 메모리에 로딩하고 DOM (Document Object Model)을 빌드하는데, 이러한 방식은 특정 노드를 검색하거나 일정 조건의 노드들을 필터링하기 편리하며, 특히 XML을 쉽게 갱신하는데 유용하다. 단점으로는 XML을 모두 메모리 상에 로딩하기 때문에, 큰 XML 데이타를 처리할 때 메모리가 많이 소비된다 점이다.

XmlDocument를 사용하여 XML 데이타를 쓰기 위해서는 먼저 XmlDocument 객체를 생성하고 이 객체에 루트노드를 추가하고 다시 루트노드 밑에 필요한 자식노드들을 추가해 나간다.

XML Element를 생성하기 위해서는 XmlDocument의 CreateElement() 메서드를 사용하고, Attribute를 생성하기 위해서는 XmlDocument의 CreateAttribute() 메서드를 사용한다. 생성된 Element는 XmlNode 클래스 객체가 되는데, AppendChild() 메서드를 통해 부모 노드에 추가시기면 된다. CreateAttribute() 메서드로 생성된 Attribute는 XmlAttribute 클래스 객체가 되는데, 이는 Element 객체의 Attributes.Append() 를 통해 Attribute를 추가하게 된다.

XmlDocument 내에 모든 노드들이 생성되고 자식노드로 추가 되었으면, Save() 메서드를 호출하여 XML 파일에 저장하면 된다.

아래 예제는 간단한 Employee 데이타를 XML로 생성하는 예이다.


예제

// using System.Xml;

XmlDocument xdoc = new XmlDocument();

// 루트노드
XmlNode root = xdoc.CreateElement("Employees");
xdoc.AppendChild(root);

// Employee#1001
XmlNode emp1 = xdoc.CreateElement("Employee");
XmlAttribute attr = xdoc.CreateAttribute("Id");
attr.Value = "1001";
emp1.Attributes.Append(attr);

XmlNode name1 = xdoc.CreateElement("Name");
name1.InnerText = "Tim";
emp1.AppendChild(name1);

XmlNode dept1 = xdoc.CreateElement("Dept");
dept1.InnerText = "Sales";
emp1.AppendChild(dept1);

root.AppendChild(emp1);

// Employee#1002
var emp2 = xdoc.CreateElement("Employee");
var attr2 = xdoc.CreateAttribute("Id");
attr2.Value = "1002";
emp2.Attributes.Append(attr2);

var name2 = xdoc.CreateElement("Name");
name2.InnerText = "John";
emp2.AppendChild(name2);

XmlNode dept2 = xdoc.CreateElement("Dept");
dept2.InnerText = "HR";
emp2.AppendChild(dept2);

root.AppendChild(emp2);

// XML 파일 저장
xdoc.Save(@"C:\Temp\Emp.xml");


/* 출력파일 Emp.xml

<Employees>
  <Employee Id="1001">
    <Name>Tim</Name>
    <Dept>Sales</Dept>
  </Employee>
  <Employee Id="1002">
    <Name>John</Name>
    <Dept>HR</Dept>
  </Employee>
</Employees>

*/



XmlDocument : XML 읽기

XmlDocument 클래스를 사용하여 XML 데이타를 읽기 위해서는 먼저 XML을 Load 하여야한다. XML 파일이나 Stream으로부터 XML 데이타를 읽기 위해서는 Load() 메서드를 사용하고, XML 문자열로부터 로드하기 위해서는 LoadXml() 메서드를 사용한다.

XML이 로드된 후 특정 조건의 단일 노드를 검색하기 위해서는 XmlDocument의 SelectSingleNode() 메서드를 사용하고, 특정 조건의 복수 노드들을 필터링하기 위해서는 SelectNodes() 메서드를 사용한다. 이러한 Select 노드 메서드는 XPath 를 파라미터로 입력받는데, 예를 들어 루트노드 Employees 밑의 Employee 노드들을 모두 가져 오고 싶으면, /Employees/Employee 와 같이 필터링 조건을 지정한다. 또한 Id가 1002인 특정 Employee 노드만 가져올 경우 아래 예제와 같이 /Employees/Employee[@Id='1002'] 처럼 조건식을 지정할 수 있다. XPath에서 상대적 경로를 지정하기 위해서는 ./ 를 시작하고 절대적 경로는 / 로 시작하면 된다. 이밖에도 다양한 XPath 표현식이 있는데, 이는 MSDN의 XPath 예제 링크 를 참고한다.

XmlNode의 Attribute는 Attributes[속성명] 인덱서를 사용하여 엑세스하며, Element의 내용(Content)은 InnerText 속성을 사용하여 엑세스한다. 또한, Element 안의 내용을 XML로 리턴하기 위해서는 InnerXml 속성을 사용한다.

아래 예제는 위에서 생성 Emp.xml 파일을 읽어 들여 각 Employee의 데이타를 출력해 본 예이다.


예제

// using System.Xml;

XmlDocument xdoc = new XmlDocument();
            
// XML 데이타를 파일에서 로드
xdoc.Load(@"C:\Temp\Emp.xml");

// 특정 노드들을 필터링
XmlNodeList nodes = xdoc.SelectNodes("/Employees/Employee");

foreach (XmlNode emp in nodes)
{
    // Attribute 읽기
    string id = emp.Attributes["Id"].Value;

    // 특정 자식 Element 읽기
    string name = emp.SelectSingleNode("./Name").InnerText; //Relative Path 사용
    string dept = emp.SelectSingleNode("Dept").InnerText;   //간단히 자식 Element명 사용
    Console.WriteLine(id + "," + name + "," + dept);

    // 자식 노드들에 대해 Loop를 도는 예
    foreach (XmlNode child in emp.ChildNodes)
    {
        Console.WriteLine("{0}: {1}", child.Name, child.InnerText);
    }
}
    
// 특정 Id 속성으로 하나의 Employee 검색 예
XmlNode emp1002 = xdoc.SelectSingleNode("/Employees/Employee[@Id='1002']");
Console.WriteLine(emp1002.InnerXml);



XPathNavigator 활용

XPathNavigator는 XML 노드들을 XPath를 사용하여 편리하게 엑세스할 수 있으며, XML의 수정, 편집을 용이하게 하는 기능을 가지고 있다. XmlDocument의 SelectNodes() 혹은 SelectSingleNode() 메서드에서 사용하는 XPath는 실제 내부적으로 XPathNavigator를 사용하고 있다.

XPathNavigator 객체는 일반적으로 XPathDocument(읽기 전용) 혹은 XmlDocument(편집가능) 객체의 CreateNavigator() 메서드를 통해 얻어지는데, 다양한 Move 메서드들과 Select 메서드들과 노드 삽입, 추가 등의 편집 메서드들을 가지고 있다.

아래 예제는 XPathNavigator를 써서 Employee 중 Name 이 Tim 인 경우 이를 Timothy로 변경하는 예이다. XML을 수정해야 하므로 XPathDocument 대신 XmlDocument을 사용하였다.


예제

// using System.Xml;
// using System.Xml.XPath;

// XML을 수정하지 않을 경우 보다 가벼운 XPathDocument 사용 (Read Only)
//XPathDocument xdoc = new XPathDocument(@"C:\Temp\Emp.xml");

XmlDocument xdoc = new XmlDocument();
xdoc.Load(@"C:\Temp\Emp.xml");

XPathNavigator nav = xdoc.CreateNavigator();
XPathNodeIterator  nodes = nav.Select("/Employees/Employee");

while(nodes.MoveNext())
{
    nodes.Current.MoveToChild("Name", "");

    // Tim을 Timothy로 변경
    if (nodes.Current.Value == "Tim")
    {
        nodes.Current.SetValue("Timothy");
    }                
}

// XML 전체 트리를 저장
using (XmlWriter wr = XmlWriter.Create(@"C:\Temp\Emp2.xml"))
{
    nav.WriteSubtree(wr);
}



© csharpstudy.com