목차

msdn에서 읽고 있는 xml 프로그래밍 : 설명이 시작 페이지

<color silver>뻑 XML, 그냥 맘편하게 JSON 쓰자고…</color>

개념 설명

Xml DOM

from : XML DOM, msdn

<?xml version="1.0"?>
  <books>
    <book>
        <author>Carson</author>
        <price format="dollar">31.95</price>
        <pubdate>05/01/2001</pubdate>
    </book>
    <pubinfo>
        <publisher>MSPress</publisher>
        <state>WA</state>
    </pubinfo>
  </books> 

이 xml은 아래 그림처럼 메모리에 구조화 된다.

주요 클래스의 자식 유무의 차이

XmlNode(XmlDocument)로 가능한 작업

  1. 노드 액세스 및 수정 / 정보 검색
  2. 전체 노드 검색 / 노트가 포함하는 정보 검색
  3. 메모리 상에서 작업

그외

다른 접근 방식

노드 형식

XmlNode로부터 얻을 수 (쓸 수 있는) 노드 형식 msdn,Xml 노드형식에 나와 있다.

일부 발췌

DOM 노드 형식 개체 설명
Document XmlDocument Document 루트. 하지만 루트요소와 동일하진 않다, 무슨 말이지?
DocumentFragment XmlDocumentFragment 트리구조 없이, 하나 이상 노드 포함하는 임시 노드
Element XmlElement 요소 노드
Attr XmlAttribute 요소노드의 특성
Text XmlText 요소,특성의 텍스트

닷넷 전용 노드 형식

노드 형식 설명
XmlDeclaration <?xml version=“1.0”…> 선언 노드

XML DOM 계층 구조

XML DOM(문서 개체 모델) 계층 구조

XML DOM(문서 개체 모델) 계층 구조

이걸 보면, 상하 관계가 좀 더 확실히 보여진다.

전체 트리와 무관한 단독 클래스

XML 데이터에 개체 계층 구조 매핑

이거 좀 옮기기 어렵다. 원본 참조

<book>
    <title>The Handmaid's Tale</title>
</book>

각 노드 타입에 따라, 연결되는 개체 클래스가 달라지므로 NodeType을 확인해서 맞게 사용 해야 한다.

예제에서 사용된 타입, 타입 확인은 XmlNodeType 개체를 사용하고 if문이나 switch를 사용해서 비교 가능

XmlNodeType.Element
XmlNodeType.Text
XmlNodeType.CDATA
XmlNodeType.ProcessingInstruction
XmlNodeType.Comment
XmlNodeType.XmlDeclaration
XmlNodeType.EntityReference
XmlNodeType.EndElement

오퍼레이션

문서 만들기

읽기/쓰기 어느 쪽을 하든 시작은 이렇게

XmlDocument doc = new XmlDocument();

읽으려는 경우,

문서 읽기

DOM에서 XML 문서 읽기

LoadXml을 사용해 메모리상의 xml로드

xml 기본 형식을 정할 수 있다면, 아래 예처럼 미리 더미값을 포함한 xml을 LoadXml로 읽어 들인 다음, 값을 수정하는 것도 괜찮겠다.

using System;
using System.IO;
using System.Xml;
 
public class Sample
{
    public static void Main()
    {
        // Create the XmlDocument.
        XmlDocument doc = new XmlDocument();
        doc.LoadXml("<book genre='novel' ISBN='1-861001-57-5'>" +
                    "<title>Pride And Prejudice</title>" +
                    "</book>");
 
        // Save the document to a file.
        doc.Save("data.xml");
    }
}

노드 추가

다음 오퍼레이션이 가능

DOM에서 새 노드 만들기의 경우, 각 노드요소 별로 생성 메소드가 있으므로 그걸 사용하면 된다. 도움말에 보면 아래 항목이 보인다.

특성을 추가하려는 경우 (또 다른 링크라서, 링크만 건다.) msdn은 온라인 문서라 그런지 depth가 너무 많다.

XmlNodeChangedEventArgs를 사용한 XML 문서의 이벤트 처리

XmlNodeChangedEventArgs를 사용한 XML 문서의 이벤트 처리

노드에 어떤 작업(추가/삭제/변경)이 발생될때 이벤트가 발생된다. (어디에 쓰는건지는 잘 모르겠음)

이벤트 발생 시기
NodeInserting 현재 문서에 속한 노드가 다른 노드에 삽입되기 직전
NodeInserted 현재 문서에 속한 노드가 다른 노드에 삽입된 후
NodeRemoving 이 문서에 속한 노드가 문서에서 제거되기 직전
NodeRemoved 이 문서에 속한 노드가 부모로부터 제거된 직후
NodeChanging 노드 값이 변경되기 직전
NodeChanged 노드 값이 변경된 직후

XML 문서에서 노드, 내용 및 값 수정

XML 문서에서 노드, 내용 및 값 수정

변경 가능한 노드 형식은 정해져 있으며, 범위 밖의 노드에서 변경 시도시 예외 발생

변경 가능한 노드 형식

