Linux环境下使用Libxml2库

使用XML技术可以方便的完成数据文件的存储及解析读取,其格式化、解析过程由XML引擎完成,在Windows平台上可使用MSXML引擎,在Linux环境下可使用libxml2库完成操作。本文简要整理了在Linux环境下使用libxml2进行XML操作的C语言编程方式,包括文件创建、读写操作。
  Libxml2库提供DOM、SAX操作接口,也实现了DTD、Scheme方式的验证,支持XPath语法查询,加上其稳定性及可移植性,满足了一般项目的要求,有关Libxml2具体介绍可参考【1】。

1. 环境初始化
  使用Libxml2库,应确保在编译环境中(尤其对于客户机编译安装的分发软件)需要相关头文件及链接库,则可以通过Libxml2预定义宏确认:

#include 
 
 
  
  
#include 
  
  
   
   
#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
        #include 
       
         #if !(defined(LIBXML_WRITER_ENABLED) && defined(LIBXML_OUTPUT_ENABLED) / && defined LIBXML_READER_ENABLED) #error "cannot use xml lib" #endif 
        
      
     
     
    
    
   
   
  
  
 
 

使用Libxml2进行XML文件解析,则初始化解析环境,使其分配相应资源、设定变量。在实验中,省略该步骤并未影响操作结果,但在内存检查中会出现警告,可能导致未预期结果。

int prj_xml_init()
{
    xmlInitParser();
    LIBXML_TEST_VERSION
    return 0;
}

2. 写入XML文件
  XML文件为树形组织结构,以惟一根元素开始,层次式记录各属性、元素等信息,例如下文件为描述一目录树结构:

 
 

 
 
 
  
  
  
   
   
 
  
  
 
  
  

 
 

Libxml2使用XML文件指针操作XML文件,使用XML节点指针操作节点,可使用xmlNewDoc()和xmlDocSetRootElement()创建,使用xmlSaveFileEnc保存,例如:

#define PRJ_XML_ENCODING "ISO-8859-1"   /* 编码方式   */
#define PRJ_XML_FILEPATH  "/home/prj/prjconf.xml" /* 文件路径   */
#define PRJ_XML_ROOT     "FOLDER_ROOT"  /* 根节点标签 */
static xmlDocPtr  pxmldoc = NULL; /*** XML数据文件文档实例 ***/
static xmlNodePtr pxmlroot = NULL; /*** XML数据文件根节点   ***/

int prj_xml_writefile()
{
  /*新建文件 */
  pxmldoc = xmlNewDoc(BAD_CAST XML_DEFAULT_VERSION);
  if (NULL == pxmldoc)
  {
      return -1;
  }
  /* 构造xml文件句柄 */
  pxmlroot = xmlNewDocNode(pxmldoc, NULL, BAD_CAST PRJ_XML_ROOT, NULL);
  if (NULL == pxmlroot)
  {
    /* 失败时清理资源 */
    xmlFreeDoc(pxmldoc);
    pxmldoc = NULL;
    return -1;
  }
  /* 构造xml根节点 */
  (void)xmlDocSetRootElement(pxmldoc, pxmlroot);
  /* 保存新XML数据文件 */
  (void)xmlSaveFileEnc(PRJ_XML_PATH, pxmldoc, PRJ_XML_ENCODING);
}

3. 写入节点信息
  在XML文件树中创建子节点并写入节点信息,需要指明该节点的标签及父节点,使用xmlNewChild()创建;增加、修改属性信息使用xmlNewProp()和xmlSetProp(),例如:

#define PRJ_XML_FOLDER " FOLDER"  /* Folder节点标签 */
#define PRJ_XML_FILE        "FILE"          /* File节点标签   */
int prj_xml_newfolder()  /* 增加Folder节点 */
{
  xmlNode *pnode = NULL;

  pnode = xmlNewChild(pxmlroot,NULL, BAD_CAST PRJ_XML_FOLDER, NULL);
  if (NULL == pnode)
  {
    return NULL;
  }
  /* 增加属性 */
  (void)xmlNewProp(pnode, BAD_CAST "name", BAD_CAST "");
  (void)xmlNewProp(pnode, BAD_CAST "attrib", BAD_CAST "");
  return pnode;
}

