반응형


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는 상황에 맞게 스트링의 비교를 통해 비교 대상에 맞게 변경할 수도 있을 것이다.

 


참고 문헌

 1. http://www.libxml.org

 2. John Fleck, Libxml Tutorial, 2004.

 3. Libxml API.

 

 

반응형
Posted by 공간사랑
,