[Linux C]利用libxml2解析xml文件

为了解析xml,可以使用Linux下默认安装的libxml2。

/*a.c功能:利用libxml2解析xml文件
*/#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libgen.h>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <libxml/xpath.h>int GetCurFilePath(char *lpOut)		// get full path of the executable file
{char chPath[BUFSIZ] = {0};int nRetVal = readlink("/proc/self/exe", chPath, sizeof(chPath)); // get full path of the current-executable fileif(nRetVal < 0){strcpy(lpOut, ".");return -1;}else{strcpy(lpOut, chPath);return 0;}
}int GetCurDir(char *lpOut)									// get directory-path of current executable-file
{char	chPath[BUFSIZ] = { 0 };if( GetCurFilePath(chPath) < 0 )return - 1;dirname(chPath);										// dirname will change value of "chPath"(contain result)strcpy(lpOut, chPath);									// copy result to out-paramreturn 0;
}xmlDocPtr getdoc(char *docname)							// 根据文件名得到文档指针
{xmlDocPtr doc;doc = xmlParseFile(docname);if(doc == NULL){fprintf(stderr, "Document not parsed successfully.\n");return NULL;}return doc;
}// 在文档doc中解析xpath表达式,返回结果集指针
xmlXPathObjectPtr getnodeset(xmlDocPtr doc, xmlChar *xpath)
{xmlXPathContextPtr context;xmlXPathObjectPtr result;context = xmlXPathNewContext(doc);if(context == NULL){printf("Error in xmlXPathNewContent\n");return NULL;}result = xmlXPathEvalExpression(xpath, context);		// 在context中解析表达式xpathxmlXPathFreeContext(context);							// 释放contextif(result == NULL){printf("Error in xmlXPathEvalExpression\n");return NULL;}if(xmlXPathNodeSetIsEmpty(result->nodesetval))			// 解析表达式的结果集为空{xmlXPathFreeObject(result);printf("No result\n");return NULL;}return result;
}// 解析xmlPath路径的结点
void testReadXmlDoc(char *filepath, char *xmlPath)
{xmlDocPtr doc = getdoc(filepath);if(NULL == doc)return ;xmlChar *xpath = (xmlChar*) xmlPath;xmlXPathObjectPtr result = getnodeset(doc, xpath);			// 获取结果集if(result){xmlNodeSetPtr nodeset = result->nodesetval;xmlChar *name, *value;printf("nodeset->nodeNr = %d\n", nodeset->nodeNr);		// 打印结果集中结点个数for(int i = 0; i < nodeset->nodeNr; i++){xmlNodePtr cur = nodeset->nodeTab[i];				// productsprintf("cur->name = %s\n", cur->name);cur = cur->xmlChildrenNode;while(cur){if(xmlStrcmp(cur->name, (const xmlChar*) "text"))		// cur->name不为"text"{printf("cur->name = %s\t", cur->name);name = xmlGetProp(cur, (const xmlChar*) "name");	// 获取属性值value = xmlGetProp(cur, (const xmlChar*) "value");printf("name = %s, value = %s\n", name, value);xmlFree(name);xmlFree(value);}cur = cur->next;}printf("\n");}xmlXPathFreeObject(result);}xmlFreeDoc(doc);xmlCleanupParser();
}int main(void)
{char curDir[100] = {0};char docname[100] = {0};GetCurDir(curDir);strcpy(docname, curDir);strcat(docname, "/dprod.xml");testReadXmlDoc(docname, "/allproducts/products");return EXIT_SUCCESS;
}

makefile文件:

CC=gcc
CFLAGS=
BIN=a
INC=/usr/include/libxml2$(BIN): $(BIN).c$(CC) $(CFLAGS) -o $(BIN) $(BIN).c -I$(INC) -lxml2 -std=c99clean:rm -f *.o $(BIN)

xml文件(dprod.xml)内容:

<?xml version="1.0"?>
<allproducts><products><product name="name11" value="value11" /><product name="name12" value="value12" /><product name="name13" value="value13" /><product name="name14" value="value14" /></products><products><product name="name21" value="value21" /><product name="name22" value="value22" /><product name="name23" value="value23" /></products><products><product name="name31" value="value31" /><product name="name32" value="value32" /></products>
</allproducts>

编译运行:

