티스토리 뷰

송호진(Hojin Song, wiluby Song) wiluby@ocic.co.kr

(이허접강좌는 3번에걸쳐서마무리될것이며, 초보자를위한강좌입니다 ^^)




필자는 XML은거의모르는상태에서 XML 프로그래밍을시작한지얼마되지않은초보개발자이다. C++로 MSXML 파서를이용하여 XML 프로그래밍을처음시작하는분들에게아주쬐그만한도움이라도되고자이강좌를시작하게되었습니다.

1. 소개

 

“XML Programming은쉽다”고말할수있습니다. 하지만제대로구현을하더라도잘않되는경우가많기때문에(뭐.. 개발자의실수겠지만) 고된정신상태(?)를계속유지하는경우가많을것입니다. 그래서대부분의개발자는자신에게맞는XML 관련 Class를만들어 XML 사용을쉽게처리하고있습니다. (필자역시그렇습니다ㅡㅡ;)그러나 XML Programming을 C++ 구현을하는분들은 (필자처럼어쩔수없이 C++로해야만하는ㅡㅡ;) 관련자료가부족하여처음시작할때많이고생을하게될지도모릅니다. (머리좋은사람은별로고생을하지않는다는…)

2. 준비물

별다른준비가필요하지않을것입니다. 아래와같이몇가지만…MS XML SDK 4.0Visual C++ IDE여기서는 DOM Programming 할것이므로관련생각(?)을가지고있으면좋겠다는.. ㅡㅡ;물론위에두개의준비물은대부분의개발자 PC에는설치가되어있을것입니다. 왜냐? 대부분해당분야를개발할때보통관련라이브러리들을모두설치해놓고시작을하기때문에… 더군다나 M$쪽개발자라면 MSXML SDK 정도는깔아봐야되는것이아닌가요?(저도배울때깔았다는전설(?)이… :P)

3. 시작하기

자~ 시작할까요? 아마도정신(?)이제대로된분들이라면벌써 VC++ IDE 환경이띄워져있을것이다. (아닌가? 필자는그랬더랍니다먼가하는것처럼보이기위해서ㅡㅡ;)준비가됐으면만들려는해당프로젝트를생성합니다. 예를들어서 MFC Application을만든다면다음과같이프로젝트를생성합니다. (여기서는 MFC AppWizard(EXE)를사용할것입니다) 

 

넘어가다가중요한점이있는데반드시 Step 2또는 3에서(프로젝트마다스텝이다를수있다) “Automation” 부분에체크표시를해야합니다. Visual C++에서는 Automation을이용해서 MSXML을사용하기때문입니다. 아~ 참고적으로여기서는Application Type을 Dialog Based로프로젝트를생성할것입니다 ;P 

이제프로젝트가생성되었으면 MSXML 파서를이용하기위해서라이브러리를추가해줘야합니다.\ 

#import <msxml4.dll>
using namespace MSXML2;
2번째줄은 namespace를사용한다는것이며, MSXML2::를붙이지않아도되도록하는옵션이라고알아두세요.(사실잘몰라서설명을하지못합니다… Namespace는중요하니관련서적을참고하길 ^^;)또한automation을이용하기위해서는두가지방법이있는데하나는 ClassWizard를이용해서 wrapper class를생성해서사용하는방법과또하나는 SmartPointer를이용해서사용하는방법입니다. 필자는SmartPointer를이용해서프로그래밍할것입니다. 스마트포인터를잘모르는분들은관련자료를읽어보세요. 스마트포인터를사용하면COM object들을 VB처럼사용하기쉽게해주고, 또귀찮은함수들(Query Interface 함수등)을일일이호출하지않아도Interface를얻어오는것도알아서다해줍니다 ;) 아주편하겠지요? ^^ 또한 SmartPointer는각인터페이스이름에 Ptr를붙이면됩니다.

Interface   SmartPointer
IXMLDOMDocument2 IXMLDOMDocument2Ptr  
IXMLDOMElement IXMLDOMElementPtr  

