1. 创建 XML 文档
(1) 相关函数有许多, 网上也有特别多的解释, 大家可以百度一下, 这里只是简单介绍一部分; 创建一个 XML 文档非常简单, 其流程如下:
用 xmlNewDoc 函数创建一个文档指针 doc.
用 xmlNewNode 函数创建一个节点指针 root_node.
用 xmlDocSetRootElement 将 root_node 设置为 doc 的根结点.
给 root_node 添加一系列的子节点, 并设置子节点的内容和属性.
用 xmlSaveFile 将 XML 文档存入文件 (用 xmlDocDumpFormatMemoryEnc 将 XML 存入内存).
用 xmlFreeDoc 关闭文档指针, 并清除本文档中所有节点动态申请的内存.
有多种方式可以添加子节点, 如可以用 xmlNewTextChild 直接添加一个文本子节点. 也可以先创建新节点, 然后用 xmlAddChild 将新节点加入到上层节点中.
注: xmlSaveFile 存入文件方便单独执行程序查看结果, 一般项目用用 xmlDocDumpFormatMemoryEnc 将 XML 存入内存!
(2) 创建 xml 文件举例
- #include <stdio.h>
- #include <libxml/parser.h>
- #include <libxml/tree.h>
- int main()
- {
- xmlChar *result = NULL;
- int size = 0;
- xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0"); // 定义文档和节点指针
- xmlNodePtr root_node = xmlNewNode(NULL,BAD_CAST "root");
- xmlDocSetRootElement(doc,root_node); // 设置根节点
- // 在根节点中直接创建节点
- xmlNewTextChild(root_node, NULL, BAD_CAST "newNode1", BAD_CAST "newNode1 content");
- xmlNewTextChild(root_node, NULL, BAD_CAST "newNode2", BAD_CAST "newNode2 content");
- xmlNewTextChild(root_node, NULL, BAD_CAST "newNode3", BAD_CAST "newNode3 content");
- // 创建一个节点, 设置其内容和属性, 然后加入根结点
- xmlNodePtr node = xmlNewNode(NULL,BAD_CAST "node2");
- xmlNodePtr content = xmlNewText(BAD_CAST "NODE CONTENT");
- xmlAddChild(root_node,node);
- xmlAddChild(node,content);
- xmlNewProp(node,BAD_CAST "attribute",BAD_CAST "yes");
- // 创建一个儿子和孙子节点
- node = xmlNewNode(NULL, BAD_CAST "son");
- xmlAddChild(root_node,node);
- xmlNodePtr grandson = xmlNewNode(NULL, BAD_CAST "grandson");
- xmlAddChild(node,grandson);
- //xmlAddChild(grandson, xmlNewText(BAD_CAST "This is a grandson node"));
- xmlNodePtr congson = xmlNewNode(NULL, BAD_CAST "congson");
- xmlAddChild(grandson,congson);
- // 存储 xml 文档
- //xmlKeepBlanksDefault(0);
- //xmlDocDumpFormatMemoryEnc(doc, &result, &size, "UTF-8", 1);
- int nRel = xmlSaveFile("CreateXml.xml",doc);
- if (nRel != -1)
- {
- printf("一个 xml 文档被创建, 写入 %d 个字节 \ n", nRel);
- }
- // 释放文档内节点动态申请的内存
- xmlFreeDoc(doc);
- return 1;
- }
CentOS 系统下面执行: gcc CreateXmlFile.c -o CreateXmlFile -I /usr/include/libxml2 -lxml2
执行./CreateXmlFile, 会生成一个 XML 文件 CreatedXml.xml.
2. 解析 XML 文档
(1)XML 解析流程
解析一个 XML 文档, 从中取出想要的信息, 例如节点中包含的文字, 或者某个节点的属性. 其流程如下:
用 xmlReadFile 函数读入一个文件, 并返回一个文档指针 doc.
用 xmlDocGetRootElement 函数得到根节点 curNode.
此时 curNode->xmlChildrenNode 就是根节点的首个儿子节点, 该儿子节点的兄弟节点可用 next 指针进行轮询.
轮询所有子节点, 找到所需的节点, 用 xmlNodeGetContent 取出其内容.
用 xmlHasProp 查找含有某个属性的节点, 属性列表指针 xmlAttrPtr 将指向该节点的属性列表.
取出该节点的属性, 用 xmlGetProp 取出其属性值.
xmlFreeDoc 函数关闭文档指针, 并清除本文档中所有节点动态申请的内存.
(2). 解析 XML 文件并获取属性示例
- #include <stdio.h>
- #include <libxml/parser.h>
- #include <libxml/tree.h>
- int main(int argc, char* argv[])
- {
- xmlDocPtr doc; // 定义解析文件指针
- xmlNodePtr curNode; // 定义结点指针
- xmlChar *szKey; // 临时字符串变量
- char *szDocName;
- if (argc <= 1) {
- printf("Usage: %s docname", argv[0]);
- return(0);
- }
- szDocName = argv[1];
- doc = xmlReadFile(szDocName,"GB2312",XML_PARSE_RECOVER);
- // 解析文件
- // 检查解析文档是否成功, 如果不成功, libxml 将报错并停止解析.
- // 一个常见错误是不适当的编码, XML 标准文档除了用 UTF-8 或 UTF-16 外还可用其它编码保存
- if (NULL == doc) {
- fprintf(stderr,"Document not parsed successfully.");
- return -1;
- }
- // 获取根节点
- curNode = xmlDocGetRootElement(doc);
- if (NULL == curNode) {
- fprintf(stderr,"empty document");
- xmlFreeDoc(doc);
- return -1;
- }
- // 确认根元素名字是否符合
- if (xmlStrcmp(curNode->name, BAD_CAST "root")) {
- fprintf(stderr,"document of the wrong type, root node != root");
- xmlFreeDoc(doc);
- return -1;
- }
- curNode = curNode->xmlChildrenNode;
- xmlNodePtr propNodePtr = curNode;
- while(curNode != NULL) {
- // 取出节点中的内容
- if ((!xmlStrcmp(curNode->name, (const xmlChar *) "newNode1"))) {
- szKey = xmlNodeGetContent(curNode);
- printf("newNode1: %s\n", szKey);
- xmlFree(szKey);
- }
- // 查找带有属性 attribute 的节点
- if (xmlHasProp(curNode,BAD_CAST "attribute")) {
- propNodePtr = curNode;
- }
- curNode = curNode->next;
- }
- // 查找属性
- xmlAttrPtr attrPtr = propNodePtr->properties;
- while (attrPtr != NULL) {
- if (!xmlStrcmp(attrPtr->name, BAD_CAST "attribute")) {
- xmlChar* szAttr = xmlGetProp(propNodePtr,BAD_CAST "attribute");
- printf("get attribute=%s\n", szAttr) ;
- xmlFree(szAttr);
- }
- attrPtr = attrPtr->next;
- }
- xmlFreeDoc(doc);
- return 0;
- }
编译: gcc ParseXmlFile.c -o ParseXmlFile -I /usr/include/libxml2 -lxml2
执行:./ParseXmlFile xxx.xml
3, 用 iconv 解决 XML 中字符集问题
libxml2 中默认的内码是 UTF-8, 所有使用 libxml2 进行处理的 xml 文件, 必须首先显式或者默认转换为 UTF-8 编码才能被处理.
要在 XML 中使用中文, 就必须能够在 UTF-8 和 GB2312 之间进行转换. libxml2 提供了默认的内码转换机制, 并且在 libxml2 的 Tutorial 中有一个例子, 事实证明这个例子并不很适合用来转换中文.
有些场合需要使用 iconv 来进行编码转换, libxml2 本身也是使用 iconv 进行编码转换的. iconv 是一个专门用来进行编码转换的库, 基本上支持目前所有常用的编码, 它是 glibc 库的一个部分.
本节其实和 libxml 没有太大关系, 可以把它简单看作是一个编码转换方面的专题. 下文提供了一个通用转码函数, 并在此基础上实现了两个转码封装函数, 即从 UTF-8 转换到 GB2312 的函数 u2g, 以及反向转换的函数 g2u. 其代码如下:
来源: https://www.cnblogs.com/liudw-0215/p/9455235.html