文档章节

Windows环境下使用libxml2

P
 Polarix
发布于 2018/12/17 23:10
字数 990
阅读 8
收藏 0

最近有个需求,很简单,就是从一个XML文件中,删除掉一个节点。 根据以前的经验,轻车熟路的编译好libxml2库,写好xpath语句,执行程序,然后懵逼了……

const char* cszXPath = "/document//picture";  
pstXPathResult = xmlXPathEvalExpression(BAD_CAST cszXPath, pstCTX);

返回的竟然是空白结果,也就是说,没有找到节点。 经过反复确认,/document/item/richtext/par/picture这个节点确实存在在,XPath语句/document//picture也没有错误。一时之间,感觉无法下手,然后网上一查,发现了突破点!
网上大量的值资料都显示,在节点具备显式的命名空间时,如果用XPath检索,那么需要显式的表明命名空间,回头再看看xml文件:

<document xmlns="http://www.lotus.com/dxl" version="8.5" maintenanceversion="3.0" replicaid="492581A600324B45" form="MainTopic">

嗯,大写的xmlns,没跑了,就是它!
接下来上网再找找,看看怎么检索带命名空间的节点。
找了一大顿,结果比较有用的只有这样一段话。

使用libxml2的xpath进行节点查询时。在测试中十分正常。后来在应用中发现总是无法找到结果。返回结果数为空。
对比测试文件与系统生成xml文件发现关于xmlns属性变化引起异常。
当使用无prefix命名空间时,会引起此异常xmlns="http://www..com.cn/xxx.xsd"
百度N个网页后找到替代方案"//*[local-name()='UserTag'][@name=\'%s\']"
即在//*[local-name()='UserTag']中UserTag为节点名称@name=\'%s\'为属性name值

老实说,我道行浅薄,到现在也没看懂啥意思,倒是咬住了另一个关键字:perfix。然后我又上网找到了这么一段示例代码,贴到源程序里,看看效果:

const char* cszXPath = "/a:document//picture";  
pstXPathResult = xmlXPathEvalExpression(BAD_CAST cszXPath, pstCTX);

执行,看到了一条libxml库输出的错误消息:

XPath error : Undefined namespace prefix

出现了prefix,这个好眼熟啊,错误提示的内容是说prefix没有定义,嗯,我好像摸到点儿门路了……

然后接下来我找到了libxml2中的这个API!

XMLPUBFUN int XMLCALL xmlXPathRegisterNs (xmlXPathContextPtr ctxt,
						 const xmlChar *prefix,
						 const xmlChar *ns_uri);

我终于明白了,全明白了。

整理一下,答案应该是在这样的,libxml2正在使用xpath之前,需要创建context对象,如果节点带有命名空间(xmlns属性)那么在搜索前,就要向context对象指定命名空间,每一个命名空间对应XPath中的一个prefix。

所以,前文所述的问题,解决方案如下。

/* 示例文件 */
const char* cszFile = "../Simple.xml";
/* DOM对象 */
xmlDocPtr pstDOM;
/* Context对象 */
xmlXPathContextPtr pstContext;
/* XPath语句 */
const char* cszXPath = "/nodesns:document//nodesns:picture";
/* XPath搜索结果 */
xmlXPathObjectPtr pstXPathResult;

/* 打开文件 */
pstDOM = xmlParseFile(cszFileName);
/* 创建Context对象 */
pstContext = xmlXPathNewContext(pstDOM);
/* 重点1:向Context对象中注册namespace并声明perfix。*/
/* 第二个参数的“nodesns”就是perfix,它出现在XPath语句里,第三个参数中的字符串就是xml文件中,xmlns的真值。 */
/* 这样,XML中的namespace和XPath中的perfix的联系就建立起来了。 */
xmlXPathRegisterNs(pstContext, BAD_CAST "nodesns", BAD_CAST "http://www.lotus.com/dxl");
/* 搜索节点... */
pstXPathResult = xmlXPathEvalExpression(BAD_CAST cszXPath, pstContext);
/* 对搜索结果的处理,略。 */
......
/* 销毁搜索结果,释放资源 */
xmlXPathFreeObject(pstXPathResult);
/* 重点2:清理注册的perfix */
/* 由于一个xml中可能存在多个namespace,本次在一个namespace中搜索,下一次可能需要在另一个namespace中搜索, */
/* 所以,多次搜索动作如果想要正在同一个Context对象中完成的话,理论上,每次搜索完成后都要清理注册的perfix。 */
/* 新的搜索开始前重新注册新的perfix。 */
xmlXPathRegisteredNsCleanup(pstContext);
/* 销毁对象释放资源关闭文件不解释... */
xmlXPathFreeContext(pstContext);
xmlFreeDoc(pstDOM);