이제 XML 파서를이용할준비는모두되었습니다 ;) 만약자신을못믿겠다면지금당장 F7 키를눌러서 Build를해보시기바랍니다. 물론현재Build 했을때에러가없어야되겠죠?아마 Build 결과창에는다음과같이몇줄이출력되어있을것입니다.Generating Code... Linking...
TestXML.exe -0 error(s), 0 warning(s)

 

 

위와같이출력이되지않고에러가발생했다면어딘가잘못타이핑을하던가ㅡㅡ; 환경이제대로조성(?)이되어있지않은것입니다. 다시처음부터차근차근해보세요. 급하게생각하시면저처럼스트레스로고생할수있다는…

 

 

4. 실전으로맛보기

이제실전으로들어가서다음 XML 문서예제를만들어보겠습니다. 우선제일간단한 XML 문서를생성하면,
<?xml version="1.0" encoding="euc-kr"?> <IRC> <Nick>wiluby</Nick> </IRC>
test.XML 로 저장 (메모장으로 만들어서~TestXML 폴더 에 저장 )

 

아~ 너무간단하지않습니까? 필자가지금바로만들수있는실력이이것이니탓하지마세요ㅡㅡ;다음코드에서위XML 문서예제를생성하는코드를만들어보겠습니다. CTestXMLDlg::OnOK()함수를아래처럼바꾼니다.TestXMLDlg.cpp

void CTestXMLDlg::OnOK()
{
IXMLDOMDocument2Ptr pDoc; // XML Document 선언
IXMLDOMProcessingInstructionPtr pPI; // XML ProcessingInstruction 선언
IXMLDOMElementPtr pRootElement; // XML Element 선언
IXMLDOMElementPtr pElement;  
IXMLDOMTextPtr pText; // XML Text 선언

 

pDoc.CreateInstance(__uuidof(DOMDocument)); // 인스턴스생성
pPI=pDoc->createProcessingInstruction(L"xml",L"version=\"1.0\" encoding=\"euc-kr\""); // PI 생성
pRootElement=pDoc->createElement(L"IRC"); // Root element 생성
pElement=pDoc->createElement(L"Nick"); // "Nick" element 생성
pText=pDoc->createTextNode(L"wiluby"); // "wiluby" text element 생성
pDoc->appendChild(pPI); // ProcessingIsntruction 추가
pElement->appendChild(pText); // text element를 "Nick" element에추가
pRootElement->appendChild(pElement); // "Nick" element를 root element에추가
pDoc->appendChild(pRootElement); // Root element를문서에추가
AfxMessageBox(pDoc->xml); // XML 내용을보자!!}
// 이제 CTRL + F5 를눌러실행시킨다음, OK 버튼을눌르면메시지박스에 XML 내용이보인다.


 

 

참고로 XML 내용중에 PI 부분중에서 encoding 부분이없을것입니다. 하지만여기에서만보이지않을뿐나중에 save() 함수로저장할경우정상적으로파일에저장이됩니다. 필자처럼 encoding 부분이없다고몇시간을고생하지말고편하게생각하길바랍니다.상당히복잡하게보이지만아주간단한주석을삽입했으니참고하시길바란며. 대부분문서를만드는순서는1) XMLDOM 인스턴스생성2) PI 생성3) Root 노드생성(Node랑 Element랑같은것으로보면된다. 다만사용에따라차이가있다)4) 각 Node 생성5) 각 Node를 Root Node에추가6) PI를 XMLDOM 에추가7) Root Node를 XMLDOM 에추가위와같은간단한(?) 순서에따라서XML 문서를생성할수있습니다.또한설명을붙이자면 Node와 Element를같게보는것은용도만다를뿐사용법이동일하기때문입니다. 뒷부분에가면설명을드릴것입니다.

 

 


 

 

강좌 : C++로하는 MSXML SDK XML Programming 니가별거냐? (2/3번째)OCI정보통신(주) Research&Development Center송호진(Hojin Song, wiluby Song)wiluby@ocic.co.kr wiluby@ueye.net