int prj_xml_setprop(xmlNode *pnode, const char *attrib, const char *value) /* 修改属性 */
{
  return xmlSetProp(pnode, BAD_CAST attrib, BAD_CAST value);
}

4. 读取节点信息
  Libxml2使用一个树型结构组织XML文件的全部信息,包括节点的子节点、属性等,则可以通过直接使用节点指针读取信息,但不是个通用方式。使用xmlReader和xmlWriter模块可完成大量读写操作,可参考【2】。
对于基本的的读取,可使用xmlGetProp()完成,它返回一个xmlChar类型的字符数组包含属性信息,在使用完成后手动释放资源,例如:

int prj_xml_readprop(xmlNode *pnode, const char *attrib) /* 读取属性 */
{
  xmlChar *strres = NULL;
  strres = xmlGetProp(pnode, BAD_CAST attrib);
  if (NULL == strres)
  {
    return -1;
  }
  /* 其他操作 */
  /* 清理资源 */
  xmlFree(strres);
  return 0;
}

5. 使用XPath查询节点集
  使用XPath语法可以表示特定的节点集,执行XPath语句则完成了查找特定节点集的功能。基本流程为:生成XPath查询字符串、初始化XPath查询环境、执行查询获得结果集、操作结果集、清理XPath查询环境。
  XPath语法有丰富的路径表达方式、运算符及运算函数,可以完成复杂的节点查询。例如:
查询某Folder节点pnode下的所有文件名以”File”开头的文件节点。使用GetNodePath()得到pnode的路径字符串,使用start-with函数查询。

  char expr[64]={0};    /* 存放XPath语句 */
  xmlChar *npath;
  npath = xmlGetNodePath(pnode); /* 得到pnode的路径字符串 */
  (void)snprintf(expr, 64, "%s/%s[starts-with(@path,'%s/')]",
              (const char *)npath, PRJ_XML_FILE, "File");
  xmlFree(npath);

又如查询名为”Folder2”的文件夹,但在Windows上名称对大小写不敏感,则可以使用lower-case()函数将节点属性转为小写再比较。对于Libxml2,暂未支持这个在xml2.0定义的函数,因此需要translat()函数代替,自然有性能的消耗:
FOLDER_ROOT/FOLDER[translate(@name, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')='Folder2']
  生成XPath语句后,则可进行查询得到查询结果集,集合可能含有0、1或多个元素,然后进行具体操作:

int prj_xml_xpath_evaluate(const xmlChar* expr, xmlNodePtr *ppnode)
{
  xmlXPathContextPtr pctx = NULL;
  xmlXPathObjectPtr  pobj = NULL;
  if (NULL == expr)
  {
      return -1;
  }
  pctx = xmlXPathNewContext(pxmldoc); /* 初始化XPath查询环境 */
  if (NULL == pctx)
  {
      return -1;
  }
  pobj = xmlXPathEvalExpression(BAD_CAST expr,pctx); /* 执行查询 */
  if (NULL == pobj)
  {
      xmlXPathFreeContext(pctx);
      return -1;
  }
  if (0 == pobj->nodesetval->nodeNr) /* 结果集为空 */
  {
    /* 其他操作 */
  }
  else
  {
    /* 其他操作 */
  }
  
  xmlXPathFreeObject(pobj);  /* 清理XPath查询环境 */
  xmlXPathFreeContext(pctx);
  return 0;
}

6.   环境清理
  在完成XML文件操作后,需进行资源清理。清理前保证修改信息写入文件,可使用上文提到xmlSaveFileEnc()完成。清理环境操作如:

 
 
int32 prj_xml_clear()
{
  if (NULL != pxmldoc)
  {
    /* 清理文档链表资源 */
   xmlFreeDoc(pxmldoc);
   pxmldoc = NULL;
   pxmlroot = NULL;
  }
  /* 通知xml解析结束 */
  xmlCleanupParser();
  return 0;
}

 以上是在Linux环境是使用Libxml2库完成XML操作的基本方式,完成复杂、具体需求的操作也可以通过参考资源信息进行实验完成。
  Stone&Ice
  From: http://blog.csdn.net/stoneandice
参考资源:
1. http://xmlsoft.org/ Libxml2官方网站
2. http://www.w3school.com.cn/x.asp W3school的XML参考手册

 

                
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值