Wednesday, May 12, 2010

C에서 XML 파싱(libxml2 활용하기)

http://codezip.tistory.com/185


XMLSOFT 사이트
샘플코드 및 API가 잘 나와 있다.

다운받기

버전은 편한 대로 다운 받는다.


리눅스에서는 libxml2-2.6.32.tar.gz 이상없이 설치가 되고
현재 AIX 5.3에서 설치는 되었으나

실행시 라이브러리 참조를 못 하는 듯 하여 RPM를 다운 받아서 설치하였다.

AIX다운받기 설치하였음


./configure; make ; make install
로 쉽게 설치가 된다.

C 소스 작성과 동일하며 컴파일 시에 gcc -Wall -o bpng `xml2-config --cflags` bpng.c



  1. #
  2. #
  3. CC = gcc
  4. DEBUGFLAG = -g
  5. BASEDIR = /home/openbase/wonhong/xml/TEST
  6. CFLAGS = `xml2-config --cflags`
  7. LIBS = `xml2-config --libs`
  8. SRCS = bpng.c
  9. BINS = bpng
  10. $(BINS): $(SRCS)
  11. echo ""
  12. make -f Makefile OBJS=$@.o EXE=$@ build
  13. build: $(OBJS)
  14. $(CC) $(CFLAGS) $(LIBS) -o $(EXE) $(OBJS)





  1. /**
  2. bpng.c
  3. 메뉴얼에 있는 소스를 거의 그대로 사용
  4. XML의 내용만 읽는 기능만 있음
  5. Modified By 일퍼센트
  6. */
  7. #include
  8. #include
  9. #include
  10. #include
  11. #include
  12. #include
  13. void
  14. parseChannel (xmlDocPtr doc, xmlNodePtr cur) {
  15. xmlChar *key;
  16. cur = cur->xmlChildrenNode;
  17. while (cur != NULL) {
  18. if((!xmlStrcmp(cur->name, (const xmlChar *) "item"))) {
  19. parseItem(doc, cur);
  20. }
  21. else if((!xmlStrcmp(cur->name, (const xmlChar *) "title"))) {
  22. key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
  23. printf("BLOG NAME: %s\n", key);
  24. xmlFree(key);
  25. }
  26. else if((!xmlStrcmp(cur->name, (const xmlChar *) "link"))) {
  27. key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
  28. printf("MY BLOG LINK : %s\n", key);
  29. xmlFree(key);
  30. }
  31. cur = cur->next;
  32. }
  33. xmlFreeDoc(doc);
  34. return;
  35. }
  36. void
  37. parseItem(xmlDocPtr doc, xmlNodePtr cur){
  38. xmlChar *key;
  39. cur = cur->xmlChildrenNode;
  40. while (cur != NULL) {
  41. if((!xmlStrcmp(cur->name, (const xmlChar *) "title"))) {
  42. key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
  43. printf("제목: %s\n", key);
  44. xmlFree(key);
  45. }
  46. else if((!xmlStrcmp(cur->name, (const xmlChar *) "description"))) {
  47. key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
  48. printf("내용: %s\n", key);
  49. xmlFree(key);
  50. }
  51. else if((!xmlStrcmp(cur->name, (const xmlChar *) "author"))) {
  52. key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
  53. printf("글쓴이: %s\n", key);
  54. xmlFree(key);
  55. }
  56. else if((!xmlStrcmp(cur->name, (const xmlChar *) "pubDate"))) {
  57. key = xmlNodeListGetString(doc, cur->xmlChildrenNode,1);
  58. printf("등록일자: %s\n", key);
  59. }
  60. cur = cur->next;
  61. }
  62. return;
  63. }
  64. static void
  65. parseDoc(char *docname) {
  66. xmlDocPtr doc;
  67. xmlNodePtr cur;
  68. doc = xmlParseFile(docname);
  69. if (doc == NULL ) {
  70. fprintf(stderr,"Document not parsed successfully. \n");
  71. return;
  72. }
  73. cur = xmlDocGetRootElement(doc);
  74. if (cur == NULL) {
  75. fprintf(stderr,"empty document\n");
  76. xmlFreeDoc(doc);
  77. return;
  78. }
  79. if (xmlStrcmp(cur->name, (const xmlChar *) "rss")) {
  80. fprintf(stderr,"document of the wrong type, root node != rss");
  81. xmlFreeDoc(doc);
  82. return;
  83. }
  84. cur = cur->xmlChildrenNode; //channel
  85. while (cur != NULL) {
  86. if ((!xmlStrcmp(cur->name, (const xmlChar *) "channel"))){
  87. parseChannel (doc, cur);
  88. }
  89. cur = cur->next;
  90. }
  91. xmlFreeDoc(doc);
  92. return;
  93. }
  94. int
  95. main(int argc, char **argv) {
  96. char *docname;
  97. if (argc <= 1) {
  98. printf("Usage: %s docname\n", argv[0]);
  99. return(0);
  100. }
  101. docname = argv[1];
  102. parseDoc (docname);
  103. return (1);
  104. }
  105. string.h>




Rss.xml 파일은

RSS XML 동일한 형태를 가지며 한글은 제외시켜서 테스트하였다.

Libxml2 자체에서 EUC_KR이 인식이 안 되는 듯 하여 iconv 라이브러리 사용해야 할 듯

이거 나중에 올려야겠다.