(이허접강좌는 3번에걸쳐서마무리될것이며, 초보자를위한강좌입니다 ^^)필자는 XML은거의모르는상태에서 XML 프로그래밍을시작한지얼마되지않은초보개발자이다. C++로 MSXML 파서를이용하여 XML 프로그래밍을처음시작하는분들에게아주쬐그만한도움이라도되고자이강좌를시작하게되었습니다.1. Object 생성하기
먼저객체를사용하기위해서는객체를생성해야합니다. 왜냐면?? 인터페이스는객체가아니기때문입니다. 객채를생성할때SmartPointer를이용하면2가지방법으로객체를생성할수있습니다. ;)
IXMLDOMDocument2Ptr pDoc; // 선언
1) pDoc.createInstance(__uuidof(DOMDocument));
2) pDoc=IXMLDOMDocument2Ptr(__uuidof(DOMDocument));
위와같이하면간단하게객체를생성할수있습니다 ;) ^^ 필자는주로 1번을사용합니다 ;)
2. IXMLDOMDocument2Ptr
이인터페이스는 MSXML 파서를이용해서 DOM 작업(?)을하는데있어서반드시필요합니다. 바로 XML 문서를생성/조작하는데기본이되는인터페이스이기때문입니다. 사용하기위해서는다음과같이하면됩니다. (앞에서배우셨죠? ^^)
IXMLDOMDocument2Ptr pDoc=NULL; // XML DOM 문서선언
pDoc.CreateInstance(__uuidof(DOMDocument)); // 인스턴스생성.
그런데위에서선언부에는 IXMLDOMDocument2 인데, 왜인스턴스를생성할때는 _uuidof 매크로에 DOMDocument2가아니라 DOMDocument를사용하는가?? 그건필자도잘모르겠습니다. 필자도초보이기대문에 ^^; 여러분이직접찾아보시죠~ 찾는분에게는+a의지식이주어질것입니다 ;)
3. IXMLDOMProcessingInstructionPtr
이인터페이스는문서에PI를생성하는데쓰입니다. PI가먼지모르시는분들은 XML 서적을… ^^; 사용법은아래같이 ^^
IXMLDOMProcessingInstructionPtr pPI=NULL; // PI 선언
pPI=pDoc->createProcessingInstruction(L"xml",L"version=\"1.0\" encoding=\"euc-kr\""); // PI 생성
pDoc->appendChild(pPI); // PI를 XML Document에추가 ;)
그리고PI의추가는제일먼저해줘야될것으로보입니다. 이유는…저도초보라서 ^^;; 필자는젤먼저만해서어떤결과가나올지모르겠습니다. 모험심이강하신분은시도를… :P
4. IXMLDOMElementPtr
MSXML 프로그래밍에서 Element는 Node라고도볼수있고또그반대도… 첨해보시는분들은무지혼동하실줄압니다.필자도처음할때는그거나그거나라고생각을했는데나중에보니용도가달랐습니다. 그러나현재 element를추가하거나단순검색(selectSingleNode)에서는 IXMLDOMElement만사용하면됩니다 ;)
IXMLDOMElementPtr pElement=NULL; // Element 선언
pElement=pDoc->createElement(L”nick”); // “nick” 이라는Elment 생성
pDoc->appendChild(pElement); // XML문서에 element 추가
간단하게 element가추가되지요? ^^; 대부분의순서를보면“선언-> 생성-> 추가”의형식을가지고있습니다. 이것만잘생각하고프로그래밍하면즐거운나날이계속될것입니다 ;) ^^;;
5. IXMLDOMTextPtr
이제 TextNode를알아볼까요? TextNode는보시면아시다시피 element의값입니다. <nick>wiluby</nick>에서“wiluby” 가바로 TextNode가되지요 ^^; 코드로옮겨볼까요?
IXMLDOMTextPtr pText; // XML Text 선언
pText=pDoc->createTextNode(L"wiluby"); // "wiluby" text element 생성
pElement->appendChild(pText); // text element를상위 element에추가
여기서 pElement는앞절에서생성한 element입니다 ;) ^^ 소스를쭈욱~ 연결해서코딩하시면되겠죠? ^^
어떠세요? 이정도면간단한 XML 문서정도는생성하실수있겠죠? 그러나~ 생성보다는이미만들어진 XML 문서를많이이용하시게될것입니다 ;) 그러기위해서는몇가지는더배우셔야합니다. (사실거의다아셔야지된다는…)
6. XML 문서읽기와저장하기
이제부터만들어진문서를이용하기위해서는 load()와 save() 메소드를아셔야합니다☺그래야읽고저장을하겠죠?
우선 XML 문서를읽어오는 load() 메소드를알아보겠습니다.
load(const _variant_t &)
아~ xml 파일을 variant 형으로받네요.. ^^; 간단하게 test.xml 파일이 c:\에있다고가정하고해보겠습니다.
pDoc->load((_variant_t) ”c:\\test.xml”);
간단하게읽어오겠죠? C:\test.xml 파일이존재하면아주잘읽어들입니다 ;) 물론여기서는에러처리를하지않았습니다. 해당파일이존재하지않더라고에러메시지없이아주잘지나갑니다. 그러므로에러를처리하고싶으시면다음과같이FAILED 메크로를사용하시면됩니다 ;) ^^
HRESULT hr=pDoc->load((_variant_t)”c:\\test.xml”);
if(FAILED(hr)) { // load 실패하면..
…에러처리…
}
이문서에서는에러처리를거의하지않았지만거의모든메소드들은반환값이있습니다. 그러므로사용하실때는꼭! 에러처리를해주셔야좋은프로그램을만드실수있으실것입니다.
이제읽어오는것을알았으니저장하는법을알아야겠죠? 저장은 save() 메소드를이용합니다. Save() 메소드를볼까요?
save(const _variant_t &)
아~ save() 메소드도 load()메소드와똑같이 variant형을받네요 ^^;; 그러면다음과같이탁탁탁~~ *타이핑소리*
pDoc->save((_vaiant_t)"c:\\result.xml");
c:\result.xml 파일로결과값을저장합니다☺어떻습니까?? 쉽지않나요? 아마도처음시작하시는분들도무리없이이부분까지오셨으리라믿습니다!! ^^
7. 노드검색하기(XPath이용)
아지금까지잘따라오셨으면이부분도잘보셔야됩니다 ;) XML문서를조작하기위해서는검색이중요하니깐요? 그렇겠죠? 저도처음이부분에서어떻게해야될지몰라서고생을많이했었거든요. 우선검색을위한예제 XML을봐봅시다•
<?xml version="1.0" encoding="euc-kr"?>
<IRC>
<Nick SN=”001” SEX=”M”>wiluby</Nick>
<Nick SN=”002” SEX=”M”>darkduck</Nick>
</IRC>
앞에예제를딱보시면느낌이오나요? 아~ 저분딱아셨네☺바로앞에서제가적어논예제에 Attribute를약간추가를한것입니다. 보시면”Nick” element에“SN” 과“SEX” 라는 attribute가보이죠? 이절에서이용해야되기때문에추가한것입니다 ;) ^^; 단순검색과확장검색으로나누어알려드리겠는데요. 별의미없습니다 ^^;;; 뭐대단한게있는가본데라고생각하시면큰오산입니다. 그냥읽어주시면됩니다 ~~ ^^
1) 단순검색단순검색이라고제가부른것은단순히 element를검색하는법을나타냅니다. 물론형식은 XPath를써야되지만요. 필자가 XPath의 X자만알기때문에몇가지밖에잘모릅니다 ;) 6^^
우선검색에는두가지메소드가제공이되고있습니다.
IXMLDOMNodeList * selectNodes(XPath String) // 찾으려는노드를모두반환
IXMLDOMNode * selectSingleNode(XPath String) // 찾은노드단하나만반환
앞에와같이찾아서반환하는갯수가틀린메소드가제공이되고있습니다. 그리고잘보시면반환형태가IXMLDOMElement가아니라 IXMLDOMNode 나 IXMLDOMNodeList 형태입니다.
그리고대충설명을하면Element는Node의확장인터페이스입니다. Element나 ProcessingInstruction은특성을구성할때쓰이며, Node는문서의트리형태를구성할때쓰입니다. 사용되는것을보면 IXMLDOMElement 인터페이스는간단한 element의생성등에쓰이고, IXMLDOMNode 인터페이스는주로element의검색및조작에쓰입니다. (음… 뽀록으로배운거라ㅡㅡ;; 틀렸다면죄송합니다. *넙죽*)
그러면이제element만을검색하기위한 XPath문법을알아보겠습니다.
//element <<-풀어쓰면무지복잡한문장이된답니다. 선배의말씀ㅡㅡ;
하하~ 너무쉽죠? “//”에다가찾을 element의이름을적어주면됩니다. 예를들어서“Nick” 이라는 element 하나를찾아라!
IXMLDOMElementPtr pElement=NULL;
pElement=pDoc->selectSingleNode(L“//Nick”);
이렇게됩니다 ;) pElement에는맨먼저찾은노드가들어가있겠죠? 만약찾은노드가없다면? pElement는 NULL값을가지게됩니다 ^^;
그러면이번에“Nick” 이라는노드를다찾아볼까요? 반환되는값은 Node들의집합이기때문에 IXMLDOMNodeList 인터페이스를사용해야합니다.
IXMLDOMNodeListPtr pNodeList=NULL;
pNodeList=pDoc->selectNodes(L”//Nick”);
아하하~ 이려면“Nick” 을가진노드모두를찾습니다 ;)
그런데몇개의노드를찾았는지궁금하시죠?
long lCount=pNodeList->Getlength();
이렇게 Getlength() 메소드를사용하면 long형으로찾은갯수를반환해줍니다 ;) ^^;근데찾은노드들을어떻게이용해야될지모르시겠다고요? 아~ 이런… 그럼배운것이말짱꽝!이죠~그럼예제로처음만들었던 TestXML 프로젝트에추가해보겠습니다. 다음과같이 CTestXMLDlg 클래스에 OK버튼에대한 OnOK() 메소드를다음과같이 copy&paste 합니다 ;) ^^
void CTestXMLDlg::OnOK()
{
IXMLDOMDocument2Ptr pDoc=NULL; // XML Document 선언
IXMLDOMNodeListPtr pNodeList=NULL; // 찾은노드가저장될인터페이스
CString strTmp=""; // 임시저장변수•
long lCount=0,lTotal=0; // 루프에쓰일변수, 찾은노드수
pDoc.CreateInstance(__uuidof(DOMDocument)); // 인스턴스생성
pDoc->load((_variant_t)"c:\\test.xml"); // 아까보여드린예제를 c:\test.xml 로저장 ^^
pNodeList=pDoc->selectNodes(L"//Nick"); // “Nick” element는다찾아라
lTotal=pNodeList->Getlength(); // 몇개를찾았나?
while(lCount<lTotal) // 찾은갯수만큼루프를돌려라~
{
strTmp+=(LPCTSTR)pNodeList->Getitem(lCount++)->GetnodeName();
strTmp+="\n";
// 위두줄은찾은노드를인덱스로검색을하면서노드이름을 strTmp 변수에추가합니다 ;)
}
AfxMessageBox(strTmp); // 찾은노드이름을메시지박스에보여줌}
실행을시키고, OK 버튼을누르시면 ;) ^^
 