[zcm@tmp #115]$make
gcc  -o a a.c -I/usr/include/libxml2 -lxml2 -std=c99
a.c: 在函数‘GetCurFilePath’中:
a.c:18: 警告:隐式声明函数‘readlink’
[zcm@tmp #116]$./a
nodeset->nodeNr = 3
cur->name = products
cur->name = product	name = name11, value = value11
cur->name = product	name = name12, value = value12
cur->name = product	name = name13, value = value13
cur->name = product	name = name14, value = value14cur->name = products
cur->name = product	name = name21, value = value21
cur->name = product	name = name22, value = value22
cur->name = product	name = name23, value = value23cur->name = products
cur->name = product	name = name31, value = value31
cur->name = product	name = name32, value = value32[zcm@tmp #117]$


说明:对于编译中出现的“a.c:18: 警告:隐式声明函数‘readlink’”错误,实在不能明白。我查了下手册,这个函数在unistd.h中,而且我也已经#include了,为什么还会出现这个错误呢?

后来突然想到,可能是-std=c99的原因,将它改为-std=gnu99后,这个警告就没有了!


--------------------------------------------------------------------------------------------------------------------------------------------------

修改了xml文件和上面源码中的testReadXmlDoc()后,发现结果相当神奇,看来对libxml2的理解还是比较缺乏。

1. 修改xml文件内容:

<?xml version="1.0"?>
<allproducts><products>h1<product name="name11" value="value11" />h2<product name="name12" value="value12" />h3<product name="name13" value="value13" />h4<product name="name14" value="value14" />h5</products><products><product name="name21" value="value21" /><product name="name22" value="value22" /><product name="name23" value="value23" /></products><products><product name="name31" value="value31" />g1<product name="name32" value="value32" />
g2</products>
</allproducts>

2. 修改testReadXmlDoc()

// 解析xmlPath路径的结点
void testReadXmlDoc(char *filepath, char *xmlPath)
{xmlDocPtr doc = getdoc(filepath);if(NULL == doc)return ;xmlChar *xpath = (xmlChar*) xmlPath;xmlXPathObjectPtr result = getnodeset(doc, xpath);			// 获取结果集if(result){xmlNodeSetPtr nodeset = result->nodesetval;xmlChar *name, *value;printf("nodeset->nodeNr = %d\n", nodeset->nodeNr);		// 打印结果集中结点个数for(int i = 0; i < nodeset->nodeNr; i++){xmlNodePtr cur = nodeset->nodeTab[i];				// productsprintf("cur->name = %s\n", cur->name);cur = cur->xmlChildrenNode;int ctext = 0;while(cur){if(xmlStrcmp(cur->name, (const xmlChar*) "text"))		// cur->name不为"text"{printf("cur->name = %s\t", cur->name);name = xmlGetProp(cur, (const xmlChar*) "name");	// 获取属性值value = xmlGetProp(cur, (const xmlChar*) "value");printf("name = %s, value = %s\n", name, value);xmlFree(name);xmlFree(value);}else{ctext++;xmlChar *v = xmlNodeListGetString(doc, cur, 1);printf("cur->content = [%s], v = [%s]", cur->content, v);	// cur->content获取cur的内容xmlFree(v);}cur = cur->next;}printf("ctext = %d\n", ctext);printf("\n");}xmlXPathFreeObject(result);}xmlFreeDoc(doc);xmlCleanupParser();
}


运行结果:

[zcm@tmp #168]$make
gcc  -o a a.c -I/usr/include/libxml2 -lxml2 -std=gnu99
[zcm@tmp #169]$./a
nodeset->nodeNr = 3
cur->name = products
cur->content = [h1], v = [h1h2h3h4h5]cur->name = product	name = name11, value = value11
cur->content = [h2], v = [h2h3h4h5]cur->name = product	name = name12, value = value12
cur->content = [h3], v = [h3h4h5]cur->name = product	name = name13, value = value13
cur->content = [h4], v = [h4h5]cur->name = product	name = name14, value = value14
cur->content = [h5], v = [h5]ctext = 5cur->name = products
cur->content = [], v = []cur->name = product	name = name21, value = value21
cur->content = [], v = []cur->name = product	name = name22, value = value22
cur->content = [], v = []cur->name = product	name = name23, value = value23
cur->content = [], v = []ctext = 4cur->name = products
cur->content = [], v = [g1g2]cur->name = product	name = name31, value = value31
cur->content = [g1], v = [g1g2]cur->name = product	name = name32, value = value32
cur->content = [
g2], v = [
g2]ctext = 3[zcm@tmp #170]$

由此可见,一般情况下,我们用的比较多的可能会是cur->content这个东西了!


补充:

在网上看到一个人的写法,可以在解析xml文件时,直接忽略掉结点之间的无效空白。对于本文,就是将:

doc = xmlParseFile(docname); --->修改为:doc = xmlParseFile(docname, "UTF-8", XML_PARSE_NOBLANKS);  // 第3个参数是关键



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/406131.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

nginx: [error] open() “/usr/local/var/run/nginx.pid“ failed (2: No such file or directory)

nginx: [error] open() “/usr/local/var/run/nginx.pid” failed (2: No such file or directory)

Delphi XE7 Update1修正列表

Delphi XE7 Update1修正列表 官方下载地址&#xff1a;http://altd.embarcadero.com/download/radstudio/xe7/delphicbuilder_xe7_upd1_win.isobug修正列表&#xff1a;http://edn.embarcadero.com/article/44156更新内容&#xff1a;http://docwiki.embarcadero.com/RADStudio…

【转】C# split 几种使用方法

第一种方法&#xff1a; string s "abcdeabcdeabcde"; string[] sArray s.Split(c); foreach (string i in sArray) Console.WriteLine(i.ToString()); Console.ReadKey();输出下面的结果:abdeabdeabd…

泛型类java_Java泛型 - 通用类( Generic Classes)

Java泛型 - 通用类( Generic Classes)泛型类声明看起来像非泛型类声明&#xff0c;除了类名后跟一个类型参数部分。泛型类的类型参数部分可以有一个或多个用逗号分隔的类型参数。 这些类称为参数化类或参数化类型&#xff0c;因为它们接受一个或多个参数。语法 (Syntax)public …

漫谈经典排序算法:一、从简单选择排序到堆排序的深度解析

From: http://blog.csdn.net/touch_2011/article/details/6767673 1、序言 这是《漫谈经典排序算法系列》第一篇&#xff0c;该篇从最简单的选择排序算法谈起&#xff0c;由浅入深的详细解析两种选择排序算法的过程及性能比较。逐步揭露选择排序的本质及其基本思想。 各种排序算…

Ant Design Vue 限制数字输入框只能输入大于等于0的整数

Ant Design Vue 限制数字输入框只能输入大于等于0的整数

ajax三级联动+全国最新省市县数据

写个Ajax三级联动实例&#xff0c;用的最新的全国省市县mysql数据。这里只说一下思路&#xff0c;具体请看源码。首先看index.php&#xff0c;这是一个省份列表<?php $connmysql_connect("localhost","root",""); mysql_select_db("chi…

React开发(168):...dva调用不成功的原因

注意三对三对应关系 否则无法调用成功

java 序列化 protobuf_java序列化机制之protobuf(快速高效跨语言)

我们之前曾讲过java自带的一种序列化机制&#xff0c;但是这种机制效率太低&#xff0c;有很多缺点。因此也涌现出了很多优秀的系列化框架&#xff0c;比如说protobuf、protostuff、thrift、hession、kryo、avro、fst、msgpack等等。这篇文章我们就看一下第一个序列化框架proto…

Java 四舍五入

如果把float或者double进行强制转换的话&#xff0c;都是进行的截尾操作&#xff0c;例如 float b1 1.3f; float b2 1.7f; System.out.println((int)b1"---"(int)b2); 结果是&#xff1a;1---1 如果要进行四舍五入的话&#xff0c;采用java.lang.Math中的round方法…

使用js将驼峰命名法与-命名的切换

使用js将驼峰命名法与-命名的切换

深入react技术栈(2):JSX语法

JSX的由来 DOM元素 组件元素 JSX基本语法 XML基本语法 元素类型 、我们讲到两种不同的元素:DOM元素和组件元素 在JSX里面有对应 注释 元素属性 Boolean属性 展开属性 自定义属性 javascript属性表达式 属性值使用表达式 用{}表示 HTML转义 文章参考深入react学习技术栈

关于在n-1的数组中找到那个被减去的数及异或与位与

// 有1到N共 n-1个数&#xff0c;问少了哪个数 // 有序数组(如果是无序数组那么将a[i] 移动至 a[a[i]] 这样子就成功排序了) //其实可以采用byte数组的来做&#xff0c;感觉会更快 //当然&#xff0c;这个更多的是用在1-n 共n1个数&#xff0c;问多出来的那个数是多少&#xff…

linux内存映射函数mmap

From: http://hi.baidu.com/cchaha0227/blog/item/7bb7911f4299eb02314e157e.html Linux提供了内存映射函数mmap, 它把文件内容映射到一段内存上(准确说是虚拟内存上), 通过对这段内存的读取和修改, 实现对文件的读取和修改, 先来看一下mmap的函数声明: 头文件: <unistd.h…

用css改变input光标的3种方法

用css改变input光标的3种方法

鄙视和膜拜

在汉化的世界 流行两种风气 鄙视和膜拜 常常看GAL论坛都是 膜拜大大, BS 不敢明目张胆。但是字面上白地黑子很明显表示 出BS情绪 我今天谈谈 昨天和血色玲珑交流的心得 首先 汉化不值得膜拜的 F大就喷我了: 搞汉化&#xff0c;其实什么都不算&#xff0c;根本没什么了不起。 好…

java map 允许重复_java中key值可以重复的map:IdentityHashMap

在Java中&#xff0c;有一种key值可以重复的map&#xff0c;就是IdentityHashMap。在IdentityHashMap中&#xff0c;判断两个键值k1和 k2相等的条件是 k1 k2 。在正常的Map 实现(如 HashMap)中&#xff0c;当且仅当满足下列条件时才认为两个键 k1 和 k2 相等&#xff1a;(k1nu…

JS 获取图片的原始尺寸

JS 获取图片的原始尺寸