至此,问题解决。

© 著作权归作者所有

P

Polarix

粉丝 3
博文 4
码字总数 7151
作品 2
大连
程序员
私信 提问
Windows环境下libxml2库的使用小结

(1)--环境的搭建,下载与安装LIBXML2和ICONV Libxml2是一个C语言的XML程序库,可以简单方便的提供对XML文档的各种操作,并且支持XPATH查询,以及部分的支持XSLT转换等功能。Libxml2的下载地址...

moki_oschina
2014/08/19
154
0
Libxml2库的编译和使用

Libxml2库提供了C语言解析和构造xml文档的接口,为后台C语言处理程序和前台应用程序提供了一种通用的通迅方式。 本文以libxml2-2.6.30版本来说明Libxml2库的使用方法。 1. 编译库文件 libxml...

mickelfeng
2013/05/18
319
0
linux下使用libxml2库读写XML文件

一、安装libxml2库 在linux对XML文件进行增、删、改、查,需要使用库libxml2 这个库可以在地址:ftp.gnome.org/pub/GNOME/sources/libxml2/2.6/ 下载, 我下载的文件是libxml2-2.6.30.tar.gz...

北风其凉
2014/09/03
471
0
configure: error: xml2-config not found. Please ch

configure: error: xml2-config not found. Please check your libxml2 installation 参考文章:http://blog.csdn.net/anljf/article/details/6981247 configure: error: xml2-config not fo......

天下杰论
2014/06/16
62
0
configure: error: xml2-config not found. Please check your libxml2 installation

安装php时的报错 checking libxml2 install dir... no checking for xml2-config path... configure: error: xml2-config not found. Please check your libxml2 installation. 检查是否安装......

bengozhong
2018/10/19
54
0

没有更多内容

加载失败,请刷新页面

加载更多

Spring Boot WebFlux 增删改查完整实战 demo

03:WebFlux Web CRUD 实践 前言 上一篇基于功能性端点去创建一个简单服务,实现了 Hello 。这一篇用 Spring Boot WebFlux 的注解控制层技术创建一个 CRUD WebFlux 应用,让开发更方便。这里...

泥瓦匠BYSocket
23分钟前
5
0
从0开始学FreeRTOS-(列表与列表项)-3

FreeRTOS列表&列表项的源码解读 第一次看列表与列表项的时候,感觉很像是链表,虽然我自己的链表也不太会,但是就是感觉很像。 在FreeRTOS中,列表与列表项使用得非常多,是FreeRTOS的一个数...

杰杰1号
26分钟前
4
0
Java反射

Java 反射 反射是框架设计的灵魂(使用的前提条件:必须先得到代表的字节码的 Class,Class 类 用于表示.class 文件(字节码)) 一、反射的概述 定义:JAVA 反射机制是在运行状态中,对于任...

zzz1122334
53分钟前
4
0
聊聊nacos的LocalConfigInfoProcessor

序 本文主要研究一下nacos的LocalConfigInfoProcessor LocalConfigInfoProcessor nacos-1.1.3/client/src/main/java/com/alibaba/nacos/client/config/impl/LocalConfigInfoProcessor.java p......

go4it
昨天
7
0
前端技术之:webpack热模块替换(HMR)

第一步:安装HMR中间件: npm install --save-dev webpack-hot-middleware 第二步:webpack配置中引入webpack对象 const webpack = require('webpack’); 第三步:增加devServer配置项: ho......

popgis
昨天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部