msdn에서 읽고 있는 xml 프로그래밍 : 설명이 시작 페이지
<color silver>뻑 XML, 그냥 맘편하게 JSON 쓰자고…</color>
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로부터 얻을 수 (쓸 수 있는) 노드 형식 msdn,Xml 노드형식에 나와 있다.
일부 발췌
DOM 노드 형식 | 개체 | 설명 |
---|---|---|
Document | XmlDocument | Document 루트. 하지만 루트요소와 동일하진 않다, 무슨 말이지? |
DocumentFragment | XmlDocumentFragment | 트리구조 없이, 하나 이상 노드 포함하는 임시 노드 |
Element | XmlElement | 요소 노드 |
Attr | XmlAttribute | 요소노드의 특성 |
Text | XmlText | 요소,특성의 텍스트 |
닷넷 전용 노드 형식
노드 형식 | 설명 |
---|---|
XmlDeclaration | <?xml version=“1.0”…> 선언 노드 |
이걸 보면, 상하 관계가 좀 더 확실히 보여진다.
전체 트리와 무관한 단독 클래스
이거 좀 옮기기 어렵다. 원본 참조
<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();
읽으려는 경우,
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 문서의 이벤트 처리
노드에 어떤 작업(추가/삭제/변경)이 발생될때 이벤트가 발생된다. (어디에 쓰는건지는 잘 모르겠음)
이벤트 | 발생 시기 |
---|---|
NodeInserting | 현재 문서에 속한 노드가 다른 노드에 삽입되기 직전 |
NodeInserted | 현재 문서에 속한 노드가 다른 노드에 삽입된 후 |
NodeRemoving | 이 문서에 속한 노드가 문서에서 제거되기 직전 |
NodeRemoved | 이 문서에 속한 노드가 부모로부터 제거된 직후 |
NodeChanging | 노드 값이 변경되기 직전 |
NodeChanged | 노드 값이 변경된 직후 |
변경 가능한 노드 형식은 정해져 있으며, 범위 밖의 노드에서 변경 시도시 예외 발생
변경 가능한 노드 형식
노드 형식 | 변경되는 데이터 |
---|---|
Attribute | 특성 값 |
CDATASection | CDATASection 내용 |
Comment | 주석 내용 |
ProcessingInstruction | 대상을 제외한 내용 |
Text | 텍스트 내용 |
XmlDeclaration | <?xml 및 ?> 태그를 제외한 선언 내용 |
Whitespace | 공백 값.인식된 XML 공백 문자인 공백, 탭, CR 또는 LF 중 하나로 값을 설정할 수 있습니다. |
SignificantWhitespace | 유효 공백 값.인식된 XML 공백 문자인 공백, 탭, CR 또는 LF 중 하나로 값을 설정할 수 있습니다. |
네임스페이스를 포함할 수 있다(아래 예제처럼)라고 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>
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() ); } } } }