C语言两个libxml2库使用的问题-问答-阿里云开发者社区-阿里云

开发者社区> 问答> 正文

C语言两个libxml2库使用的问题

a123456678 2016-06-06 18:27:38 1393

比如如下是一个XML文件,p为根结点

<p>
    <one>1</one>
    <two>2</two>
    <three>3</three>
</p>
我想在根节点之外再添加个标签如下:

<main>
    <p>
        <one>1</one>
        <two>2</two>
        <three>3</three>
    </p>
</main>
不知该用什么方法。还有就是有一个子结构如下

<p>
    <a1>    
        <one>1</one>
        <two>2</two>
        <three>3</three>
    </a1>
    <a2>    
        <one>1</one>
        <two>2</two>
        <three>3</three>
    </a2>
    ......
</p>
向去掉最外层的

<

p>标签,而里面的内容保留(我找的示例删除节点,里面的子节点也都没有了)。

这两种情况,该如何实现呢?

是不是有什么高级的用法我忽略或是还没看到,还是哪里有问题,请前辈指教。先谢谢啦

PS:第一个问题,我尝试先新建一个新的xml,先把把

生成,然后使用另一个树读入源文件,把读入的树根使用新建子节点的方法赋给新的xml,可是会报错。

XML C语言 数据格式
分享到
取消 提交回答
全部回答(1)
  • a123456678
    2019-07-17 19:29:14

    主要就是xmlNewNode创建节点,xmlAddChild增加子节点,xmlUnlinkNode和xmlFreeNode删除节点. 下面是解决这个问题的完整代码:

    /**
     * section: Tree
     * synopsis: Navigates a tree to print element names
     * purpose: Parse a file to a tree, use xmlDocGetRootElement() to
     *          get the root element, then walk the document and print
     *          all the element name in document order.
     * usage: tree1 filename_or_URL
     * test: tree1 test2.xml > tree1.tmp && diff tree1.tmp $(srcdir)/tree1.res
     * author: Dodji Seketeli
     * copy: see Copyright for the status of this software.
     */
    #include <stdio.h>
    #include <string.h>
    #include <libxml/parser.h>
    #include <libxml/tree.h>
    
    /*
     *To compile this file using gcc you can type
     *  gcc `xml2-config --cflags --libs` -o tree1 tree1.c
     *Run this program
     *  ./tree1 test.xml
     */
    
    static const char* LEVELS[] = {"", " ", "  ", "   ", "    ", "     ", "      ", "       " };
    
    static void printTree(xmlNode * a_node, int level);
    
    /**
     * print_element_names:
     * @a_node: the initial xml node to consider.
     *
     * 打印所有兄弟节点和子节点的名字.
     */
    static void print_element_names(xmlNode * a_node, const char* msg);
    
    
    // 根据标签名称获取节点(可以实现更加复杂的逻辑,获取指定节点)
    static xmlNode *getNode(xmlNode *rootNode, const char* tag, xmlNode **parentNode);
    
    // 删除当前节点,但是保留子节点
    static void removeNode(xmlNode *parentNode, xmlNode *nodeToDelete);
    
    // 用一个父节点包装子节点
    static void wrapWithNode(xmlNode *parentNode, xmlNode *node, xmlNode *newNode);
    
    // 增加一个新节点
    static void appendNewChildNode(xmlNode *parentNode, xmlNode *newNode);
    
    /**
     * print_element_names:
     * @a_node: the initial xml node to consider.
     *
     * Prints the names of the all the xml elements
     * that are siblings or children of a given xml node.
     */
    static int test_removeNode(const char* filepath);
    
    /**
     * print_element_names:
     * @a_node: the initial xml node to consider.
     *
     * Prints the names of the all the xml elements
     * that are siblings or children of a given xml node.
     */
    static int test_wrapWithNode(const char* filepath);
    
    int main(int argc, char **argv)
    {
        if (argc != 2) {
            printf("error: invalid arguments");
            return -1;
        }
    
       /*
        * this initialize the library and check potential ABI mismatches
        * between the version it was compiled for and the actual shared
        * library used.
        */
       LIBXML_TEST_VERSION
    
        printf("test: removeNode:\n");
        test_removeNode(argv[1]);
    
        printf("\n\ntest: wrapWithNode\n");
        test_wrapWithNode(argv[1]);
    
       /*
        *Free the global variables that may
        *have been allocated by the parser.
        */
       xmlCleanupParser();
    
       return 0;
    }
    
    void print_element_names(xmlNode * a_node, const char* msg)
    {
        xmlNode *cur_node = NULL;
    
        if (msg != NULL && strlen(msg) > 0) {
            printf("print: %s\n", msg);
        }
    
        for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
            if (cur_node->type == XML_ELEMENT_NODE) {
                printf("node type: Element, name: %s\n", cur_node->name);
            }
    
            print_element_names(cur_node->children, "");
        }
    }
    
    void printTree(xmlNode * a_node, int level)
    {
        xmlNode *cur_node = NULL;
    
        //printf("%s", LEVELS[level]);
    
        for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
            if (cur_node->type == XML_ELEMENT_NODE) {
                printf("%s%s <%d>\n", LEVELS[level], cur_node->name, cur_node->type);
                printTree(cur_node->children, level + 1);
            } else {
                printf("%s#%s <%d>\n", LEVELS[level], cur_node->name, cur_node->type);
            }
        }
    }
    
    xmlNode *getNode(xmlNode *rootNode, const char* tag, xmlNode **parentNode) {
        xmlNode *cur = rootNode;
        if ((cur->type == XML_ELEMENT_NODE) && (!xmlStrcmp(cur->name, (const xmlChar *)tag))){
            *parentNode = NULL;
            return cur;
        }
    
        *parentNode = cur;
        cur = cur->xmlChildrenNode;
        while (cur != NULL) {
            if ((cur->type == XML_ELEMENT_NODE) && (!xmlStrcmp(cur->name, (const xmlChar *)tag))){
                return cur;
            }
    
            if (cur->type == XML_ELEMENT_NODE) {
                *parentNode = cur;
            }
            cur = cur->next;
        }
    
        return NULL;
    }
    
    // 删除当前节点,但是保留子节点
    void removeNode(xmlNode *parentNode, xmlNode *nodeToDelete) {
        if (nodeToDelete == NULL) {
            printf("error: nodeToDelete is null");
            return;
        }
    
        xmlNodePtr siblingNode = nodeToDelete->next;
    
        while (siblingNode != NULL) {
            if (siblingNode->type == XML_ELEMENT_NODE) {
                printf("debug: found sibling: %s\n", siblingNode->name);
                break;
            }
    
            siblingNode = siblingNode->next;
        }
    
        printf("debug: parentNode: %s, nodeToDelete: %s\n", parentNode->name, nodeToDelete->name);
        printTree(parentNode, 0);
    
        xmlNode *childrenNode = nodeToDelete->children;
        if (childrenNode == NULL) {
            printf("warn: childrenNode is null\n");
        }
        //xmlUnlinkNode(nodeToDelete->children);
    
        xmlNodePtr nextChildNode = NULL;
    
        while (childrenNode != NULL) {
            printf("debug: childrenNode: %s\n", childrenNode->name);
            nextChildNode = childrenNode->next;
            xmlUnlinkNode(childrenNode);
    
            if (siblingNode != NULL) {
                printf("debug: addPreSibling: %s, sibling is %s\n", childrenNode->name, siblingNode->name);
                xmlAddPrevSibling(siblingNode, nextChildNode);
            } else {
                printf("debug: addChild: %s, parent is %s\n", childrenNode->name, parentNode->name);
                printTree(childrenNode, 0);
                xmlAddChild(parentNode, childrenNode);
            }
    
            childrenNode = nextChildNode;
        }
    
        xmlUnlinkNode(nodeToDelete);    
        xmlFreeNode(nodeToDelete);
    }
    
    // 用一个父节点包装子节点
    void wrapWithNode(xmlNode *parentNode, xmlNode *node, xmlNode *newNode) {
        xmlUnlinkNode(node);
        xmlAddChild(newNode, node);
        xmlAddChild(parentNode, newNode);
    }
    
    // 增加一个新节点
    void appendNewChildNode(xmlNode *parentNode, xmlNode *newNode) {
        xmlAddChild(parentNode, newNode);
    }
    
    int test_removeNode(const char* filepath) {
        xmlDoc *doc = NULL;
        xmlNode *root_element = NULL;
        xmlNode *parentNode = NULL;
        xmlNode *curNode = NULL;
    
        /*parse the file and get the DOM */
        doc = xmlReadFile(filepath, NULL, 0);
    
        if (doc == NULL) {
            printf("error: could not parse file %s\n", filepath);
        }
    
        /*Get the root element node */
        root_element = xmlDocGetRootElement(doc);
    
        // 删除节点,但是保留子节点
        curNode = getNode(root_element, "p", &parentNode);
        if (curNode == NULL) {
            printf("error: p node is not found");
            return -1;
        }
        if (parentNode == NULL) {
            // 根节点只能有一个子节点,这里就不处理了
            printf("error: This is root node, should treat specially. root node should have only one node");
            return -1;
        }
        removeNode(parentNode, curNode);
    
    
        // 重新获取跟节点,应该是main了
        root_element = xmlDocGetRootElement(doc);
    
        print_element_names(root_element, "after delete");
    
        /*free the document */
        xmlFreeDoc(doc);
        return 0;
    }
    
    int test_wrapWithNode(const char* filepath) {
        xmlDoc *doc = NULL;
        xmlNode *root_element = NULL;
        xmlNode *newNode = NULL;
    
        /*parse the file and get the DOM */
        doc = xmlReadFile(filepath, NULL, 0);
    
        if (doc == NULL) {
            printf("error: could not parse file %s\n", filepath);
        }
    
        /*Get the root element node */
        root_element = xmlDocGetRootElement(doc);
    
        // 增加一个父节点,根节点需要特殊处理
        xmlUnlinkNode(root_element);
        newNode = xmlNewNode(NULL, BAD_CAST "main");
        xmlAddChild(newNode, root_element);
        xmlDocSetRootElement(doc, newNode);
        // 重新获取跟节点,应该是main了
        root_element = xmlDocGetRootElement(doc);
    
        print_element_names(root_element, "after wrap");
    
        /*free the document */
        xmlFreeDoc(doc);
    
        return 0;
    }
    
    我测试的结果:
    
    全选复制放进笔记print: after delete **删除节点p后的节点树**
    node type: Element, name: parent
    node type: Element, name: a1
    node type: Element, name: one
    node type: Element, name: two
    node type: Element, name: three
    node type: Element, name: a2
    node type: Element, name: one
    node type: Element, name: two
    node type: Element, name: three
    
    
    test: wrapWithNode **增加一个main节点后的节点树**
    print: after wrap
    node type: Element, name: main
    node type: Element, name: parent
    node type: Element, name: p
    node type: Element, name: a1
    node type: Element, name: one
    node type: Element, name: two
    node type: Element, name: three
    node type: Element, name: a2
    node type: Element, name: one
    node type: Element, name: two
    node type: Element, name: three
    0 0
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

推荐文章
相似问题
推荐课程