MSXML6를 이용해서 XML을 파싱하는 MFC 애플리케이션을 만들어 보았다.
먼저 Visual Studio에서 다이얼로그 기반 MFC애플리케이션을 만든 후 MSXML를 사용하기 위해서 MSXML6 DLL를 임포트하였다. 물론 헤더파일을 include할 수 있지만 이 방법이 가장 손이 덜 간다.
<stdafx.h>
...
#import <msxml6.dll>
unsing namespace MSXML2;
...
그런다음 애플리케이션 클래스의 InitInstance()의 처음과 끝에 각각 COM라이브러리를 초기화하는 코드와, COM라이브러리를 해제하는 코드를 넣는다(실제로는 사용하기 직전에 초기화해도 문제 없다). MSXML은 COM 컴포넌트로 구현되어 있기 때문에 사용하기 위해서는 반드시 이 작업이 필요하다.
COM라이브러리를 초기화할 때 필요에 따라 ::CoInitialize()나 ::CoInitializeEx()중에서 선택해서 사용하면 된다. 자세한 내용은 MSDN을 참고할 것.
<MyApp.cpp>
BOOL CMyApp::InitInstance()
{
//::CoInitializeEx(NULL, COINIT_MULTITHREADED);
::CoInitialize(NULL);
...
기존 처리
...
::CoUninitialize();
}
이제 MSXML을 사용할 준비는 되었으니 실제로 사용하는 코드를 작성해 보자.
이 예에서는 다이얼로그에 버튼을 하나 추가하고, 그 버튼의 클릭 핸들러에 작성하여, 그 안에 MSXML을 사용하는 코드를 작성하였다.
<MyDlg.cpp>
void CMyClg::OnBnClickedButton1()
{
LPCWSTR xml =
L"<?xml version='1.0' encoding='utf-8'?>"
L"<itemlist><item>꽃</item><item>책</item></itemlist>";
MSXML2::IXMLDOMDocument2Ptr pDoc = NULL;
MSXML2::IXMLDOMNamedNodeMapPtr pNodeMap = NULL;
MSXML2::IXMLDOMNodeListPtr pNodeList = NULL;
pDoc.CreateInstance(__uuidof(MSXML2::DOMDocument60));
if( !pDoc ) {
return; // DOMDocument인스턴스 생성 실패
}
if( !pDoc->loadXML(xml) ) {
return; // XML파싱 실패
}
pNodeList = pDoc->selectNodes(L"//itemlist");
if( pNodeList ) {
MSXML2::IXMLDOMNodePtr pNode = pNodeList->Getitem(0);
MSXML2::IXMLDOMNodeListPtr pNodeList = pNode->GetchildNodes();
if( pNodeList ) {
MSXML2::IXMLDOMNodePtr pNode2 = NULL;
while( (pNode2 = pNodeList->nextNode()) ) {
CString nodeName = pNode2->GetnodeName();
if( !nodeName.Compare(L"item") ) {
CString str = (LPCWSTR)pNode2->Gettext();
MessageBox(str);
}
}
}
}
}
좀 장황한 코드이지만 알고보면 무척 간단하다.
테스트를 위해 "책"과 "꽃" 아이템을 가진 아이템리스트를 정의한 간단한 XML를 만들었다.
위 코드에서 하는 일이란 XML을 파싱하기 위해 DOMDocument인스턴스 포인터를 얻어온 후, loadXML()메서드를 호출하여 XML을 파싱한 후에, 그 나머지 코드에선 그냥 값을 빼서 쓰고 있다. 값을 빼서 쓰기 위해서는 대개의 경우 노드를 찾고 그 노드의 하위를 열거하면서 읽어오는 방식을 쓴다. 트리 구조라고 생각하면 된다. 값을 빼오기 위해 위 예제에서는 IXMLDOMNode와 IXMLDOMNodeList를 사용하였다.
빌드해서 실행한 후, 버튼을 클릭하면 텍스트가 "꽃"인 메시지박스와 "책"인 메시지박스가 순서대로 표시된다.
정말 간단하지 않은가?