Libxml2 学习

1、概要
libxml 是一个实现操作XML数据功能的开源C语言库。
2、windows下使用libxml
从 ftp://gd.tuwien.ac.at/pub/libxml/win32 下载 libxml2 iconv libz 将其放到某个目录下
配置VS 项目中添加头文件和 三个的都文件都需要
3、libxml使用
3.1 libxml 生成xml文件
主要通过函数 xmlNewDoc xmlNewNode xmlDocSetRootElement xmlNewTextChild xmlSaveFormatFileEnc 来实现
如下代码:
static int Test_New(char* szFile)
{
xmlDocPtr doc = NULL; //
xmlNodePtr rootNode = NULL;
xmlNodePtr node = NULL;
xmlNodePtr node1 = NULL;
doc = xmlNewDoc(BAD_CAST "1.0");
rootNode = xmlNewNode(NULL, BAD_CAST "root");
xmlDocSetRootElement(doc, rootNode);
node = xmlNewTextChild(rootNode, NULL, BAD_CAST "student", NULL);
xmlNewTextChild(node, NULL, BAD_CAST "name", BAD_CAST "zhangsan");
xmlNewTextChild(node, NULL, BAD_CAST "age", BAD_CAST "25");
xmlNewTextChild(node, NULL, BAD_CAST "sex", BAD_CAST "labc");
xmlNewChild(rootNode, NULL, BAD_CAST "node1", BAD_CAST "node1_test&");
xmlNewTextChild(rootNode, NULL, BAD_CAST "node2", BAD_CAST "node2_test&");
node = xmlNewTextChild(rootNode, NULL, BAD_CAST "node3", BAD_CAST "node3test");
xmlNewProp(node, BAD_CAST "color", BAD_CAST "0A");
xmlNewProp(node, BAD_CAST "attr", BAD_CAST "123");
node = xmlNewNode(NULL, BAD_CAST "node4");
node1 = xmlNewText(BAD_CAST "node4T<");
xmlAddChild(rootNode, node);
xmlAddChild(node, node1);
xmlSaveFormatFileEnc(szFile, doc, "UTF-8", 1);
xmlFreeDoc(doc);
return 0;
} 结果:

需要几点注意的地方:
(1)这里一定注意 xmlNewDoc 中固定为1.0 千万不要写其他的,否则会出错。之前写成了V1.0 被折腾了半天。
(2)xmlNewTextChild xmlNewChild 都可以创建子节点,但是他们还是有区别的,主要区别在于如果content中包含了& < > 等符号时,使用xmlNewChild 会出错,而 xmlNewTextChild 不会出错,这些保留符号会被自动转义,所以推荐使用 xmlNewTextChild
(3)一共提供了3中增加子节点的方法,注意 xmlNewText 也会转义特殊字符。
3.2 libxml 遍历xml文件的node
static int print_child(xmlNodePtr node)
{
if (node == NULL)
{
return 1;
}
if (node->type == XML_ELEMENT_NODE)
{
printf("<%s>\n", node->name);
}
for (node = node->children; node != NULL; node = node->next)
{
print_child(node);
}
return 0;
} static int Test_AnalysisFile(char* szFile)
{
xmlDocPtr doc = NULL; //文件指针
xmlNodePtr root = NULL;
doc = xmlReadFile(szFile, "UTF-8", XML_PARSE_NOBLANKS);
if (doc == NULL)
{
printf("xmlReadFile error %s\n", xmlGetLastError()->message);
return 1;
}
root = xmlDocGetRootElement(doc);
if (root == NULL)
{
xmlFreeDoc(doc);
return 0;
}
print_child(root);
xmlFreeDoc(doc);
return 0;
} 通过 xmlReadFile 函数来实现解析xml文件。
注意,这里node->children 也可以用宏定义 node->xmlChildrenNode
3.3 转换xml Node为字符串
static int Test_ToString(char* szFile)
{
xmlDocPtr doc = NULL; //文件指针
xmlNodePtr root = NULL;
xmlBufferPtr nodeBuffer;
char szBuf[1024] = { 0 };
doc = xmlReadFile(szFile, "UTF-8", XML_PARSE_NOBLANKS);
if (doc == NULL)
{
printf("xmlReadFile error %s\n", xmlGetLastError()->message);
return 1;
}
root = xmlDocGetRootElement(doc);
if (root == NULL)
{
xmlFreeDoc(doc);
return 0;
}
nodeBuffer = xmlBufferCreate();
xmlNodeDump(nodeBuffer, doc, root, 0, 1);
snprintf(szBuf, sizeof(szBuf), (char*)nodeBuffer->content);
xmlBufferFree(nodeBuffer);
xmlFreeDoc(doc);
printf("%s\n", szBuf);
return 0;
} 这里,通过xmlNodeDump来实现转换为字符串,结果如下

注意这里 xmlNodeDump(nodeBuffer, doc, root, 0, 1); 函数最后一个参数 如果为0的话则会去掉空白符如下