노드 형식 변경되는 데이터
Attribute 특성 값
CDATASection CDATASection 내용
Comment 주석 내용
ProcessingInstruction 대상을 제외한 내용
Text 텍스트 내용
XmlDeclaration <?xml 및 ?> 태그를 제외한 선언 내용
Whitespace 공백 값.인식된 XML 공백 문자인 공백, 탭, CR 또는 LF 중 하나로 값을 설정할 수 있습니다.
SignificantWhitespace 유효 공백 값.인식된 XML 공백 문자인 공백, 탭, CR 또는 LF 중 하나로 값을 설정할 수 있습니다.

XPath 탐색

XPath Select

네임스페이스를 포함할 수 있다(아래 예제처럼)라고 msdn에 명시. 없는 경우는 어떻게 되는지 모르겠네..

네임스페이스가 없는 경우, 해당 구문 없이 사용

// Load the document and set the root element.
XmlDocument doc = new XmlDocument();
doc.Load("bookstore.xml");
XmlNode root = doc.DocumentElement;
 
// Add the namespace.
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("bk", "urn:newbooks-schema");
 
// Select and display the first node in which the author's 
// last name is Kingsolver.
XmlNode node = root.SelectSingleNode(
    "descendant::bk:book[bk:author/bk:last-name='Kingsolver']", nsmgr);
Console.WriteLine(node.InnerXml);
<?xml version='1.0'?>
<bookstore xmlns="urn:newbooks-schema">
  <book genre="novel" style="hardcover">
    <title>The Handmaid's Tale</title>
    <author>
      <first-name>Margaret</first-name>
      <last-name>Atwood</last-name>
    </author>
    <price>19.95</price>
  </book>
  <book genre="novel" style="other">
    <title>The Poisonwood Bible</title>
    <author>
      <first-name>Barbara</first-name>
      <last-name>Kingsolver</last-name>
    </author>
    <price>11.99</price>
  </book>
  <book genre="novel" style="paperback">
    <title>The Bean Trees</title>
    <author>
      <first-name>Barbara</first-name>
      <last-name>Kingsolver</last-name>
    </author>
    <price>5.99</price>
  </book>
</bookstore>

XML 데이터 형식 변환

XML 데이터 형식 변환

XmlConvert 클래스의 메서드를 사용해서 형식 변환을 한다.

날짜형식

// example : <Element>2001-02-27T11:13:23</Element>
DateTime vDateTime = XmlConvert.ToDateTime(reader.ReadString());

상세한 내용 (변경 가능 부분) : 문자열을 .NET Framework 데이터 형식으로 변환

예제

xml을 메모리에 저장하고 사용

using System.Xml;
using System.Xml.XPath;
 
namespace XXX 
{
  class EMailDataXml
  {
    XmlDocument mDoc;
 
    public EMailDataXml()
    {
      mDoc = new XmlDocument();
      // save this to memory
      mDoc.LoadXml( 
        @"<queue>" + 
          @"<info index=""-1"" handler=""QICmd1""/>" +
          @"<email>" +
            @"<addr>dummy@x.y.z</addr>" +
            @"<title>n/a</title>" +
            @"<text>nothing</text>" + 
          @"</email>" + 
        @"</queue>" );
 
      // insert header
      XmlDeclaration xmldecl;
      xmldecl = mDoc.CreateXmlDeclaration( "1.0", "UTF-8", "yes" );
      XmlElement rootNode = mDoc.DocumentElement;
      mDoc.InsertBefore( xmldecl, rootNode );
    }
 
    // XPath로 XmlNode를 찾아서, Attribute에 값을 추가
    public void updateIndex( int newIndex )
    {
      try
      {
        XmlNode targetNode = mDoc.SelectSingleNode( "queue/info" );
        if( targetNode == null || targetNode.Attributes == null )
          return;
        XmlAttributeCollection _attrCol = targetNode.Attributes;
        XmlAttribute _attrIndex = (XmlAttribute)_attrCol.GetNamedItem( "index" );
        _attrIndex.Value = newIndex.ToString();
			}
      catch( XPathException _exp1 )
      {
        System.Windows.Forms.MessageBox.Show( _exp1.ToString() );
      }
    }
 
    public void updateHandler( string handlerName )
    {
      try
      {
        XmlNode targetNode = mDoc.SelectSingleNode( "queue/info" );
        if( targetNode == null || targetNode.Attributes == null )
          return;
        XmlAttributeCollection _attrCol = targetNode.Attributes;
        XmlAttribute _attrHandlerName = (XmlAttribute)_attrCol.GetNamedItem( "handler" );
        _attrHandlerName.Value = handlerName;
      }
      catch( XPathException _exp1 )
      {
        System.Windows.Forms.MessageBox.Show( _exp1.ToString() );
      }
    }
 
    // XPath로 XmlNode를 찾은 뒤, 하위 노드들을 순서대로 읽어서 값을 변경
    public void updateEMailData( string addr, string title, string emailText )
    {
      try
      {
        XmlNode targetParentNode = mDoc.SelectSingleNode( "queue/email" );
        if( targetParentNode == null )
          return;
 
        // get first child
        XmlNode _child = targetParentNode.FirstChild;
        // set value and move to next sibling xmlNode
        _child.FirstChild.Value = addr;
        _child = _child.NextSibling;
        _child.FirstChild.Value = title;
        _child = _child.NextSibling;
        _child.FirstChild.Value = emailText;
      }
      catch( XPathException _exp1 )
      {
        System.Windows.Forms.MessageBox.Show( _exp1.ToString() );
      }
    }
  }
}