msdn에서 읽고 있는 xml 프로그래밍 : [[http://msdn.microsoft.com/ko-kr/library/t058x2df.aspx|설명이 시작 페이지]] 뻑 XML, 그냥 맘편하게 JSON 쓰자고... ====== 개념 설명 ====== ===== Xml DOM ===== from : [[http://msdn.microsoft.com/ko-kr/library/hf9hbf87.aspx|XML DOM, msdn]] Carson 31.95 05/01/2001 MSPress WA 이 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 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|원본 참조]] The Handmaid's Tale * 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 | ====== 오퍼레이션 ====== ===== 문서 만들기 ===== 읽기/쓰기 어느 쪽을 하든 시작은 이렇게 XmlDocument doc = new XmlDocument(); 읽으려는 경우, * 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로 읽어 들인 다음, 값을 수정하는 것도 괜찮겠다. using System; using System.IO; using System.Xml; public class Sample { public static void Main() { // Create the XmlDocument. XmlDocument doc = new XmlDocument(); doc.LoadXml("" + "Pride And Prejudice" + ""); // Save the document to a file. doc.Save("data.xml"); } } ===== 노드 추가 ===== 다음 오퍼레이션이 가능 * [[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 | 태그를 제외한 선언 내용 | | 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']" // 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); The Handmaid's Tale Margaret Atwood 19.95 The Poisonwood Bible Barbara Kingsolver 11.99 The Bean Trees Barbara Kingsolver 5.99 ===== XML 데이터 형식 변환 ===== [[http://msdn.microsoft.com/ko-kr/library/15st98za.aspx|XML 데이터 형식 변환]] XmlConvert 클래스의 메서드를 사용해서 형식 변환을 한다. 날짜형식 // example : 2001-02-27T11:13:23 DateTime vDateTime = XmlConvert.ToDateTime(reader.ReadString()); 상세한 내용 (변경 가능 부분) : [[http://msdn.microsoft.com/ko-kr/library/9z1wz8wy.aspx|문자열을 .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( @"" + @"" + @"" + @"dummy@x.y.z" + @"n/a" + @"nothing" + @"" + @"" ); // 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() ); } } } }