首页 > 代码库 > libxml

libxml

  1 /**  2  * section: Tree  3  * synopsis: Navigates a tree to print element names  4  * purpose: Parse a file to a tree, use xmlDocGetRootElement() to  5  *          get the root element, then walk the document and print  6  *          all the element name in document order.  7  * usage: tree1 filename_or_URL  8  * test: tree1 test2.xml > tree1.tmp && diff tree1.tmp $(srcdir)/tree1.res  9  * author: Dodji Seketeli 10  * copy: see Copyright for the status of this software. 11  */ 12 #include <stdio.h> 13 #include <string.h> 14 #include <libxml/parser.h> 15 #include <libxml/tree.h> 16  17 /* 18  *To compile this file using gcc you can type 19  *  gcc `xml2-config --cflags --libs` -o tree1 tree1.c 20  *Run this program 21  *  ./tree1 test.xml 22  */ 23  24 static const char* LEVELS[] = {"", " ", "  ", "   ", "    ", "     ", "      ", "       " }; 25  26 static void printTree(xmlNode * a_node, int level); 27  28 /** 29  * print_element_names: 30  * @a_node: the initial xml node to consider. 31  * 32  * 打印所有兄弟节点和子节点的名字. 33  */ 34 static void print_element_names(xmlNode * a_node, const char* msg); 35  36  37 // 根据标签名称获取节点(可以实现更加复杂的逻辑,获取指定节点) 38 static xmlNode *getNode(xmlNode *rootNode, const char* tag, xmlNode **parentNode); 39  40 // 删除当前节点,但是保留子节点 41 static void removeNode(xmlNode *parentNode, xmlNode *nodeToDelete); 42  43 // 用一个父节点包装子节点 44 static void wrapWithNode(xmlNode *parentNode, xmlNode *node, xmlNode *newNode); 45  46 // 增加一个新节点 47 static void appendNewChildNode(xmlNode *parentNode, xmlNode *newNode); 48  49 /** 50  * print_element_names: 51  * @a_node: the initial xml node to consider. 52  * 53  * Prints the names of the all the xml elements 54  * that are siblings or children of a given xml node. 55  */ 56 static int test_removeNode(const char* filepath); 57  58 /** 59  * print_element_names: 60  * @a_node: the initial xml node to consider. 61  * 62  * Prints the names of the all the xml elements 63  * that are siblings or children of a given xml node. 64  */ 65 static int test_wrapWithNode(const char* filepath); 66  67 int main(int argc, char **argv) 68 { 69     if (argc != 2) { 70         printf("error: invalid arguments"); 71         return -1; 72     } 73  74    /* 75     * this initialize the library and check potential ABI mismatches 76     * between the version it was compiled for and the actual shared 77     * library used. 78     */ 79    LIBXML_TEST_VERSION 80  81     printf("test: removeNode:\n"); 82     test_removeNode(argv[1]); 83  84     printf("\n\ntest: wrapWithNode\n"); 85     test_wrapWithNode(argv[1]); 86  87    /* 88     *Free the global variables that may 89     *have been allocated by the parser. 90     */ 91    xmlCleanupParser(); 92  93    return 0; 94 } 95  96 void print_element_names(xmlNode * a_node, const char* msg) 97 { 98     xmlNode *cur_node = NULL; 99 100     if (msg != NULL && strlen(msg) > 0) {101         printf("print: %s\n", msg);102     }103 104     for (cur_node = a_node; cur_node; cur_node = cur_node->next) {105         if (cur_node->type == XML_ELEMENT_NODE) {106             printf("node type: Element, name: %s\n", cur_node->name);107         }108 109         print_element_names(cur_node->children, "");110     }111 }112 113 void printTree(xmlNode * a_node, int level)114 {115     xmlNode *cur_node = NULL;116 117     //printf("%s", LEVELS[level]);118 119     for (cur_node = a_node; cur_node; cur_node = cur_node->next) {120         if (cur_node->type == XML_ELEMENT_NODE) {121             printf("%s%s <%d>\n", LEVELS[level], cur_node->name, cur_node->type);122             printTree(cur_node->children, level + 1);123         } else {124             printf("%s#%s <%d>\n", LEVELS[level], cur_node->name, cur_node->type);125         }126     }127 }128 129 xmlNode *getNode(xmlNode *rootNode, const char* tag, xmlNode **parentNode) {130     xmlNode *cur = rootNode;131     if ((cur->type == XML_ELEMENT_NODE) && (!xmlStrcmp(cur->name, (const xmlChar *)tag))){132         *parentNode = NULL;133         return cur;134     }135 136     *parentNode = cur;137     cur = cur->xmlChildrenNode;138     while (cur != NULL) {139         if ((cur->type == XML_ELEMENT_NODE) && (!xmlStrcmp(cur->name, (const xmlChar *)tag))){140             return cur;141         }142 143         if (cur->type == XML_ELEMENT_NODE) {144             *parentNode = cur;145         }146         cur = cur->next;147     }148 149     return NULL;150 }151 152 // 删除当前节点,但是保留子节点153 void removeNode(xmlNode *parentNode, xmlNode *nodeToDelete) {154     if (nodeToDelete == NULL) {155         printf("error: nodeToDelete is null");156         return;157     }158 159     xmlNodePtr siblingNode = nodeToDelete->next;160 161     while (siblingNode != NULL) {162         if (siblingNode->type == XML_ELEMENT_NODE) {163             printf("debug: found sibling: %s\n", siblingNode->name);164             break;165         }166 167         siblingNode = siblingNode->next;168     }169 170     printf("debug: parentNode: %s, nodeToDelete: %s\n", parentNode->name, nodeToDelete->name);171     printTree(parentNode, 0);172 173     xmlNode *childrenNode = nodeToDelete->children;174     if (childrenNode == NULL) {175         printf("warn: childrenNode is null\n");176     }177     //xmlUnlinkNode(nodeToDelete->children);178 179     xmlNodePtr nextChildNode = NULL;180 181     while (childrenNode != NULL) {182         printf("debug: childrenNode: %s\n", childrenNode->name);183         nextChildNode = childrenNode->next;184         xmlUnlinkNode(childrenNode);185 186         if (siblingNode != NULL) {187             printf("debug: addPreSibling: %s, sibling is %s\n", childrenNode->name, siblingNode->name);188             xmlAddPrevSibling(siblingNode, nextChildNode);189         } else {190             printf("debug: addChild: %s, parent is %s\n", childrenNode->name, parentNode->name);191             printTree(childrenNode, 0);192             xmlAddChild(parentNode, childrenNode);193         }194 195         childrenNode = nextChildNode;196     }197 198     xmlUnlinkNode(nodeToDelete);    199     xmlFreeNode(nodeToDelete);200 }201 202 // 用一个父节点包装子节点203 void wrapWithNode(xmlNode *parentNode, xmlNode *node, xmlNode *newNode) {204     xmlUnlinkNode(node);205     xmlAddChild(newNode, node);206     xmlAddChild(parentNode, newNode);207 }208 209 // 增加一个新节点210 void appendNewChildNode(xmlNode *parentNode, xmlNode *newNode) {211     xmlAddChild(parentNode, newNode);212 }213 214 int test_removeNode(const char* filepath) {215     xmlDoc *doc = NULL;216     xmlNode *root_element = NULL;217     xmlNode *parentNode = NULL;218     xmlNode *curNode = NULL;219 220     /*parse the file and get the DOM */221     doc = xmlReadFile(filepath, NULL, 0);222 223     if (doc == NULL) {224         printf("error: could not parse file %s\n", filepath);225     }226 227     /*Get the root element node */228     root_element = xmlDocGetRootElement(doc);229 230     // 删除节点,但是保留子节点231     curNode = getNode(root_element, "p", &parentNode);232     if (curNode == NULL) {233         printf("error: p node is not found");234         return -1;235     }236     if (parentNode == NULL) {237         // 根节点只能有一个子节点,这里就不处理了238         printf("error: This is root node, should treat specially. root node should have only one node");239         return -1;240     }241     removeNode(parentNode, curNode);242 243 244     // 重新获取跟节点,应该是main了245     root_element = xmlDocGetRootElement(doc);246 247     print_element_names(root_element, "after delete");248 249     /*free the document */250     xmlFreeDoc(doc);251     return 0;252 }253 254 int test_wrapWithNode(const char* filepath) {255     xmlDoc *doc = NULL;256     xmlNode *root_element = NULL;257     xmlNode *newNode = NULL;258 259     /*parse the file and get the DOM */260     doc = xmlReadFile(filepath, NULL, 0);261 262     if (doc == NULL) {263         printf("error: could not parse file %s\n", filepath);264     }265 266     /*Get the root element node */267     root_element = xmlDocGetRootElement(doc);268 269     // 增加一个父节点,根节点需要特殊处理270     xmlUnlinkNode(root_element);271     newNode = xmlNewNode(NULL, BAD_CAST "main");272     xmlAddChild(newNode, root_element);273     xmlDocSetRootElement(doc, newNode);274     // 重新获取跟节点,应该是main了275     root_element = xmlDocGetRootElement(doc);276 277     print_element_names(root_element, "after wrap");278 279     /*free the document */280     xmlFreeDoc(doc);281 282     return 0;283 }

https://segmentfault.com/q/1010000000581732

libxml