libxml的使用(4)--xpath搜索节点树

 

在libxml的tutorial中介绍了一种用关键字查找节点的方法,这种方法将使用打xpath系列API。由于我才刚刚接触libxml,所以我对xpath的认识也仅仅是在tutorial提供的功能之内了。废话少说,直接进入整体。

我们在操作xml文件是经常需要根据特定的条件查找一系列的节点,为了实现这样的功能,我们需要一个xmlXPathContextPtr和一个expression。我们调用xmlXPathEvalExpression函数来得到一个xmlXPathObjectPtr指针,这个指针包含了一个xmlNodeSetPtr,其中有一个变量nodeTab是我们所需要的节点数组。

 

[cpp] view plaincopyprint?
 
 
  1. xmlXPathObjectPtr ret = NULL;  
  2. xmlXPathContextPtr con = NULL;  
  3.   
  4. con = xmlXPathNewContext(doc);  
  5. ret = xmlXPathEvalExpression((xmlChar*)expr, con);  
  6. xmlXPathFreeContext(con);  

这样我们就得到了查询的结果了。expr是查询的条件,tutorial给的例子里,这个条件是“//keyword”,表示找出所有名称为keyword的节点。至于其他的条件,我现在还不知道。

 

得到了查询的结果,我们就要对结果进行处理。

 

[cpp] view plaincopyprint?
 
 
  1. if(NULL == ret) {  
  2.     fprintf(stderr, "eval func error\n");  
  3.     exit(1);  
  4. }  
  5. if(xmlXPathNodeSetIsEmpty(ret->nodesetval)){  
  6.     fprintf(stderr, "node set empty\n");  
  7.     xmlXPathFreeObject(ret);  
  8.     exit(1);  
  9. }  
  10. xmlNodeSetPtr nodeset = ret->nodesetval;  
  11. int i;  
  12. for(i = 0; i < nodeset->nodeNr; i ++) {  
  13.     //handle the node  
  14. }  
  15. xmlXPathFreeObject(ret);  

 

下面是一个程序的实例。用于提取出网页中的链接:

web.html

 

[html] view plaincopyprint?
 
 
  1. <html>  
  2.     <head>  
  3.         <title>web</title>  
  4.     </head>  
  5.     <body>  
  6.         <href="www.baidu.com">baidu</a>  
  7.         <href="www.google.com">Google</a>  
  8.     </body>  
  9. </html>  

 

link.c

 

[cpp] view plaincopyprint?
 
 
  1. #include <stdio.h>  
  2. #include <string.h>  
  3. #include <stdlib.h>  
  4. #include <libxml/parser.h>  
  5. #include <libxml/xpath.h>  
  6.   
  7. static xmlDocPtr  
  8. getDocPtr(char* docname) {  
  9.     xmlDocPtr doc = NULL;  
  10.     xmlKeepBlanksDefault(0);  
  11.   
  12.     doc = xmlParseFile(docname);  
  13.     if(NULL == doc) {  
  14.         fprintf(stderr, "document cannot be parsed!\n");  
  15.         exit(1);  
  16.     }  
  17.     return doc;  
  18. }  
  19.   
  20. static xmlXPathObjectPtr  
  21. getXPathObjectPtr(xmlDocPtr doc, xmlChar* xpath_exp) {  
  22.     xmlXPathObjectPtr result;  
  23.     xmlXPathContextPtr context;  
  24.       
  25.     context = xmlXPathNewContext(doc);  
  26.     result = xmlXPathEvalExpression((const xmlChar*)xpath_exp, context);  
  27.     xmlXPathFreeContext(context);  
  28.   
  29.     if(NULL == result) {  
  30.         fprintf(stderr, "eval expression error!\n");  
  31.         return NULL;  
  32.     }  
  33.   
  34.     if(xmlXPathNodeSetIsEmpty(result->nodesetval)) {  
  35.         fprintf(stderr, "empty node set!\n");  
  36.         xmlXPathFreeObject(result);  
  37.         return NULL;  
  38.     }  
  39.     return result;  
  40. }  
  41.   
  42. int main() {  
  43.     char* docname = "web.html";  
  44.     xmlDocPtr doc = NULL;  
  45.     xmlXPathObjectPtr xpath_obj = NULL;  
  46.     xmlNodeSetPtr nodeset = NULL;  
  47.     xmlChar* xpath_exp = (xmlChar*)"//a";  
  48.     xmlChar* uri;  
  49.   
  50.     doc = getDocPtr(docname);  
  51.   
  52.     xpath_obj = getXPathObjectPtr(doc, xpath_exp);  
  53.   
  54.     if(NULL != xpath_obj) {  
  55.         nodeset = xpath_obj->nodesetval;  
  56.         int i = 0;  
  57.         for(i = 0; i < nodeset->nodeNr; i ++) {  
  58.             uri = xmlGetProp(nodeset->nodeTab[i],(const xmlChar*)"href");  
  59.             printf("link address:%s\n",uri);  
  60.             xmlFree(uri);  
  61.         }  
  62.         xmlXPathFreeObject(xpath_obj);  
  63.     }  
  64.     xmlFreeDoc(doc);  
  65.     xmlCleanupParser();  
  66.       
  67.     return 1;  
  68. }  

输出结果为:

 

 

[html] view plaincopyprint?
 
 
  1. link address:www.baidu.com  
  2. link address:www.google.com  

 

 
 
posted @ 2017-05-02 20:09  fire909090  阅读(2089)  评论(0编辑  收藏  举报