通过libxml2的xpath解析xml

Xpath简介

XPath 是一门在 XML 文档中查找信息的语言, 基于XML的树状结构,提供在数据结构树中找寻节点的能力,用于在 XML 文档中通过元素和属性进行导航。XPath 使用路径表达式来选取 XML 文档中的节点或节点集。节点是通过沿着路径 (path) 或者步 (steps) 来选取的。

xpath表达式的基本格式

xpath通过"路径表达式"(Path Expression)来选择节点。在形式上,"路径表达式"与传统的文件系统非常类似。

斜杠(/)作为路径内部的分割符。

同一个节点有绝对路径和相对路径两种写法。

绝对路径(absolute path)必须用"/"起首,后面紧跟根节点,比如/step/step/...。

相对路径(relative path)则是除了绝对路径以外的其他写法,比如 step/step,也就是不使用"/"起首。

"."表示当前节点。

".."表示当前节点的父节点

nodename(节点名称):表示选择该节点的所有子节点

"/":表示选择根节点

"//":表示选择任意位置的某个节点

"@": 表示选择某个属性

xpath路径表达式可以参考https://www.cnblogs.com/sunny-bear/articles/5400441.html

使用Xpath常用到的函数

(1)xmlXPathNewContext函数

xmlXPathContextPtr  xmlXPathNewContext(xmlDocPtr doc)

创建一个新的上下文指针,释放时调用xmlXPathFreeContext

参数doc:    XML文档指针

返回:新的上下文指针

 

(2)xmlXPathRegisterNs函数

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

注册新的命名空间。如果@ns_uri为NULL,则取消注册命名空间

ctxt:      XPath上下文

prefix:  命名空间前缀不能为NULL或空字符串

ns_uri:  命名空间名称

返回:    成功时为0,出错时为-1

 

(3)xmlXPathEvalExpression函数

xmlXPathObjectPtr      xmlXPathEvalExpression(const xmlChar * str,xmlXPathContextPtr ctxt)

xmlXPathEval()的别名。在给定的上下文和XPath位置路径中找到符合要求的元素。

参数str:      XPath表达式

参数ctxt:     XPath上下文

返回:    查询结果指针。

解析xml的方法和实例

通过libxml2对xml进行解析的方法有两种,一种是比较简单的使用libxml2提供的接口来对xml一层一层的解析,缺点是层数嵌套比较多时效率不好。另一种方法是使用xpath,通过你给出路径,它可以快速的查找出目标节点。

那么下面来看看两种方法有什么不同。

第一种,递归调用接口一层一层的查找所要找的节点。

xmlNodePtr getXmlNodeByName(xmlNodePtr root,char *name)//通过节点名找到对应节点

{

    if(NULL ==root || NULL ==name)

    {

            return NULL;}

    xmlNodePtr pnode=xmlFirstElementChild(root);//返回根节点的子节点

    while(pnode!=NULL)

    {

        if(!strcmp(pnode->name,name))

            return pnode;



        xmlNodePtr pnode_1 = getXmlNodeByName(pnode,name);//递归查找下一层

        if(pnode_1!=NULL)

            return pnode_1;



        pnode = xmlNextElementSibling(pnode);//返回同一层的节点

   

    }

    return NULL;

}

 

调用方法:

cur = getXmlNodeByName(root,"Object");//从root中找到名字为Object的节点

 

第二种,通过路径直接找出所要查找的节点。

xmlXPathObjectPtr getNodeset(xmlDocPtr pdoc, const xmlChar *xpath)

{

    if(pdoc == NULL|| xpath == NULL)return NULL;

xmlXPathContextPtr context = NULL; //定义XPath上下文指针

xmlXPathObjectPtr result = NULL; //定义XPath结果指针



context = xmlXPathNewContext(pdoc);//用xml文档指针来初始化context指针

if(context!=NULL)

{

       result = xmlXPathEvalExpression(xpath, context);//计算xpath的查询结果,

//并存入result中

        if(result == NULL)return NULL;

        if (xmlXPathNodeSetIsEmpty(result->nodesetval))

        //使用result->nodesetval得到节点集合指针,其中包含了所有符合Xpath查询结果的节点

        {

            xmlXPathFreeObject(result);//使用释放Xpath对象指针;

            printf("nodeset is empty\n");

            return NULL;

        }

}

return NULL;

}

调用方法:

char tmpxpath[128];

sprintf(tmpxpath,"///AnalyticsModule[@Type='Face_Search_Engine']//SimpleItem[@Name='fastpicnum']",valuestring);

xmlXPathObjectPtr tmpxPathObj_ptr = getNodeset(RuleDoc,tmpxpath);//返回查询结果

if((tmpxPathObj_ptr)&&(tmpxPathObj_ptr->nodesetval))//判断查询结果和节点集合指针是否为空

{

    tmpxNode = tmpxPathObj_ptr->nodesetval->nodeTab[0];

    ······//处理

}

以上tmpxpath表示的路径含义是在根目录下任意位置找到AnalyticsModule且其属性Type='Face_Search_Engine’,然后在从AnalyticsModule下任意位置找到属性为Name='fastpicnum'的tt:SimpleItem。

查询到的节点会放到查询节点集合指针中,例如本例子中给的路径比较明确,只有一个,则一般都是节点集合的第一个元素,如果想找出某个路径下的全部子元素,可以使用下面的例子

xmlChar *xpath = BAD_CAST ("/producttype/product/*"); //xpath语句,路径为product的所有子元素

xmlXPathObjectPtr result = getNodeset(pdoc, xpath); //调用函数,查询XPath表达式,得到一个查询结果

int i;

 for (i = 0; i < result ->nodeNr; i++)

{

    tmpxNode = result ->nodeTab[i];//遍历

    ······//处理

}

更多libxml2接口可以参考libxml2官网

你可能感兴趣的:(xml)