이렇게표시되죠? ^^ 참자알~ 하셨습니다~ ^^2) 확장검색확장검색은단순검색이랑사용법에는차이가없습니다. 그런데이문서를보시는분들은초보자라서어떻게하는지잘모르시거든요ㅡㅡ; 저처럼… (물론저보다는잘하시겠지만…)여기서는단순히 element 이름만으로검색하는것을넘어서 attribute에대해서검색을하고사용하는법에대해서알려드리겠습니다. 그리고예제는단순하게한가지만보여드리겠습니다. 왜냐고요? 앞에서배운단순검색예제와다른부분이거의없기때문이죠ㅡㅡ;우선 attribute에대해서검색을하고사용을하려면IXMLDOMNamedNodeMap 인터페이스를사용해야합니다. 아시겠죠? ^^ (그냥그렇다고끄덕이고지나가세요~ ^^)
void CTestXMLDlg::OnOK()
{ IXMLDOMDocument2Ptr pDoc=NULL; // XML Document 선언
IXMLDOMNamedNodeMapPtr pNodeMap=NULL; // for attribute
IXMLDOMNodeListPtr pNodeList=NULL; // 찾은노드들
IXMLDOMNodePtr pNode=NULL; // 찾은노드들하나씩(뒤에설명)
CString strTmp="";
long lCount=0,lTotal=0; // 노드들에대한갯수관련
long lTotalAttr=0,lCountAttr=0; // attribute에대한갯구관련
 
pDoc.CreateInstance(__uuidof(DOMDocument)); // 인스턴스생성
pDoc->load((_variant_t)"c:\\test.xml"); // 전에사용된예제파일~ ^^
 
pNodeList=pDoc->selectNodes(L"//Nick"); // “ Nick”노드들모두찾기~
 
if(pNodeList) {
lTotal=pNodeList->Getlength(); // 검색된노드의총갯수
while(lCount<lTotal) // 루프를돌리자~
{
pNode=pNodeList->Getitem(lCount++); // lCount 번째노드를선택
pNodeMap=pNode->Getattributes(); // 해당노드의 attribute 목록선택
 
lCountAttr=0;
lTotalAttr=pNodeMap->Getlength(); // Total of Attribute
while(lCountAttr<lTotalAttr)
{
strTmp+=(LPCTSTR)pNode->GetbaseName(); // 현재노드이름
strTmp+=" = ";
// 아래는해당노드의 attribute name
strTmp+=(LPCTSTR)pNodeMap->Getitem(lCountAttr)->GetnodeName();
strTmp+=" / ";
// 위에 attribute name에해당하는 attribute value(값)
strTmp+=(LPCTSTR)pNodeMap->Getitem(lCountAttr)->GetnodeValue().bstrVal;
strTmp+="\n";
lCountAttr++;
}
 
} // lCount < l Total
// return S_OK;
}
 
AfxMessageBox(strTmp);
}
자자실행시키시고결과값을보시면…
 
