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处理还需自己多多的了解。
C语言两个libxml2库使用的问题的更多相关文章
- C++的XML编程经验――LIBXML2库使用指南[转]
C++的XML编程经验――LIBXML2库使用指南 写这篇文章的原因有如下几点:1)C++标准库中没有操作XML的方法,用C++操作XML文件必须熟悉一种函数库,LIBXML2是其中一种很优秀的XML ...
- C++的XML编程经验――LIBXML2库使用指南
C++的XML编程经验――LIBXML2库使用指南 写这篇文章的原因有如下几点:1)C++标准库中没有操作XML的方法,用C++操作XML文件必须熟悉一种函数库,LIBXML2是其中一种很优秀的XML ...
- 分享:写了一个 java 调用 C语言 开发的动态库的范例
分享:写了一个 java 调用 C语言 开发的动态库的范例 cfunction.h 代码#pragma once#ifdef __cplusplusextern "C" {#e ...
- c++ 11开始语言本身和标准库支持并发编程
c++ 11开始语言本身和标准库支持并发编程,意味着真正要到编译器从语言和标准库层面开始稳定,估计得到17标准出来.14稳定之后的事情了,根据历史经验,新特性的引入到稳定被广泛采用至少要一个大版本的跨 ...
- 【Go语言绘图】gg 库的基本使用
最近接了个比较大的需求,需要做很多图片处理的事情,比如图片的旋转裁截拼接,各种渐变处理,文字排列,一开始光是想想就头疼.但没有办法,既然已经需求已经到手上了,那就得把它做好才行,于是便开始被迫营业,无 ...
- iOS解决两个静态库的冲突 duplicate symbol
http://blog.163.com/023_dns/blog/static/118727366201391544630380/ 场景: 解决TencentOpenAPI.framework与Zba ...
- Python3.x(windows系统)安装libxml2库
Python3.x(windows系统)安装libxml2库 cmd安装命令: pip install lxml 执行结果: 再执行命令: pip install virtualenv 执行结果:
- R语言两种方式求指定日期所在月的天数
R语言两种方式求指定日期所在月的天数 days_monthday<-function(date){ m<-format(date,format="%m& ...
- Go语言的标准net库使用
Go语言的标准net库使用 与大多数语言一样,Go的标准库是很全的,因为Go的出现本来就是为了网络通信的高并发实现,所以其相关的网络库封装得很简洁,也更加的易读.这里对使用到的api进行记录. net ...
随机推荐
- javascript中间preventDefault与stopPropagation角色介绍
preventDefault的作用是什么方法,它? 我们知道,例如,<a href="http://www.baidu.com">百度</a>,这是html ...
- ABP
ABP ABP之Javascript生成 2015-08-02 18:49 by Barlow Du, 319 阅读, 收藏, 编辑 还是服务在调试SimpleTaskSystem的AngularJs ...
- TCP/IP 网络编程(六)
流程模型: 线程模型: 线程的创建和运行流程 #include <pthread.h> int pthread_create(pthread_t * restrict thread, co ...
- (大数据工程师学习路径)第三步 Git Community Book----中级技能(下)
一.追踪分支 1.追踪分支 在Git中‘追踪分支’是用于联系本地分支和远程分支的. 如果你在’追踪分支'(Tracking Branches)上执行推送(push)或拉取(pull)时,它会自动推送( ...
- hdu4699 Editor 2013 多校训练第十场 D题 数列维护 splay | 线段树 | 栈!!!!!
题意:维护一个文本编辑,并且查询最大前缀和. 写了splay,wa了13次 过了之后觉着特傻逼.发现题解两个栈就可以了,光标前后维护两个栈,维护前面的栈的前缀和 和 最大前缀和. 哎,傻逼,太弱了,还 ...
- 【年终分享】彩票数据预测算法(一):离散型马尔可夫链模型实现【附C#代码】
原文:[年终分享]彩票数据预测算法(一):离散型马尔可夫链模型实现[附C#代码] 前言:彩票是一个坑,千万不要往里面跳.任何预测彩票的方法都不可能100%,都只能说比你盲目去买要多那么一些机会而已. ...
- robot framework-databaselibaray库使用(python)(转)
公司做项目用到了databaselibaray,刚开始使用时碰到了很多问题,网上也查阅了很多资料终于是可以用了,现在整理记录下来,有需要的同学可随意使用: 另,本文主要是databaselibaray ...
- XStream 用法汇总
XStream是一家Java对象和XML转换工具,很好很强大.它提供了所有的基本型.排列.收集和其他类型的支持,直接转换.因此XML在数据交换经常使用.对象序列化(和Java对象的序列 ...
- 【android】ImageView的src和background以及两者之间的神奇的差异
一.ImageView中XML属性src和background的差别: background会依据ImageView组件给定的长宽进行拉伸.而src就存放的是原图的大小,不会进行拉伸.src是图片内容 ...
- WinForm实现类似QQ停靠,显示隐藏过程添加特效效果
原文:WinForm实现类似QQ停靠,显示隐藏过程添加特效效果 这可能是个老题长谈的问题了,只是在项目中会用到这个效果,所以今天做个记录.大家见了别喷我.在项目中的需求是这样的. 打开程序,在屏幕的右 ...