http://blog.naver.com/placeaj/120102079830
libxml2 XML / 프로그래밍
ex)
<?xml version="1.0" encoding="UTF-8"?>
<A>
<B>
<C>
<element1>TEST1</element1>
<element2>TEST2</element2>
<element3>TEST3</element3>
</C>
<C>
<element1>TEST4</element1>
<element2>TEST5</element2>
<element3>TEST6</element3>
</C>
</B>
<B>
<C>
<element1>TEST7</element1>
<element2>TEST8</element2>
<element3>TEST9</element3>
</C>
<C>
<element1>TEST10</element1>
<element2>TEST11</element2>
<element3>TEST12</element3>
</C>
</B>
</A>
위와 같은 XML 문서가 있을 때, <C> element의 자식 element인 element2의 content 를 변경하고자 하였다.
구현하기에 앞서 libxdml header파일을 설정하려고 하는데 자꾸 error가 났다. 확인해 본 결과 libxml의 디렉토리 구조가 libxml2/libxml 안에 있어서 참조가 되지 않았다. 그래서 /usr/include/libxml에 header 파일이 없다면 옮기도록 하자.
일단 libxml.org의 API, Sample Code를 참조하도록 하자. 나도 처음에는 뭐가 뭔지 몰랐는데 libxml tutorial을 보면서 차근히 해본 결과 큰 문제 없이 겉의 구조를 파악할 수 있있다.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include "xmlParser.h"
/* Make by JH.Kim */
/* GLOBAL VARIABLE */
xmlChar *data;
/* 임의로 입력한 데이터다. */
char d[5120] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<A>\r\n<B>\r\n<C>\r\n<element1>TEST1</element1>\r\n<element2>TEST2</element2>\r\n<element3>TEST3</element3></C>\r\n<C>\r\n<element1>TEST4</element1>\r\n<element2>TEST5</element2>\r\n<element3>TEST6</element3></C>\r\n<C>\r\n<element1>TEST7</element1>\r\n<element2>TEST8</element2>\r\n<element3>TEST9</element3></C>\r\n<C>\r\n<element1>TEST10</element1>\r\n<element2>TEST11</element2>\r\n<element3>TEST12</element3></C>\r\n</B>\r\n</A>";
void SetXmlData(char *d){
data = (xmlChar *)d;
}
void SetXmlParsingElement(char *element, char *parsingData){
xmlDocPtr doc;
xmlNodePtr cur;
xmlNodePtr temp;
/* create xml document object */
doc = xmlParseDoc(data);
/* create xml document object exception */
if(doc == NULL){
fprintf(stderr, "Document not parsed successfully.\n");
return;
}
/* xml document 에서 root element를 가져옴 */
cur = xmlDocGetRootElement(doc);
/* xml document의 root element의 유효성 검사 */
if(cur == NULL){
fprintf(stderr, "empty document.\n");
xmlFreeDoc(doc);
return;
}
/* xml document의 root element의 이름 비교 */
if(xmlStrcmp(cur->name, (const xmlChar *) "A")){
fprintf(stderr, "document of the wrong type, root node != reginfo \n");
xmlFreeDoc(doc);
return;
}
/* root element의 child element 값을 가져옴 */
cur = cur->xmlChildrenNode;
/* element를 비교하여 변경하고자 하는 element를 찾음 */
while(cur != NULL){
if((!xmlStrcmp(cur->name, (const xmlChar *)"B"))){
temp = cur;
temp = temp->xmlChildrenNode;
/* registeration element의 children element 중 conteact element의 위치를 찾음 */
while(temp != NULL){
if((!xmlStrcmp(temp->name, (const xmlChar *)"C"))){
ParseElement(doc, temp, element, parsingData);
temp = temp->next;
}//if
else{
temp = temp->next;
}
}//while
}//if
cur = cur->next;
}
xmlChar *d;
int i;
xmlDocDumpFormatMemory(doc, &d, &i, 1);
printf("\n\n/*******CHANGED********/\n%s", (char *) d);
xmlFree(d);
xmlFreeDoc(doc);
}
void ParseElement(xmlDocPtr doc, xmlNodePtr cur, char *element, char *parsingData){
xmlChar *key;
xmlChar *r;
cur = cur->xmlChildrenNode;
while(cur != NULL){
if((!xmlStrcmp(cur->name, (const xmlChar *)element))){
key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 5);
xmlFree(key);
r = xmlNodeGetContent(cur);
printf("GET XML URI DATA : %s\n", r);
xmlNodeSetContent(cur, (xmlChar *)parsingData);
}
cur = cur->next;
}
return;
}
int main(int argc, char **argv){
char *e;
e = "element1";
char *c;
c = "CHANGE URI DATA";
SetXmlData(d);
SetXmlParsingElement(e, c);
return (0);
}
위의 결과는 다음과 같다.
GET XML URI DATA : TEST1
GET XML URI DATA : TEST4
GET XML URI DATA : TEST7
GET XML URI DATA : TEST10
/*******CHANGED********/
<?xml version="1.0" encoding="UTF-8"?>
<A>
<B>
<C>
<element1>CHANGE URI DATA</element1>
<element2>TEST2</element2>
<element3>TEST3</element3></C>
<C>
<element1>CHANGE URI DATA</element1>
<element2>TEST5</element2>
<element3>TEST6</element3></C>
<C>
<element1>CHANGE URI DATA</element1>
<element2>TEST8</element2>
<element3>TEST9</element3></C>
<C>
<element1>CHANGE URI DATA</element1>
<element2>TEST11</element2>
<element3>TEST12</element3></C>
</B></A>
변경된 content는 상황에 맞게 스트링의 비교를 통해 비교 대상에 맞게 변경할 수도 있을 것이다.
참고 문헌
2. John Fleck, Libxml Tutorial, 2004.
3. Libxml API.