이렇게나오겠죠? 그죠? ^^ 이예제는“Nick” element 이름을가진모든노드에대해서 attribute를표시하는예제입니다 ;) ^^
그러면이제우리가원하는 attribute value로찾아봐야겠죠? 뭐아시는분들은건너뛰세요~ ^^
pNodeList=pDoc->selectNodes(L"//Nick"); // “ Nick”노드들모두찾기~
소스중에서윗줄을보시면검색조건을바꾸실수있습니다.XPath의형식을대충보시면
//elementname[@attributename=’attributevalue’]
형식입니다 ;)
전에보여진 xml 예제를가지고형식을만들어보겠습니다.
조건1) element가“Nick” 이고, attribute name이“SN”중에서“SN” 의값이“2” 인노드들을검색하기
Element name = Nick
attribute name = SN
attribute value = 2
검색식1) 위의조건대로검색식을만들면
//Nick[@SN=’2’]
이됩니다 :)
 이제검색에도문제가거의없겠죠? ^^; 이정도면웬만한문서는검색및조작이가능하게될것입니다 ^^;



 

 

 

강좌 : C++로하는 MSXML SDK XML Programming 니가별거냐? (3/3번째)OCI정보통신(주) Research&Development Center송호진(Hojin Song, wiluby Song)wiluby@ocic.co.kr

