您的位置:首页 > 运维架构 > Linux

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>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linux 职场 xpath