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() );
}
}
}
}