/**
 * @file    xmltools.h
 * @brief   数据库XML文件解析接口
 *
 * @version $Revision: 1.1 $
 * @date    $Date: 2018/11/24 06:54:50 $
 * @author  $Author: lizhongming $
 * @state   $State: Exp $
 *
 */

 
#ifndef _XMLTOOLS_H
#define _XMLTOOLS_H

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "utf.h"

typedef int (*db_parser_handler)(char* buf,void* object,void* rdb);
typedef int (dbparser_fn_t)(char* buf,void* object,void* rdb);


/** Skip unused part of xml 
 *  set skip tag and the levels,
 *  when the end tag handler encounters the same depth , the 
 *  skipped element has ended and the flag  be cleared! 
 *  assuming {root}=1 ,skip flag and skip depth
 */
typedef struct xml_parse_skip_t  xml_parse_skip_t;
struct xml_parse_skip_t{
    int	   skip_flag;   /**< is skip                  */
    int    skip_depth;  /**< which level of the depth */
    int	   global_depth;/**< {root}=1                 */
};

#define XML_TOOLS_ATTR_AND			(1) //attr is and relation
#define XML_TOOLS_ATTR_OR			(2) //attr is or-relation

#define XMLTOOLS_MAX_PATH_LEN	  (10) //最大支持路径层数
#define XMLTOOLS_MAX_VALUE_LEN	  (64) //最大值字符表达长度
#define XMLTOOLS_MAX_TAG_LEN	  (32) //标签长度
#define XMLTOOLS_MAX_NAME		  XMLTOOLS_MAX_TAG_LEN
#define XMLTOOLS_MAX_ATTR_LEN	  (3) //max 3 attrs

typedef  char** elem_text ;
typedef struct path_session_t path_session_t;
typedef struct attr_pair attr_pair;

struct attr_pair{
	char name[XMLTOOLS_MAX_NAME];
	char value[XMLTOOLS_MAX_TAG_LEN];
};
typedef enum type_identifier_e type_identifier_e;
enum type_identifier_e{
	axis_child,
	axis_attribute,
	predicate
};
/** contains one seesion of xpath*/
struct path_session_t
{
	type_identifier_e type_identifier;
	char tag[XMLTOOLS_MAX_TAG_LEN];			 /**<   */
	attr_pair attrs[XMLTOOLS_MAX_ATTR_LEN];	 /**< 每个属性之间是与的关系  */
	//attr_pair * current;//current position of attr_pair ,used internal
	int	 level;			/**< desired level, root elem is 1*/
};

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @brief 通过一次遍历XML文件获取某一类型数据的全部属性值
 * @param filename XML文件名
 * @param path element路径
 * @param item element类型
 * @param output_data 该类element的数据缓冲区
 * @return 返回 APR_SUCCESS   - 成功
 *              APR_NOTFOUND  - element不存在
 *              APR_EBADF     - 文件错误
 */
APR_DECLARE(int) xml_db_attach(const char*  filename,const char* path,
                               const char* item, db_parser_handler pfn,void* output_data);

/**
 * @brief 获取XML文件里的单个element属性值
 * @param filename XML文件名
 * @param path element全路径
 * @param value 获取的element的属性值
 * @return 返回 APR_SUCCESS   - 成功
 *              APR_NOTFOUND  - element不存在
 *              APR_EBADF     - 文件错误
 * @note 
 <pre>Example:
 char *value = NULL;
rv= xml_get_elem("SYSCONF.xml","//systemconf/IPBCASTB/", &value);
//Example:
//<systemconf>
//     <VERSION type="386">1.0</VERSION>
//     <IPBCASTB > 172.20.255.255 </IPBCASTB>
//</systemconf>
//
//仿照XPATH语法
//axis-identifier::node-test[predicate1][predicate2]..

//rv=xml_get_elem("SYSCONF.xml","//systemconf/IPBCASTB/", &value);

value=" 172.20.255.255 "

//rv=xml_get_elem("SYSCONF.xml","//systemconf/VERSION/@type/", &value); 

value="386"
//rv=xml_get_elem("SYSCONF.xml","//systemconf/VERSION[attribute::type="386"]/", &value); 

value="1.0"
//注意目前谓词只支持=号，只支持attribute轴,只支持1个谓词表达式。
</pre>
 */
APR_DECLARE(int) xml_get_elem(const char* filename,const char* path, char **value);

/**
 * @brief  dbparser_fn_retrieve
 * @param  fn_name  要取得的已注册函数名
 */
APR_DECLARE(dbparser_fn_t*) dbparser_fn_retrieve(const char *fn_name);

/**
 * @brief  dbparser_fn_register
 * @param  fn_name  要注册函数名
 * @param  pfn  处理函数句柄
 */
APR_DECLARE(void) dbparser_fn_register(const char *fn_name,dbparser_fn_t *pfn, apr_pool_t *pool);


APR_DECLARE(int) xml_get_elem_free_memory(void *point);

#ifdef __cplusplus
}
#endif

#endif /* _XMLTOOLS_H */
