티스토리 뷰

출처:

http://myblue0324.tistory.com/92

XML은 현재 많은 분야에서 쓰이고 있는 문서포맷입니다.
TinyXML은 C/C++ 프로그래밍에서 쉽게 간단하게 XML문서를 파싱하고 생성하고 수정하는 방법을 제공합니다.

다음은 TinyXML의 사용예제입니다.



1. 예제 XML 문서 (sample.xml)
본 포스팅에서 예제로 사용된 XML 문서형태입니다.

<?xml version="1.0" encoding="euc-kr" ?>
<MyApp>
<!--Settings for MyApp-->
<Messages>
<Welcome>Welcome to MyApp</Welcome>
<Farewell>Thank you for using MyApp</Farewell>
</Messages>
<Windows>
<Window name="MainFrame" x="5" y="15" w="400" h="250" />
</Windows>
<Connection ip="192.168.0.1" timeout="123.456000" />
</MyApp>

2. XML 문서 읽기.
XML 문서는 파일의 경로를 입력하여 해당 XML문서를 읽어들일 수 있습니다.

TiXmlDocument doc;
doc.LoadFile("D:\\sample.xml");

또는 C/C++에서 제공하는 파일오픈 관련 함수를 통하여 문자열로 읽어들일수도 있습니다.

char* pXmlData = NULL;
CString strFilePath = "D:\\sample.xml";

CFile hFile;
if (!hFile.Open(strFilePath, CFile::modeRead)) return;

DWORD dwSize = hFile.GetLength();
pXmlData = new char[dwSize];
memset(pXmlData, 0x00, sizeof(pXmlData));

if (!hFile.Read(pXmlData, uSize))
{
delete [] pXmlData;
return;
}
hFile.Close();

TiXmlDocument doc;
doc.Parse(pXmlData);

3. XML 문서 파싱 및 수정.
문자열 혹은 파일명을 통해 읽어들인 XML 문서의 원하는 노드 및 속성, 데이터 파싱이 가능하고 데이터의 수정또한 가능합니다.

원하는 노드 및 데이터의 파싱하는 예제입니다.

TiXmlDocument doc;
doc.LoadFile("D:\\sample.xml");

// 루트노드 접근.
TiXmlElement* pRoot = doc.FirstChildElement("MyApp");
if (!pRoot) return;

// 값을 읽고자 하는 Welcome 엘리먼트로 접근.
TiXmlElement* pElem = pRoot->FirstChildElement("Messages")->FirstChildElement("Welcome");
if (!pElem) return;

// 엘리먼트 이름(Welcome).
char* pszNode = (char*)pElem->Value();
if (pszNode)
TRACE("Node: <%s>\n", pszNode);

// 해당 엘리먼트의 데이터(Welcome to MyApp).
char* pszText = (char*)pElem->GetText();
if (pszText)
TRACE("Text: %s\n", pszText);

원하는 노드의 속성을 파싱합니다.

TiXmlDocument doc;
doc.LoadFile("D:\\sample.xml");

// 루트노드 접근.
TiXmlElement* pRoot = doc.FirstChildElement("MyApp");
if (!pRoot) return;

// 속성을 가지고 있는 Window 엘리먼트로 접근.
TiXmlElement* pElem = pRoot->FirstChildElement("Windows")->FirstChildElement("Window");
if (!pElem) return;

// Window 엘리먼트 name 속성의 문자열 데이터(MainFrame).
char* pszText = (char*)pElem->Attribute("name");
if (pszText)
TRACE("Text: %s\n", pszText);

// Window 엘리먼트 x 속성의 정수형 데이터(5).
int nValue;
pElem->Attribute("x", &nValue);
TRACE("Text: %d\n", n);

원하는 엘리먼트의 데이터를 수정합니다.

TiXmlDocument doc;
doc.LoadFile("D:\\sample.xml");

TiXmlElement* pRoot = doc.FirstChildElement("MyApp");
if (!pRoot) return;

// 수정하고자 하는 Welcome 엘리먼트로 접근.
TiXmlElement* pElem = pRoot->FirstChildElement("Messages")->FirstChildElement("Welcome");
if (!pElem) return;

// Welcome 엘리먼트의 데이터 삭제 및 "Hi. Everyone" 문자열로 수정.
pElem->Clear();
pElem->LinkEndChild(new TiXmlText("Hi. Everyone"));

