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

最近使用libxml2想做点东西,翻看一些example后还是有些疑问,去segmentfault问了下,感谢@pingjiang的热心解答,问题解决,记录如下

(一)如下是一个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标签,而里面的内容保留(我找的示例删除节点,里面的子节点也都没有了)。

完整的实现:

/**

 * 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;

}

示例使用的是如下XML文件:

<parent>

	<p>

		<a1>

		    <one>1</one>

		    <two>2</two>

		    <three>3</three>

		</a1>

		<a2>

		    <one>1</one>

		    <two>2</two>

		    <three>3</three>

		</a2>

	</p>

</parent>

结果:

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

代码还没仔细看,略看下,写的非常不错,真乃大神,看来得细细的啃一下libxml2的源码才行….
想要完成全部的XML处理还需自己多多的了解。

你可能感兴趣的:(xml)