wiluby@ueye.net

(이허접강좌는 3번에걸쳐서마무리될것이며, 초보자를위한강좌입니다 ^^)필자는 XML은거의모르는상태에서 XML 프로그래밍을시작한지얼마되지않은초보개발자이다. C++로 MSXML 파서를이용하여 XML 프로그래밍을처음시작하는분들에게아주쬐그만한도움이라도되고자이강좌를시작하게되었습니다.1. 노드의 Text 값바꾸기지금까지배운것으로아마도잘프로그래밍하시고계시리라굳게믿습니닷!! 혹시나몰라서 ^^; <Nick>wiluby</Nick>에서“wiluby” 라는 Text 값을어떻게바꿀까?? 하시는분이있으실텐데요. 물론 MSXML SDK Help를보시면찾으실수있지만어디까지나초보를위해서~ ^^; 다음과같이예제코드를만들었습니다 ;)
void CTestXMLDlg::OnOK()
{
IXMLDOMDocument2Ptr pDoc=NULL; // XML Document 선언
IXMLDOMElementPtr pElement=NULL; // 찾은노드
 
IXMLDOMTextPtr pText;
 
pDoc.CreateInstance(__uuidof(DOMDocument)); // 인스턴스생성
pDoc->load((_variant_t)"c:\\test.xml"); // 전에사용된예제파일~ ^^
 
pElement=pDoc->selectSingleNode(L"//*[@SN='1']"); // attribute "SN" 값이 1인노드찾기
if(pElement)
{
pElement->Puttext(L"Changed"); // Text 값을변경 ^^;
}
 
AfxMessageBox(pDoc->xml); }
기존에있던코드를위와같이조금만바꾼다음에실행을시키시면 ;)