다음 예제는 XML 문서전체를 순환하면서 엘리먼트 및 속성 데이터를 파싱하는 예제입니다.

TiXmlDocument doc;
doc.LoadFile("D:\\sample.xml");
TiXmlHandle hDoc(&doc);

// 루트노드 접근.
TiXmlElement* pRoot = hDoc.FirstChildElement().Element();
if (!pRoot) return;

// 루트노드를 시작으로 각 하위노드들의 뎁스별 순차검색.
SearchXMLData(pRoot);
void SearchXMLData(TiXmlElement* pElem)
{
TiXmlHandle hRoot(0);
TiXmlElement* pSubElem = pElem;
TiXmlAttribute* pAttrib = NULL;

// 현재 뎁스의 노드를 루트노드로 설정하고 하위노드가 있는지를 판별.
hRoot = TiXmlHandle(pSubElem);
pSubElem = hRoot.FirstChildElement().Element();
if (!pSubElem) return;

char* pszNode = NULL;
char* pszAttrib = NULL;
char* pszText = NULL;

while (pSubElem)
{
// 엘리먼트 이름.
pszNode = (char*)pSubElem->Value();
if (pszNode)
TRACE("Node: <%s>\n", pszNode);

// 속성.
pAttrib = pSubElem->FirstAttribute();
if (pAttrib)
{
while (pAttrib)
{
// 속성이름.
pszAttrib = (char*)pAttrib->Name();
if (pszAttrib)
TRACE("Attrib: (%s)\n", pszAttrib);

// 속성 데이터
pszText = (char*)pAttrib->Value();
if (pszText)
TRACE("Text: %s\n", pszText);

pAttrib = pAttrib->Next();
}
}

pszText = (char*)pSubElem->GetText();
if (pszText)
TRACE("Text: %s\n", pszText);

// 현재 노드의 하위노드 검색을 위한 함수호출.
SearchXMLData(pSubElem);
pSubElem = pSubElem->NextSiblingElement();
}
}

4. XML 문서 생성.
원하는 형태의 XML 문서 생성이 가능합니다.
XML 문서 생성시 new 를 통해 할당된 노드 및 데이터들은 자동으로 해제가 되기 때문에 직접 해제할 필요가 없습니다.

TiXmlDocument doc;
TiXmlElement* pElem = NULL;

// XML 선언.
TiXmlDeclaration* pDec = new TiXmlDeclaration("1.0", "euc-kr", "");
doc.LinkEndChild(pDec);

// 루트노드 설정.
TiXmlElement* pRoot = new TiXmlElement("MyApp");
doc.LinkEndChild(pRoot);

// 주석 추가.
TiXmlComment* pComment = new TiXmlComment();
pComment->SetValue("Settings for MyApp");
pRoot->LinkEndChild(pComment);

// 하위노드 및 데이터 추가.
TiXmlElement* pNode = NULL;
TiXmlElement* pSubNode = NULL;

pNode = new TiXmlElement("Messages");
pRoot->LinkEndChild(pNode);

pSubNode = new TiXmlElement("Welcome");
pSubNode->LinkEndChild(new TiXmlText("Welcome to MyApp"));
pNode->LinkEndChild(pSubNode);

// 하위노드 및 속성값 추가.
pNode = new TiXmlElement("Windows");
pRoot->LinkEndChild(pNode);

pSubNode = new TiXmlElement("Window");
pNode->LinkEndChild(pSubNode);
pSubNode->SetAttribute("name", "MainFrame");
pSubNode->SetAttribute("x", 5);
pSubNode->SetAttribute("y", 15);
pSubNode->SetAttribute("w", 400);
pSubNode->SetAttribute("h", 250);

doc.SaveFile("D:\\sample3.xml");

위 예제를 잘 활용하면 간단한 XML 문서를 조작하는데는 상당히 유용할듯 보입니다.

TinyXML 소스코드는 아래의 URL에서 다운로드가 가능합니다.

http://sourceforge.net/projects/tinyxml/

프로젝트에 다운로드 받은 파일들을 추가하고 헤더파일들을 include 하여 사용하면 쉽게 사용가능합니다. 그러나 간혹 Visual Studio에서 컴파일 시 미리컴파일된 헤더 관련해서 에러가 발생하는데 이런 경우에는 아래 URL을 참조하여 해결하면 원만한 사용이 가능합니다.

http://myblue0324.tistory.com/55

반응형
댓글