사용자 도구

사이트 도구


language:csharp:xml

차이

문서의 선택한 두 판 사이의 차이를 보여줍니다.

차이 보기로 링크

양쪽 이전 판이전 판
language:csharp:xml [2014/12/01 14:58] kieunslanguage:csharp:xml [2024/04/23 22:44] (현재) – 바깥 편집 127.0.0.1
줄 1: 줄 1:
 +msdn에서 읽고 있는 xml 프로그래밍 : [[http://msdn.microsoft.com/ko-kr/library/t058x2df.aspx|설명이 시작 페이지]]
  
 +<color silver>뻑 XML, 그냥 맘편하게 JSON 쓰자고...</color>
 +
 +====== 개념 설명 ======
 +
 +===== Xml DOM =====
 +
 +from : [[http://msdn.microsoft.com/ko-kr/library/hf9hbf87.aspx|XML DOM, msdn]]
 +
 +<code xml>
 +<?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> 
 +</code>
 +
 +이 xml은 아래 그림처럼 메모리에 구조화 된다.
 +
 +{{:csharp:xmldom-memorystructure.gif|}}
 +
 +  * 각 원은 XmlNode 개체 - DOM 트리에서 기본 개체
 +  * XmlDocument (extended from XmlNode)로 메모리 로드/파일저장 (문서작업)을 수행 가능
 +  * DOM을 사용한 구조적인 접근/편집이 필요없이, 단순 읽기/쓰기가 필요한 경우
 +  * price는 특성(Attribute)이 있으며, GetAttribute를 사용해서 값을 읽어 올 수 있다.
 +
 +주요 클래스의 자식 유무의 차이
 +
 +  * 있음 : Document / DocumentFragment / EntityReference / Element / Attribute
 +  * 없음 : XmlDeclaration / Notation / Entity / CDATASection / Text / Comment / ProcessingInstruction / DocumentType 
 +
 +==== XmlNode(XmlDocument)로 가능한 작업 ====
 +
 +  - 노드 액세스 및 수정 / 정보 검색
 +  - 전체 노드 검색 / 노트가 포함하는 정보 검색
 +  - 메모리 상에서 작업
 +
 +==== 그외 ====
 +
 +다른 접근 방식
 +
 +  * 순차 접근 : XmlReader/XmlWriter 를 사용한 순차(Front to Back) 탐색 방식 사용 가능
 +  * 임의 접근 : XPath / XPathNavigator
 +
 +===== 노드 형식 =====
 +
 +XmlNode로부터 얻을 수 (쓸 수 있는) 노드 형식 [[http://msdn.microsoft.com/ko-kr/library/3k5w5zc3.aspx|msdn,Xml 노드형식]]에 나와 있다.
 +
 +일부 발췌
 +
 +^ DOM 노드 형식 ^ 개체 ^ 설명 ^
 +| Document | XmlDocument | Document 루트. 하지만 루트요소와 동일하진 않다, 무슨 말이지? |
 +| DocumentFragment | XmlDocumentFragment | 트리구조 없이, 하나 이상 노드 포함하는 임시 노드 |
 +| Element | XmlElement | 요소 노드 |
 +| Attr | XmlAttribute | 요소노드의 특성 |
 +| Text | XmlText | 요소,특성의 텍스트 |
 +
 +닷넷 전용 노드 형식
 +
 +^ 노드 형식 ^ 설명 ^
 +| XmlDeclaration | <?xml version="1.0"…> 선언 노드 |
 +
 +===== XML DOM 계층 구조 =====
 +
 +[[http://msdn.microsoft.com/ko-kr/library/xe9470fe.aspx|XML DOM(문서 개체 모델) 계층 구조]]
 +
 +{{:csharp:xmldom-class.gif|XML DOM(문서 개체 모델) 계층 구조}}
 +
 +이걸 보면, 상하 관계가 좀 더 확실히 보여진다.
 +
 +전체 트리와 무관한 단독 클래스
 +
 +  * XmlImplementation : xml문서 만드는데 사용.
 +  * XmlNamedNodeMap : 정렬되지 않은 노드 검색
 +  * XmlNodeList : 인덱스별로 정렬된 노드 검색
 +  * XmlNodeChangedEventArgs : xml문서 이벤트 처리, 좀 알아둬야할 것 같은 느낌
 +
 +===== XML 데이터에 개체 계층 구조 매핑 =====
 +
 +이거 좀 옮기기 어렵다. [[http://msdn.microsoft.com/ko-kr/library/a3bszkbd.aspx|원본 참조]]
 +
 +<code xml>
 +<book>
 +    <title>The Handmaid's Tale</title>
 +</book>
 +</code>
 +
 +  * book : XmlElement
 +  * title : XmlElement
 +  * The Handmaid's Tale : XmlText
 +
 +각 노드 타입에 따라, 연결되는 개체 클래스가 달라지므로 NodeType을 확인해서 맞게 사용 해야 한다.
 +
 +예제에서 사용된 타입, 타입 확인은 XmlNodeType 개체를 사용하고 if문이나 switch를 사용해서 비교 가능
 +
 +| XmlNodeType.Element |
 +| XmlNodeType.Text |
 +| XmlNodeType.CDATA |
 +| XmlNodeType.ProcessingInstruction |
 +| XmlNodeType.Comment |
 +| XmlNodeType.XmlDeclaration |
 +| XmlNodeType.EntityReference |
 +| XmlNodeType.EndElement |
 +====== 오퍼레이션 ======
 +
 +===== 문서 만들기 =====
 +
 +읽기/쓰기 어느 쪽을 하든 시작은 이렇게
 +
 +<code csharp>
 +XmlDocument doc = new XmlDocument();
 +</code>
 +
 +읽으려는 경우,
 +  * Load 메소드를 사용해서 읽기
 +  * XmlReader를 사용해서 로드
 +  * LoadXML 메서드를 사용해서 읽기
 +  * 선택은? 글쎄 아직 모르겠음.
 +===== 문서 읽기 =====
 +
 +[[http://msdn.microsoft.com/ko-kr/library/azsy1tw2.aspx|DOM에서 XML 문서 읽기]]
 +
 +  * XmlReader : 여러 형식(문자열/스트림/URL/텍스트판독기)으로 부터 XML을 읽어옴
 +  * Load : 문서를 메모리로 읽어 옮
 +  * LoadXml : 문자열에서 xml을 읽어옴
 +
 +LoadXml을 사용해 메모리상의 xml로드
 +
 +xml 기본 형식을 정할 수 있다면, 아래 예처럼 미리 더미값을 포함한 xml을 LoadXml로 읽어 들인 다음, 값을 수정하는 것도 괜찮겠다.
 +
 +<code csharp>
 +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");
 +    }
 +}
 +</code>
 +
 +===== 노드 추가 =====
 +
 +다음 오퍼레이션이 가능
 +
 +  * [[http://msdn.microsoft.com/ko-kr/library/k44daxya.aspx|DOM에서 새 노드 만들기]]
 +  * [[http://msdn.microsoft.com/ko-kr/library/7bxbds1w.aspx|기존 노드 복사]]
 +  * [[http://msdn.microsoft.com/ko-kr/library/kh91w6fw.aspx|한 문서에서 다른 문서로 기존 노드 복사]]
 +  * [[http://msdn.microsoft.com/ko-kr/library/033kfdk4.aspx|문서 조각 복사]]
 +
 +DOM에서 새 노드 만들기의 경우, 각 노드요소 별로 생성 메소드가 있으므로 그걸 사용하면 된다. 도움말에 보면 아래 항목이 보인다.
 +
 +  * [[http://msdn.microsoft.com/ko-kr/library/system.xml.xmldocument.createcdatasection.aspx|CreateCDataSection]]
 +  * [[http://msdn.microsoft.com/ko-kr/library/system.xml.xmldocument.createcomment.aspx|CreateComment]]
 +  * [[http://msdn.microsoft.com/ko-kr/library/system.xml.xmldocument.createdocumentfragment.aspx|CreateDocumentFragment]]
 +  * [[http://msdn.microsoft.com/ko-kr/library/system.xml.xmldocument.createdocumenttype.aspx|CreateDocumentType]]
 +  * [[http://msdn.microsoft.com/ko-kr/library/system.xml.xmldocument.createelement.aspx|CreateElement]]
 +  * [[http://msdn.microsoft.com/ko-kr/library/system.xml.xmldocument.createnode.aspx|CreateNode]]
 +  * [[http://msdn.microsoft.com/ko-kr/library/system.xml.xmldocument.createprocessinginstruction.aspx|CreateProcessingInstruction]]
 +  * [[http://msdn.microsoft.com/ko-kr/library/system.xml.xmldocument.createsignificantwhitespace.aspx|CreateSignificantWhitespace]]
 +  * [[http://msdn.microsoft.com/ko-kr/library/system.xml.xmldocument.createtextnode.aspx|CreateTextNode]]
 +  * [[http://msdn.microsoft.com/ko-kr/library/system.xml.xmldocument.createwhitespace.aspx|CreateWhitespace]]
 +  * [[http://msdn.microsoft.com/ko-kr/library/system.xml.xmldocument.createxmldeclaration.aspx|CreateXmlDeclaration]]
 +
 +특성을 추가하려는 경우 (또 다른 링크라서, 링크만 건다.) msdn은 온라인 문서라 그런지 depth가 너무 많다.
 +
 +  * [[http://msdn.microsoft.com/ko-kr/library/9yz7d1yb.aspx|DOM에서 요소의 새 특성 만들기]]
 +
 +===== XmlNodeChangedEventArgs를 사용한 XML 문서의 이벤트 처리 =====
 +
 +[[http://msdn.microsoft.com/ko-kr/library/4aa0sbk2.aspx|XmlNodeChangedEventArgs를 사용한 XML 문서의 이벤트 처리]]
 +
 +노드에 어떤 작업(추가/삭제/변경)이 발생될때 이벤트가 발생된다. (어디에 쓰는건지는 잘 모르겠음)
 +
 +^ 이벤트 ^ 발생 시기 ^
 +| NodeInserting | 현재 문서에 속한 노드가 다른 노드에 삽입되기 직전 |
 +| NodeInserted | 현재 문서에 속한 노드가 다른 노드에 삽입된 후 |
 +| NodeRemoving | 이 문서에 속한 노드가 문서에서 제거되기 직전 |
 +| NodeRemoved | 이 문서에 속한 노드가 부모로부터 제거된 직후 |
 +| NodeChanging | 노드 값이 변경되기 직전 |
 +| NodeChanged | 노드 값이 변경된 직후 |
 +
 +===== XML 문서에서 노드, 내용 및 값 수정 =====
 +
 +[[http://msdn.microsoft.com/ko-kr/library/1w7dc16f.aspx|XML 문서에서 노드, 내용 및 값 수정]]
 +
 +  * XmlNode
 +    * .Value : 값 변경
 +    * .InnerXml : 노드 전체 변경 (노드를 새 노드로 바꾸기). 자식노드의 태그를 변경.
 +    * .RemoveChild : 기존 노드를 삭제 (삭제된 노드를 리턴)
 +  * XmlCharacterData (문자열 처리)
 +    * .AppendData / InsertData 
 +    * .ReplaceData 로 문자열 처리. 원래값이 리턴값으로 돌아옴.
 +    * .DeleteData : 범위내 문자열 제거
 +
 +변경 가능한 노드 형식은 정해져 있으며, 범위 밖의 노드에서 변경 시도시 예외 발생
 +
 +  * InvalidOperationException
 +
 +변경 가능한 노드 형식
 +
 +^ 노드 형식 ^ 변경되는 데이터 ^
 +| Attribute | 특성 값 |
 +| CDATASection | CDATASection 내용 |
 +| Comment | 주석 내용 |
 +| ProcessingInstruction | 대상을 제외한 내용 |
 +| Text | 텍스트 내용 |
 +| XmlDeclaration | <?xml 및 ?> 태그를 제외한 선언 내용 |
 +| Whitespace | 공백 값.인식된 XML 공백 문자인 공백, 탭, CR 또는 LF 중 하나로 값을 설정할 수 있습니다. |
 +| SignificantWhitespace | 유효 공백 값.인식된 XML 공백 문자인 공백, 탭, CR 또는 LF 중 하나로 값을 설정할 수 있습니다. |
 +===== XPath 탐색 =====
 +
 +  * [[http://msdn.microsoft.com/ko-kr/library/d271ytdx.aspx|XPath 탐색을 사용하여 노드 선택]]
 +  * [[http://msdn.microsoft.com/ko-kr/library/ms256471(v=VS.80).aspx|XPath 구문(syntax)]]
 +  * [[http://msdn.microsoft.com/ko-kr/library/ms256086(VS.80).aspx|XPath예제]]
 +
 +==== XPath Select ====
 +  * SelectSingleNode : 선택 기준과 일치하는 첫번째 노드
 +  * SelectNodes : 일치하는 노드들의 XmlNodeList를 리턴
 +
 +네임스페이스를 포함할 수 있다(아래 예제처럼)라고 msdn에 명시. 없는 경우는 어떻게 되는지 모르겠네..
 +
 +네임스페이스가 없는 경우, 해당 구문 없이 사용
 +  * 있음 : "descendant::bk:book[bk:author/bk:last-name='Kingsolver']"
 +  * 없음 : "descendant::book[author/last-name='Austen']"
 +
 +<code csharp>
 +// 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'
 +// last name is Kingsolver.
 +XmlNode node = root.SelectSingleNode(
 +    "descendant::bk:book[bk:author/bk:last-name='Kingsolver']", nsmgr);
 +Console.WriteLine(node.InnerXml);
 +</code>
 +<code xml>
 +<?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>
 +</code>
 +
 +===== XML 데이터 형식 변환 =====
 +[[http://msdn.microsoft.com/ko-kr/library/15st98za.aspx|XML 데이터 형식 변환]]
 +
 +XmlConvert 클래스의 메서드를 사용해서 형식 변환을 한다.
 +
 +날짜형식
 +
 +<code csharp>
 +// example : <Element>2001-02-27T11:13:23</Element>
 +DateTime vDateTime = XmlConvert.ToDateTime(reader.ReadString());
 +</code>
 +
 +상세한 내용 (변경 가능 부분) : [[http://msdn.microsoft.com/ko-kr/library/9z1wz8wy.aspx|문자열을 .NET Framework 데이터 형식으로 변환]]
 +
 +====== 예제 ======
 +
 +xml을 메모리에 저장하고 사용
 +
 +<code csharp>
 +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() );
 +      }
 +    }
 +  }
 +}
 +</code>