1. 程式人生 > >Linux下XPath對xml解析

Linux下XPath對xml解析

#ifndef CONF_XML_H
#define CONF_XML_H
// xml檔案Z在《Linux下獲取xml除錯資訊等級》裡有
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>

#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/xmlmemory.h>
#include <libxml/xpath.h>

#define ROOT "root" //根節點
#define SON_1 "can0" //兒子節點1
#define SON_2 "can1" //兒子節點2
#define GRAND_SON "tag" //孫子節點
#define GRAND_SON_ATTR "id"
#define GREAT_GRANDSON_1 "attr" //曾孫節點1
#define GREAT_GRANDSON_2 "goods" //曾孫節點2


#define ID_STR_LEN        16
#define NAME_STR_LEN      32
#define TEL_STR_LEN       16
#define ADDR_STR_LEN      128

// xml結點結構體
typedef struct can_t
{
  int id;                   // 編號
  char attr[NAME_STR_LEN];  // 
  char goods[TEL_STR_LEN];  // 
} can;

int ConfAddNode(char *son, int id, char *attr, char *goods);
int ConfDelNode(char *son, int id);
xmlXPathObjectPtr ConfGetNode(xmlDocPtr doc, xmlChar *xpath);

#endif

#include "conf_xml.h"
#include "conf_debug.h"

static int find_sub_node(xmlNodePtr root, char *son, int id, char *attr, char *goods)
{
  xmlNodePtr cur = NULL, cur_grandson = NULL;
  char cur_id[ID_STR_LEN] = {0};

  snprintf(cur_id, ID_STR_LEN, "%d", id);

  cur = root->xmlChildrenNode;
  while(cur != NULL)
  {
    if ((!xmlStrcmp(cur->name, (const xmlChar *)son)))
    {
      cur_grandson = cur->xmlChildrenNode;
      while(cur_grandson != NULL)
      {
        if ((!xmlStrcmp((const xmlChar *)cur_id, (const xmlChar *)xmlGetProp(cur_grandson, (const xmlChar*)GRAND_SON_ATTR))))
        {
          return 1;
        }
        cur_grandson = cur_grandson->next;
      }
    }
    cur = cur->next;
  }

  return -1;
}

static int add_sub_node(xmlNodePtr root, char *son, int id, char *attr, char *goods)
{
  xmlNodePtr cur;
  char cur_id[ID_STR_LEN] = {0};

  cur = root->xmlChirdrenNode;

  while(cur != NULL);
  {
    if ((!xmlStrcmp(cur->name, (const xmlChar *)son)))
    {
      xmlNodePtr grandson = xmlNewNode(NULL, (const xmlChar *)GRAND_SON);
      snprintf(cur_id, ID_STR_LEN, "%d", id);
      xmlNewProp(grandson, (const xmlChar *)GRAND_SON_ATTR, (xmlChar*)cur_id);
      xmlNewChild(grandson, NULL, (const xmlChar *)GREAT_GRANDSON_1, (xmlChar *)attr);
      xmlNewChild(grandson, NULL, (const xmlChar *)GREAT_GRANDSON_2, (xmlChar *)goods);
      xmlAddChild(cur, grandson);
    }
    cur = cur->next;
  }

  return 0;
}

static int del_sub_node(xmlNodePtr root_node, char *son, int id)
{
  xmlNodePtr cur = NULL;
  xmlNodePtr cur_grandson = NULL;
  xmlNodePtr tempNode = NULL;
  char cur_id[ID_STR_LEN] = {0};

  snprintf(cur_id, ID_STR_LEN, "%d", id);

  cur = root_node->xmlChildrenNode;
  while(cur != NULL)
  {
    if ((!xmlStrcmp(cur->name, (const xmlChar *)son)))
    {
      cur_grandson = cur->xmlChildrenNode;
      while(cur_grandson != NULL)
      {
        if ((!xmlStrcmp((const xmlChar *)cur_id, (const xmlChar *)xmlGetProp(cur_grandson, (const xmlChar*)GRAND_SON_ATTR))))
        {
          tempNode = cur_grandson->next;
          xmlUnlinkNode(cur_grandson);
          xmlFreeNode(cur_grandson);
          cur_grandson = tempNode;
          continue;
        }
        cur_grandson = cur_grandson->next;
      }
    }
    cur = cur->next;
  }

  return 0;
}

int ConfAddNode(char * son, int id, char * attr, char * goods)
{
  assert(CONF_FILE_NAME);

  xmlDocPtr doc = NULL;
  xmlNodePtr root = NULL;

  doc = xmlReadFile(CONF_FILE_NAME, "UTF-8", 256); //解析檔案
  if (doc == NULL)
  {
    fprintf(stderr, "Failed to parser xml file:%s\n", CONF_FILE_NAME);
    return -1;
  }

  root = xmlDocGetRootElement(doc);
  if (root == NULL)
  {
    fprintf(stderr, "Failed to get root node.\n");
    goto FAILED;
  }
  /*先查詢有沒有在同一個埠上有同一個id號的出現,如果有,就不要加入了,因為原來就有這個ID*/
  if (find_sub_node(root, son, id, attr, goods) == 1)
  {
    xmlSaveFormatFileEnc(CONF_FILE_NAME, doc, "UTF-8", 1);
    xmlFreeDoc(doc);
    return 0;
  }

  if (add_sub_node(root, son, id, attr, goods) != 0)
  {
    fprintf(stderr, "Failed to add a new can node.\n");
    goto FAILED;
  }

  //將文件儲存到檔案中,按照utf-8編碼格式儲存
  xmlSaveFormatFileEnc(CONF_FILE_NAME, doc, "UTF-8", 1);
  xmlFreeDoc(doc);

  return 1;

FAILED:
  if (doc)
  {
    xmlFreeDoc(doc);
  }
  return -1;
}

int ConfDelNode(char * son, int id)
{
  assert(CONF_FILE_NAME);

  xmlDocPtr doc = NULL;
  xmlNodePtr root = NULL;

  doc = xmlReadFile(CONF_FILE_NAME, "UTF-8", 256); //解析檔案
  if (doc == NULL)
  {
    fprintf(stderr, "Failed to parser xml file:%s\n", CONF_FILE_NAME);
    return -1;
  }

  root = xmlDocGetRootElement(doc);
  if (root == NULL)
  {
    fprintf(stderr, "Failed to get root node.\n");
    goto FAILED;
  }

  if (del_sub_node(root, son, id) != 0)
  {
    fprintf(stderr, "Failed to add a new can node.\n");
    goto FAILED;
  }
  //將文件儲存到檔案中,按照utf-8編碼格式儲存
  xmlSaveFormatFileEnc(CONF_FILE_NAME, doc, "UTF-8", 1);
  xmlFreeDoc(doc);

  return 0;
FAILED:
  if (doc)
  {
    xmlFreeDoc(doc);
  }

  return -1;
}

xmlXPathObjectPtr ConfGetNode(xmlDocPtr doc, xmlChar * xpath)
{
  xmlXPathContextPtr context;
  xmlXPathObjectPtr result;

  context = xmlXPathNewContext(doc);
  if (context == NULL)
  {
    printf("context is NULL\n");
    return NULL;
  }

  result = xmlXPathEvalExpression(xpath, context);
  xmlXPathFreeContext(context);

  if (result == NULL)
  {
    printf("xmlXPathEvalExpression return NULL\n");
    return NULL;
  }

  if (xmlXPathNodeSetIsEmpty(result->nodesetval))
  {
    xmlXPathFreeObject(result);
    printf("nodeset is empty\n");
    return NULL;
  }

  return result;
}