2. Attribute 읽어오기

Attrbiute 값을읽어오는방법에는두가지방법이있습니다. 하나는해당 element에서 getAttribute() 메소드를사용하거나, IXMLDOMNamedNodeMap 인터페이스를사용하는방법이있습니다. 모두나름대로장단점이있으니, 대충사용하시길(?) 바랍니다 ^^;1) getAttribute() 메소드
이메소드는 IXMLDOMElement 인터페이스에붙어있는메소드입니다. 사용은간단히하실수있겠죠? 모르신다구요? 아~ 이런… 그럼또보여드려야지용~ ^^;
void CTestXMLDlg::OnOK()
{
IXMLDOMDocument2Ptr pDoc=NULL; // XML Document 선언
IXMLDOMElementPtr pElement=NULL; // 찾은노드들하나씩(뒤에설명)
 
pDoc.CreateInstance(__uuidof(DOMDocument)); // 인스턴스생성
pDoc->load((_variant_t)"c:\\test.xml"); // 전에사용된예제파일~ ^^
 
pElement=pDoc->selectSingleNode(L"//*[@SN='1']"); // attribute "SN" 값이 1인노드찾기
if(pElement)
{
 
// 찾은노드의attribute name이“SEX” 인값표시
AfxMessageBox((LPCTSTR)pElement->getAttribute(L"SEX").bstrVal);
}
}
이제이해하셨죠? ^^;
2) IXMLDOMNamedNodeMapPtr
위에노드검색을하실때 attribute 검색을배우셨죠? 그때 IXMLDOMNamedNodeMap 인터페이스를사용하셨을것입니다. 이인터페이스는해당노드의모든 attribute를가져와서값을쉽게읽을수있도록해줍니다 ;)예제는앞에확장검색예제에서보셨죠?
pNodeMap=pNode->Getattributes(); // NodeMap에 pNode의 attribute들을주입(?) 시킨다
이렇게하시면됩니다. pNodeMap은당연히 IXMLDOMNamedNodeMap 인터페이스고요. pNode는 IXMLDOMElement나 IXMLDOMNode 인터페이스입니다. ;)
3. 만들어진 XML 문서를이쁘게만들기(XSLT)
이제어느정도모두초보티를벗으셨겠네요. ^^; 그러나이것저것혼자서해보신분들은아시겠지만 XML문서를만들어보시면. 이문서의처음에서예제로만들어본문서를파일에저장해보시면아마두… 다음과같이…
 
