Libxml2应用及详解
XML 可能是设计的最糟糕的格式,作为一种文件格式,它真的没有扩展能力,它通常是一个完全的灾难。2014年3月6日 -Linus Torvalds
XML 是胡扯。解析 XML 对人类来说是讨厌的,甚至对计算机来说也是一场灾难。没有理由让这个可怕垃圾存在。2014年3月6日。-Linus Torvalds
tips:
1.注意事项:想要表示孩子节点的孩子节点需要格式
node1 = cur->xmlChildrenNode;
node2 = node1->xmlChildrenNode->next;
2.问题
默认的Libxml2在写入XML文件时,都是将所有内容写成一行的,不便于文本查看。其实Libxml2是可以生成格式化的XML文件的。
解决办法
(1)打开开关:
xmlKeepBlanksDefault(0);
xmlIndentTreeOutput = 1;
(2)注意这个开关必须在XML节点加入到DOM树之前打开
即在我们需要在创建XML文件前或者加载XML文件前
(3)保存文件时使用xmlSaveFormatFile或xmlSaveFormatFileEnc或xmlSaveFormatFileTo,
并设置最后一个参数format=1
格式说明:
由于Libxml2是unix下的库,所以生成格式化XML只有换行符,没有回车符,且缩进用空格符而不是制表符。
3.xmlChar 类型是xml封装的char类型,但是最后需要xmlFree();
类型
- xmlChar 替代了插入,使用UTF-8编码的一截字符串,用完记得xmlFree()释放;
- xmlDoc 包含有解析文档建立的树结构, xmlNodePtr是指向这个结构的指针,根节点。
- xmlNodePtr 和 xmlNode 包含单一的结构,xmlNodePtr是指向这个结构的指针,被用于遍历文档。
部分函数说明
//定义文档指针
xmlDocPtr doc;
//获取树形结构
doc = xmlParseFile(file_name);
//以版本version = 1.0建立文档
doc = xmlNewDoc(BAD_CAST"1.0");
//以GB2312编码解析文档
doc = xmlReadFile(docname,"GB2312",XML_PARSE_RECOVER);
//将文档保存到文件中,按照utf-8编码格式保存
xmlSaveFormatFileEnc(phone_book_file, doc, "UTF-8", 1);
//将文档已默认方式存入文件
xmlSaveFile("test.xml", doc);
//将文档以某种编码/格式存入一个文件中
xmlSaveFormatFileEnc("-", doc, encoding, 1);
//释放创建文档时获取的内存
xmlFreeDoc(doc);
//定义结点指针
xmlNodePtr cur;
//创建节点
root_node = xmlNewNode(NULL, BAD_CAST"root");
//为创建的节点添加属性及值
xmlNewProp(root_node, "value", (xmlChar *)"123");
//将根节点添加到文档中
xmlDocSetRootElement(doc, root_node);
//获取文档根节点
cur = xmlDocGetRootElement(doc);
//获取节点的子节点
cur = cur->xmlChildrenNode;
xmlChar *key
//获取文本节点的文本,需用其子节点
key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
//释放xmlNodeListGetString为其返回的字符串分配的内存
xmlFree(key);
//为当前节点添加一个新的子元素文本结点,<keyword>123</keyword>,其中NULL是命名空间
xmlNewTextChild (cur, NULL, "keyword", "123");
//设置当前节点中间的内容
xmlNodeSetContent(cur, (xmlChar *) "1");
//获取属性值
xmlGetProp(cur, "value");
//设置当前结点的value属性的属性值为1000
xmlSetProp(curNode,BAD_(xmlChar *)"value", (xmlChar *) "1000");
//为root_node添加子结点node
xmlAddChild(root_node,node);
//为root_node添加子结点node
xmlNewChild(root_node, NULL, (xmlChar *) "node",(xmlChar *) szOut);
//将当前节点从文档中断链(unlink),这样本文档就不会再包含这个子节点
xmlUnlinkNode(curNode);
//手动删除断链节点的内存, 若没有xmlDelNode或者xmlRemoveNode,使用此函数
xmlFreeNode(curNode);
一些封装函数
- xmlMalloc 动态分配内存
- xmlFree 释放内存(xmlChar*)
- xmlStrcmp 字符串比较函数
- xml2-config –cflags 取得预处理和编译标志
- xml2-config –libs 取得链接标志
创建xml文件示例
编译命令:gcc creat_xml.c -o creat_xml -I/usr/include/libxml2/ -lxml2
#include <stdio.h>
#include <unistd.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/xmlmemory.h>
#include <assert.h>
#include <string.h>
/****************************************
*练习libxml库,创建xml文档
*如果xml文件存在,则添加一个新节点
*
*@author: wxlinux @date: 2017/10/29
* ***************************************/
#define DEFAULT_XML_FILE "汇总_t.xml"
static int create_phone_books(const char *filename)
{
xmlDocPtr doc = NULL;
xmlNodePtr root_node = NULL;
xmlNodePtr node_ = NULL;
xmlNodePtr node_1 = NULL;
xmlNodePtr node_2 = NULL;
xmlNodePtr node_3 = NULL;
// xmlKeepBlanksDefault(0);
// xmlIndentTreeOutput = 1;
//创建一个xml 文档
doc = xmlNewDoc(BAD_CAST"1.0");
if(doc == NULL)
{
printf("failed to new doc .\n");
goto FAILED;
}
//创建根节点
root_node = xmlNewNode(NULL, BAD_CAST"root");
if(root_node == NULL)
{
printf("failed to new root node.\n");
goto FAILED;
}
node_ = xmlNewNode(NULL, BAD_CAST"brand");
xmlNewProp(node_, "name", (xmlChar *)"DS");
node_1 = xmlNewNode(NULL, BAD_CAST"series");
xmlNewProp(node_1, "name", (xmlChar *)"DS5");
node_2 = xmlNewNode(NULL, BAD_CAST"style");
xmlNewProp(node_2, "name", (xmlChar *)"2014款");
node_3 = xmlNewNode(NULL, BAD_CAST"type");
xmlNewProp(node_3, "name", (xmlChar *)"轿车");
xmlDocSetRootElement(doc, root_node);
xmlAddChild(root_node, node_);
xmlAddChild(node_, node_1);
xmlAddChild(node_1, node_2);
xmlAddChild(node_2, node_3);
xmlSaveFormatFileEnc(filename, doc, "UTF-8", 1);
xmlFreeDoc(doc);
return 0;
FAILED:
if(doc)
{
xmlFreeDoc(doc);
}
return -1;
}
int main(int argc, char const *argv[])
{
char *xml_file = DEFAULT_XML_FILE;
create_phone_books(xml_file);
return 0;
}
解析xml文件