libxml2的Xpath使用心得
2011-06-23 11:14
1016 查看
看了libxml2官方网站上关于xpath的实例,还是不能很好的了解libxml是如何解析xpath并返回结果的。因为这些例子全部都是获取节点的名称,而我最终要使用的是直接通过xpath获得节点的属性值。
解析xpath前面的步骤和网站上的例子相同,首先先使用
doc = xmlParseFile(filename.c_str());
解析xml文件(我设置传递的文件名是string类型的),在用然后再用
xpathCtx = xmlXPathNewContext(doc);
获得xpath的上下文。解析xpath的时候,使用
xmlXPathObjectPtr xpathObj = xmlXPathexpression_r((const xmlChar*)(expr.c_str()), xpathCtx);
这样就会返回xpath对象的指针。
关键就是如何处理这个对象。从API menu中可以看到xmlXPathObject结构主要包含了对象类型和节点集。一般的例子上都是直接获得节点集指针,然后来操纵节点集结构中 的节点数组。但是xpath对象结构中的对象类型枚举是怎么用的呢?通过后来使用gdb进行单步调试,发现哪怕xpath返回结果是属性,该xpath对 象结构的类型还是节点集(XPATH_NODESET),尝试了很多的xpath表达式,直到最后使用了string()函数之后,其类型终于变成了字符串类型(XPATH_STRING),可以通过xpath对象的stringval变量获得字符串指针。也就是说只有使用了xpath函数之后,xmlXPathObjectPtr的类型才会变成其他的类型,否则都将是节点集。
那么,用xpath表达式获取属性值,该怎么拿到里面的字符串呢?继续跟踪结构,最终找到了最基本的一个结构:xmlNode。里面有xmlElementType这个枚举类型,查看了这个枚举类型之后才发现,原来libxml定义的节点,不光是xml的节点(XML_ELEMENT_NODE),还有XML_ATTRIBUTE_NODE、XML_TEXT_NODE、XML_CDATA_SECTION_NODE、XML_ENTITY_REF_NODE、XML_ENTITY_NODE、XML_PI_NODE等等,具体可以查看这里(http://www.xmlsoft.org/html/libxml-tree.html#xmlElementType)。如果xpath最后使用的是@来获取属性值,那么,返回的节点集里面的节点它的类型就是XML_ATTRIBUTE_NODE。
不过,libxml的xpath库提供了函数来获得xmlXPathObjectPtr指针所指向的对象其中包含的值。如使用xmlXPathCastToString函数,就可以将xmlXPathObjectPtr转换为字符串类型,如果xmlXPathObjectPtr不能转换,那么将会返回空字符串。不过API上说如果转换失败将返回NULL,不知道怎么才算失败,传递一个只包含节点集的xmlXPathObjectPtr给这个函数,它只返回了空串(非NULL)。
最后用cppunit对自己写好的类进行了单元测试,全部通过了。测试的调用如下(仅包含关于xpath的测试):
//测试获得属性
string ret = xml.xpath("//property[@name='driver']/@value");
CPPUNIT_ASSERT(ret == "mysql");
//测试获得节点的文本
ret = xml.xpath("//destination/text()");
CPPUNIT_ASSERT(ret == "database");
//测试获得节点
ret = xml.xpath("//property[@name='driver']");
CPPUNIT_ASSERT(ret == "");
//测试查找不存在的节点
ret = xml.xpath("//property[@name='virtual']");
CPPUNIT_ASSERT(ret == "");
//测试获得节点集
ret = xml.xpath("//property");
CPPUNIT_ASSERT(ret == "");
使用的测试xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<log>
<destination>database</destination>
<properties>
<property name="driver" value="mysql" />
<property name="host" value="localhost" />
<property name="database" value="test" />
<property name="username" value="babydragon" />
<property name="password" value="test" />
</properties>
</log>
解析xpath前面的步骤和网站上的例子相同,首先先使用
doc = xmlParseFile(filename.c_str());
解析xml文件(我设置传递的文件名是string类型的),在用然后再用
xpathCtx = xmlXPathNewContext(doc);
获得xpath的上下文。解析xpath的时候,使用
xmlXPathObjectPtr xpathObj = xmlXPathexpression_r((const xmlChar*)(expr.c_str()), xpathCtx);
这样就会返回xpath对象的指针。
关键就是如何处理这个对象。从API menu中可以看到xmlXPathObject结构主要包含了对象类型和节点集。一般的例子上都是直接获得节点集指针,然后来操纵节点集结构中 的节点数组。但是xpath对象结构中的对象类型枚举是怎么用的呢?通过后来使用gdb进行单步调试,发现哪怕xpath返回结果是属性,该xpath对 象结构的类型还是节点集(XPATH_NODESET),尝试了很多的xpath表达式,直到最后使用了string()函数之后,其类型终于变成了字符串类型(XPATH_STRING),可以通过xpath对象的stringval变量获得字符串指针。也就是说只有使用了xpath函数之后,xmlXPathObjectPtr的类型才会变成其他的类型,否则都将是节点集。
那么,用xpath表达式获取属性值,该怎么拿到里面的字符串呢?继续跟踪结构,最终找到了最基本的一个结构:xmlNode。里面有xmlElementType这个枚举类型,查看了这个枚举类型之后才发现,原来libxml定义的节点,不光是xml的节点(XML_ELEMENT_NODE),还有XML_ATTRIBUTE_NODE、XML_TEXT_NODE、XML_CDATA_SECTION_NODE、XML_ENTITY_REF_NODE、XML_ENTITY_NODE、XML_PI_NODE等等,具体可以查看这里(http://www.xmlsoft.org/html/libxml-tree.html#xmlElementType)。如果xpath最后使用的是@来获取属性值,那么,返回的节点集里面的节点它的类型就是XML_ATTRIBUTE_NODE。
不过,libxml的xpath库提供了函数来获得xmlXPathObjectPtr指针所指向的对象其中包含的值。如使用xmlXPathCastToString函数,就可以将xmlXPathObjectPtr转换为字符串类型,如果xmlXPathObjectPtr不能转换,那么将会返回空字符串。不过API上说如果转换失败将返回NULL,不知道怎么才算失败,传递一个只包含节点集的xmlXPathObjectPtr给这个函数,它只返回了空串(非NULL)。
最后用cppunit对自己写好的类进行了单元测试,全部通过了。测试的调用如下(仅包含关于xpath的测试):
//测试获得属性
string ret = xml.xpath("//property[@name='driver']/@value");
CPPUNIT_ASSERT(ret == "mysql");
//测试获得节点的文本
ret = xml.xpath("//destination/text()");
CPPUNIT_ASSERT(ret == "database");
//测试获得节点
ret = xml.xpath("//property[@name='driver']");
CPPUNIT_ASSERT(ret == "");
//测试查找不存在的节点
ret = xml.xpath("//property[@name='virtual']");
CPPUNIT_ASSERT(ret == "");
//测试获得节点集
ret = xml.xpath("//property");
CPPUNIT_ASSERT(ret == "");
使用的测试xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<log>
<destination>database</destination>
<properties>
<property name="driver" value="mysql" />
<property name="host" value="localhost" />
<property name="database" value="test" />
<property name="username" value="babydragon" />
<property name="password" value="test" />
</properties>
</log>
相关文章推荐
- XPath语法使用的一些心得
- [libxml2]_[XML处理]_[使用libxml2的xpath特性修改xml文件内容]
- [libxml2]_[XML处理]_[使用libxml2的xpath特性修改xml文件内容]
- [libxml2]_[XML处理]_[使用libxml2的xpath特性修改xml文件内容]
- XPath语法使用的一些心得
- Windows下安装libxml2并在Python中使用XPath
- Libxml2中使用xpath解析xml问题
- Windows下安装libxml2并在Python中使用XPath
- Java报表工具Finereport使用小心得
- [心得]使用ASPX输出XML应注意的问题
- TFS 使用心得
- 使用U盘启动安装操作系统的一些心得
- Log4delphi使用心得
- htc使用心得
- 关于fedora中ipv6使用的一些心得
- Silverlight游戏设计(Game Design):(十四)练习用游戏素材资源的获取及相关工具使用心得
- Android Studio使用心得
- DataTables 控件使用和心得 (1) - 入门
- Eclipse使用心得与技巧
- Web页面报错: Eval()、XPath() 和 Bind() 这类数据绑定方法只能在上下文中使用