이렇게나왔을것입니다. 머가다르냐구요?
<?xml version="1.0" encoding="euc-kr"?>
<IRC>
<Nick>wiluby</Nick>
</IRC>
제시했던예제는앞과같은데결과는ㅡㅡ; 그냥 <IRC><Nick>wiluby</Nick></IRC>라고나올것입니다. 한줄로…솔직히한줄로나오면보기싫죠…물론이렇게짧은 XML 문서야별문제가없겠지만, 약간이라도큰문서들은보기가싫어질것입니다. 바로 indent가없기때문이죠. 그래서약간의팁을실어드리겠습니다 ^^;
바로 XSLT 를사용하시면문서를아주곱게사용하실수있습니다. 바로해당함수를보여드리죠. 하지만 XSLT 파일이하나필요합니다. Indent.xsl 파일입니다. 두개다소스를보여드릴께요.약간허접하기는하지만소스는그대로 copy&paste 합니다. 에러처리하는부분은대충제거했습니다 ;> 아마두아래소스는그냥가져다쓰시게될것입니다. 고칠곳이라고는에러처리하는부분뿐일것입니다 ^^
사용법은다음과같습니다.
형식)Transform(입력파일, 출력파일);
예제)Transform(L”c:\\test.xml”,”c:\\result.xml”);
HRESULT Transform(BSTR bsInputXMLFile, BSTR bsOutputXMLFile)
{
IXMLDOMDocumentPtr pXML=NULL; // 원래문서
IXMLDOMDocumentPtr pXSL=NULL; // 스타일쉬트~
IXMLDOMDocumentPtr pResult=NULL;
HRESULT hr=S_OK;
 
try
{
hr=pXML.CreateInstance(__uuidof(DOMDocument)); // 문서불러오기
pXML->put_async(VARIANT_FALSE);
pXML->load((_variant_t)bsInputXMLFile);
 
hr=pXSL.CreateInstance(__uuidof(DOMDocument));
 
// 쉿~타일시트불러오기
 
pXSL->put_async(VARIANT_FALSE);
pXSL->load((_variant_t)”indent.xsl”); // 파일경로에주의하세요!!!
hr=pResult.CreateInstance(__uuidof(DOMDocument));
if(FAILED(hr)) {
return E_FAIL;
}
VARIANT vObject;
VariantInit(&vObject);
vObject.vt=VT_DISPATCH;
vObject.pdispVal=pResult;
hr=pXML->transformNodeToObject(pXSL,vObject); // 변환하기~
if(FAILED(hr)) { // 에러처리
return E_FAIL;
}
// 변환완성저장하기
pResult->save((_variant_t)bsOutputXMLFile);
}
catch(_com_error &e) {
return E_FAIL;
}
return S_OK;
}
저는위함수를그냥쓰고있는데요. 아주유용합니다.
아~ 하나더있어야겠죠? XSLT 파일;) 이파일은제선배가만든것입니다 ;) (Darkness라고 ^^ 한프로그래밍하시는형이죠 ;) + 잘생겼어요~ ㅋㅋㅋ)다음내용은 indent.xsl 로저장하시면됩니다. 위에소스에이파일의경로를제대로지정해주세요. 아니면변환이않될것입니다.
<?xml version="1.0" encoding="euc-kr"?>
<!-- Edited by HyoungMoon, Lee -->
<!-- Copyright ⓒ OCI 정보통신㈜-->
<!--darkness@ocic.co.kr -->
<!---->
<!--indent for XSLT (ver 0.1.2) -->
<!--Last Update : 2002.09.25 -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="euc-kr" indent="yes"/>
<xsl:template match="*">
<xsl:element name="{name(.)}">
<xsl:apply-templates select="@*"/>
<xsl:if test="child::* or child::text()">
<xsl:apply-templates/>
</xsl:if>
</xsl:element>
</xsl:template>
<xsl:template match="@*">
<xsl:attribute name="{name(.)}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
<xsl:template match="processing-instruction()">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="comment()">
<xsl:comment>
<xsl:value-of select="."/>
</xsl:comment>
</xsl:template>
</xsl:stylesheet>

4. 끝마치며…

상당히허접하게대충대충 MSXML SDK를이용하여프로그래밍하는것을적어왔는데, 아마두이게뭔소리야하시는분들도많을꺼라고생각합니다. 그런데저같이정말 XML 프로그래밍을처음접하시는분들은좀고생을하지않을까해서이리저리문서를뒤적이다가… 이제야좀적응이되어서, 이거라도다른분들께좀도움이되지않을까해서문서를작성해올려봅니다.다른분들께도움이많이되었으면좋겠습니다 ^^ *꾸벅*질문은메일로해주시면감사하겠습니다. 아~ 한가지필자도초보라는것을기억하시고질문을… ^^;;

 


 

 


 

 

 

 

반응형
댓글