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

要解决这个问题,需要花点时间到官网好好学习一下libxml2的源代码,熟悉节点的遍历,插入和删除操作。

主要就是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

#include

#include

#include

/*

*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 \n", LEVELS[level], cur_node->name, cur_node->type);

printTree(cur_node->children, level + 1);

} else {

printf("%s#%s \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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用libxml2的xpath功能来修改节点的值。以下是一个示例代码: ```c #include <stdio.h> #include <libxml/parser.h> #include <libxml/xpath.h> int main(void) { xmlDocPtr doc; xmlXPathContextPtr xpathCtx; xmlXPathObjectPtr xpathObj; xmlNodePtr node; const xmlChar *xpathExpr = (const xmlChar *)"//book[author='Charles Dickens']/title"; const xmlChar *new_value = (const xmlChar *)"A Tale of Two Cities"; // Load the XML document doc = xmlReadFile("books.xml", NULL, 0); if (doc == NULL) { fprintf(stderr, "Failed to parse document\n"); return 1; } // Create an XPath context xpathCtx = xmlXPathNewContext(doc); if (xpathCtx == NULL) { fprintf(stderr, "Failed to create XPath context\n"); xmlFreeDoc(doc); return 1; } // Evaluate the XPath expression xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx); if (xpathObj == NULL) { fprintf(stderr, "Failed to evaluate XPath expression\n"); xmlXPathFreeContext(xpathCtx); xmlFreeDoc(doc); return 1; } // Get the first matching node node = xpathObj->nodesetval->nodeTab[0]; // Change the node value xmlNodeSetContent(node, new_value); // Save the modified document if (xmlSaveFile("books.xml", doc) < 0) { fprintf(stderr, "Failed to save document\n"); xmlXPathFreeObject(xpathObj); xmlXPathFreeContext(xpathCtx); xmlFreeDoc(doc); return 1; } // Cleanup xmlXPathFreeObject(xpathObj); xmlXPathFreeContext(xpathCtx); xmlFreeDoc(doc); return 0; } ``` 这个示例代码会在books.xml文件中找到作者为Charles Dickens的书的标题,并将其修改为"A Tale of Two Cities"。要使用此代码,需要将books.xml文件放在与代码相同的目录下,并且需要链接libxml2

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值