#ifndef ACL_XML2_INCLUDE_H
#define ACL_XML2_INCLUDE_H

#ifdef __cplusplus
extern "C" {
#endif

#include "../stdlib/acl_array.h"
#include "../stdlib/acl_ring.h"
#include "../stdlib/acl_vstream.h"
#include "../stdlib/acl_htable.h"
#include "../stdlib/acl_vstring.h"
#include "../stdlib/acl_iterator.h"
#include "../stdlib/acl_dbuf_pool.h"

typedef struct ACL_XML2	ACL_XML2;
typedef struct ACL_XML2_NODE	ACL_XML2_NODE;
typedef struct ACL_XML2_ATTR	ACL_XML2_ATTR;

struct ACL_XML2_ATTR {
	ACL_XML2_NODE *node;            /**< ڵ */
	char *name;                     /**<  */
	char *value;                    /**< ֵ */

	ssize_t name_size;              /**<  */
	ssize_t value_size;             /**< ֵ */

	/* private */
	int   quote;                    /**<  0 ʾ '  " */
	int   backslash;                /**< תַ \ */
	int   slash;                    /**< Ƿ '/' ־λ趨 */
};

struct ACL_XML2_NODE {
	char *ltag;                     /**< ǩ */
	char *rtag;                     /**< ұǩ */
	ssize_t ltag_size;              /**< ǩ */
	ssize_t rtag_size;              /**< ұǩ */
	const char *id;                 /**< IDʶ, ֻ xml->id_table
					  ڵĽڵ id ŷǿ */
	char *text;                     /**< ıʾ */
	ssize_t text_size;              /**< ļݳ */

	ACL_ARRAY *attr_list;           /**< (ACL_XML2_ATTR)б */
	ACL_XML2_NODE *parent;          /**< ڵ */
	ACL_RING children;              /**< ӽڵ㼯 */
	int  depth;                     /**< ǰڵ */

	/* private */
	ACL_XML2 *xml;                  /**< xml  */
	ACL_RING node;                  /**< ǰڵ */
	ACL_XML2_ATTR *curr_attr;       /**< ǰڽ */
	int   quote;                    /**<  0 ʾ '  " */
	int   last_ch;                  /**< ¼ڵǰһֵֽ */
	int   nlt;                      /**< '<'  */
	char  meta[3];                  /**< Ԫʱ */

	unsigned int flag;
#define	ACL_XML2_F_META_QM	(1 << 0)    /**< '?' flag */
#define	ACL_XML2_F_META_CM	(1 << 1)    /**< '!--' flag */
#define	ACL_XML2_F_META_EM	(1 << 2)    /**< only '!' flag */
#define ACL_XML2_F_SELF_CL	(1 << 3)    /**< self closed flag */
#define	ACL_XML2_F_LEAF		(1 << 4)    /**< leaf node has no child node */
#define	ACL_XML2_F_CDATA	(1 << 5)    /**< CDATA data */

/**< ǷԪ */
#define	ACL_XML2_F_META		\
	(ACL_XML2_F_META_QM | ACL_XML2_F_META_CM | ACL_XML2_F_META_EM)

#define	ACL_XML2_IS_COMMENT(x)	(((x)->flag & ACL_XML2_F_META_CM))

#define	ACL_XML2_IS_CDATA(x)	(((x)->flag & ACL_XML2_F_CDATA))

	int   status;                   /**< ״̬ǰ״̬ */
#define ACL_XML2_S_NXT		0       /**< һڵ */
#define ACL_XML2_S_LLT		1       /**<  '<' */
#define ACL_XML2_S_LGT		2       /**< ұ '>' */
#define	ACL_XML2_S_LCH		3       /**<  '<' һֽ */
#define ACL_XML2_S_LEM		4       /**<  '<'  '!' */
#define ACL_XML2_S_LTAG		5       /**< ߵıǩ */
#define ACL_XML2_S_RLT		6       /**< ұߵ '<' */
#define ACL_XML2_S_RGT		7       /**< ұߵ '>' */
#define ACL_XML2_S_RTAG		8       /**< ұߵıǩ */
#define ACL_XML2_S_ATTR		9       /**< ǩ */
#define ACL_XML2_S_AVAL		10      /**< ǩֵ */
#define ACL_XML2_S_TXT		11      /**< ڵı */
#define ACL_XML2_S_MTAG		12      /**< Ԫݱǩ */
#define ACL_XML2_S_MTXT		13      /**< Ԫı */
#define ACL_XML2_S_MCMT		14      /**< Ԫע */
#define ACL_XML2_S_MEND		15      /**< Ԫݽ */
#define	ACL_XML2_S_CDATA	16      /**< CDATA  */

	/* for acl_iterator, ͨ acl_foreach гýڵһӽڵ */

	/* ȡͷ */
	ACL_XML2_NODE *(*iter_head)(ACL_ITER*, ACL_XML2_NODE*);
	/* ȡһ */
	ACL_XML2_NODE *(*iter_next)(ACL_ITER*, ACL_XML2_NODE*);
	/* ȡβ */
	ACL_XML2_NODE *(*iter_tail)(ACL_ITER*, ACL_XML2_NODE*);
	/* ȡһ */
	ACL_XML2_NODE *(*iter_prev)(ACL_ITER*, ACL_XML2_NODE*);
};

struct ACL_XML2 {
	/* public */
					
	int   depth;                    /**<  */
	int   node_cnt;                 /**< ڵ,  root ڵ */
	int   root_cnt;                 /**< ڵ */
	int   attr_cnt;                 /**<  */
	ACL_XML2_NODE *root;            /**< XML ڵ */

	/* private */
	ACL_FILE_HANDLE fd;		/** ɱ򿪵ļ */
	ACL_VSTRING *vbuf;		/**< ڴӳļĻ  */
	ACL_VSTRING *vbuf_inner;	/**< ڲĻ */
	char  dummy[1];

	ACL_HTABLE *id_table;           /**< id ʶϣ */
	ACL_XML2_NODE *curr_node;       /**< ǰڴ XML ڵ */
	ACL_DBUF_POOL *dbuf;            /**< ڴض */
	ACL_DBUF_POOL *dbuf_inner;      /**< ڲֲڴض */
	size_t dbuf_keep;               /**< ڴбĳ */

	unsigned flag;                  /**< ־λ: ACL_XML2_FLAG_xxx */ 

	/**< Ƿһ xml ĵжڵ㣬ڲȱʡΪ */
#define	ACL_XML2_FLAG_MULTI_ROOT	(1 << 0)

	/**< Ƿݵڵû '/'  */
#define	ACL_XML2_FLAG_IGNORE_SLASH	(1 << 1)

	/**<  xml ʱǷҪݽ xml   */
#define	ACL_XML2_FLAG_XML_DECODE	(1 << 2)

	/**<  xml ʱǷҪݽ xml  */
#define ACL_XML2_FLAG_XML_ENCODE	(1 << 3)

	/* for acl_iterator, ͨ acl_foreach гӽڵ */

	/* ȡͷ */
	ACL_XML2_NODE *(*iter_head)(ACL_ITER*, const ACL_XML2*);
	/* ȡһ */
	ACL_XML2_NODE *(*iter_next)(ACL_ITER*, const ACL_XML2*);
	/* ȡβ */
	ACL_XML2_NODE *(*iter_tail)(ACL_ITER*, const ACL_XML2*);
	/* ȡһ */
	ACL_XML2_NODE *(*iter_prev)(ACL_ITER*, const ACL_XML2*);
};

/****************************************************************************/
/*                  ӿڣûԷʹøýӿڼ                  */
/****************************************************************************/

/*----------------------------- in acl_xml2.c ----------------------------*/

/**
 * ж xml Ƿպϵ, ǷǷ,  xml 
 * xml ڵԪΪ, ҲΪǱպϵ
 * @param xml {ACL_XML2*} xml 
 * @return {int} 0: ; 1: 
 */
ACL_API int acl_xml2_is_closure(ACL_XML2 *xml);

/**
 * ָǩж xml Ѿ, ñǩ xml  root һӽڵ
 * еһ xml ڵıǩͬʱ, Ϊ xml , Ϊ֤жϵȷ,
 * ԴӦ֤ĸڵֻһ,  xml->root һӽڵֻһ, 
 * 
 * @param xml {ACL_XML2*} xml 
 * @param tag {const char*} ûǩ, ڲƥʱִСд
 * @return {int} 0: ; 1: 
 */
ACL_API int acl_xml2_is_complete(ACL_XML2 *xml, const char *tag);

/**
 * һ xml 
 * @param vbuf {ACL_VSTRING*} ڴӳ仺
 * @return {ACL_XML2*} ´ xml 
 */
ACL_API ACL_XML2 *acl_xml2_alloc(ACL_VSTRING *vbuf);

/**
 * һ xml 󣬸 xml еڲڴ䶼ڸڴϽз
 * @param vbuf {ACL_VSTRING*} ڴӳ仺
 * @param dbuf {ACL_DBUF_POOL*} ڴض󣬵Է NULL ʱ xml 
 *  ڵڴϽз䣬ڲԶ xml ڴ
 * @return {ACL_XML2*} ´ xml 
 */
ACL_API ACL_XML2 *acl_xml2_dbuf_alloc(ACL_VSTRING *vbuf, ACL_DBUF_POOL *dbuf);

/**
 * һ xml  xml ڵĴڴڴӳļ
 * @param filepath {const char*} ڴӳļļ
 * @param max_len {size_t} ӳļС
 * @param init_len {size_t} ӳڴʼʱĴС
 * @param dbuf {ACL_DBUF_POOL*} ڴض󣬵Է NULL ʱ xml 
 *  ڵڴϽз䣬ڲԶ xml ڴ
 * @return {ACL_XML2*} ´ xml 
 */
ACL_API ACL_XML2 *acl_xml2_mmap_file(const char *filepath, size_t max_len,
		size_t init_len, ACL_DBUF_POOL *dbuf);

/**
 * һ xml  xml ڵĴڴڴӳļ
 * @param fd {ACL_FILE_HANDLE} ڴӳļļ xml ɹ
 *  þ xml ͷźŹر
 * @param max_len {size_t} ӳļС
 * @param init_len {size_t} ӳڴʼʱĴС
 * @param dbuf {ACL_DBUF_POOL*} ڴض󣬵Է NULL ʱ xml 
 *  ڵڴϽз䣬ڲԶ xml ڴ
 * @return {ACL_XML2*} ´ xml 
 */
ACL_API ACL_XML2 *acl_xml2_mmap_fd(ACL_FILE_HANDLE fd, size_t max_len,
		size_t init_len, ACL_DBUF_POOL *dbuf);

/**
 * õǰ xml ڲѾڴռС
 * @param xml {ACL_XML2*}
 * @return {size_t} ǰ xml ڲѷڴС
 */
ACL_API size_t acl_xml2_space(ACL_XML2 *xml);

/**
 *  xml ڲ¼ڴСı 0
 * @param xml {ACL_XML2*}
 */
ACL_API void acl_xml2_space_clear(ACL_XML2 *xml);

/**
 * ĳһ ACL_XML2_NODE ڵΪһ XML ĸڵ㣬ӶԷر
 * ڵӽڵ(ڱенڵ㲻ڵ)ñʽбڵ
 * ĳһ ACL_XML2_NODE ڵʱܱһӽڵ
 * @param xml {ACL_XML2*} xml 
 * @param node {ACL_XML2_NODE*} AXL_XML_NODE ڵ
 */
ACL_API void acl_xml2_foreach_init(ACL_XML2 *xml, ACL_XML2_NODE *node);

/**
 * һ xml ĵǷж xml ڵ㣬ڲȱʡֶ֧ڵ
 * @param xml {ACL_XML2*} xml 
 * @param on {int}  0 Ϊ 0 ʾֹж xml ڵʱ
 *  ڽʱһڵʱ㷵ʣ
 */
ACL_API void acl_xml2_multi_root(ACL_XML2 *xml, int on);

/**
 *  XML ڵ, Ƿû /, :
 * <test id=111>, <test id=111 />, û / д
 * ǺϷģֻеڶдǺϷģּԣ
 * һʧ
 * @param xml {ACL_XML2*} xml 
 * @param ignore {int}  0 ʾڵ /
 */
ACL_API void acl_xml2_slash(ACL_XML2 *xml, int ignore);

/**
 *  xml ʱǷֵıֵ xml 룬ڲȱʡ
 * @param xml {ACL_XML2*}
 * @param on {int}  0 ʾ xml 
 */
ACL_API void acl_xml2_decode_enable(ACL_XML2 *xml, int on);

/**
 *  xml ʱǷֵıֵ xml 룬ڲȱʡ
 */
ACL_API void acl_xml2_encode_enable(ACL_XML2 *xml, int on);

/**
 * ͷһ xml , ͬʱͷŸöɵ xml ڵ
 * @param xml {ACL_XML2*} xml 
 * @return {int} ͷŵ xml ڵ
 */
ACL_API int acl_xml2_free(ACL_XML2 *xml);

/**
 *  XML 
 * @param xml {ACL_XML2*} xml 
 */
ACL_API void acl_xml2_reset(ACL_XML2 *xml);

/*------------------------- in acl_xml2_parse.c ----------------------------*/

/**
 *  xml , Զ xml ڵ
 * @param xml {ACL_XML2*} xml 
 * @param data {const char*}  '\0' βַ,  xml ;
 *  Ҳǲ xml , ѭô˺, ݳ
 * @return {const char*} ͨ acl_xml2_multi_root һ xml ĵ
 *   xml ڵʱúصĵַֽΪ '\0'; 򷵻ʣݵַ
 *  ǿַ
 *  עҲͨ acl_xml2_is_complete жǷ
 */
ACL_API const char *acl_xml2_update(ACL_XML2 *xml, const char *data);
#define	acl_xml2_parse	acl_xml2_update

/*------------------------- in acl_xml2_util.c -----------------------------*/

/**
 * ʼ input, br, hr ȵԱպϱǩ, γԱպϱǩ, Ա
 * acl_xml2_tag_selfclosed ѯ, ǩǷǱԱպϱǩ,
 * úֻܱʼһ, ҲԲʼ
 */
ACL_API void acl_xml2_tag_init(void);

/**
 * ûԼһЩԱպϵıǩ
 * @param tag {const char*} ǩעǩȲô 254 ֽ
 */
ACL_API void acl_xml2_tag_add(const char *tag);

/**
 *  acl_xml2_tag_init ʼԱպϱǩ, Եô˺ж
 * ǩǷԱպϱǩ, δ acl_xml2_tag_init, úԶ 0
 * @parma tag {const char*} ǩ
 * @return {int} 0: ʾ, 1: ʾ
 */
ACL_API int  acl_xml2_tag_selfclosed(const char *tag);

/**
 * жϱǩ xml ڵǷҶڵ, Ҷڵûӽڵ
 * @param tag {const char*} ǩ
 * @return {int} 0: Ҷڵ; 1: Ҷڵ
 */
ACL_API int  acl_xml2_tag_leaf(const char *tag);

/**
 * ͷ acl_xml2_getElementsByTagName, acl_xml2_getElementsByName,
 * acl_xml2_getElementsByAttr ȺصĶ̬, Ϊö̬е
 * Ԫض ACL_XML2 Ԫص, ͷŵö̬, ֻҪ ACL_XML2
 * ͷ, ԭڸеԪȻʹ.
 * ͷ xml ڵԪ
 * @param a {ACL_ARRAY*} ̬
 */
ACL_API void acl_xml2_free_array(ACL_ARRAY *a);

/**
 *  xml лǩͬ xml һڵ
 * @param xml {ACL_XML2*} xml 
 * @param tag {const char*} ǩ
 * @return {ACL_XML2_NODE*}  xml ڵ,  NULL 
 *  ʾûз xml ڵ
 */
ACL_API ACL_XML2_NODE *acl_xml2_getFirstElementByTagName(
	ACL_XML2 *xml, const char *tag);

/**
 *  xml леǩͬ xml ڵļ
 * @param xml {ACL_XML2*} xml 
 * @param tag {const char*} ǩ
 * @return {ACL_ARRAY*}  xml ڵ㼯,  ̬,  NULL 
 *  ʾûз xml ڵ, ǿֵҪ acl_xml2_free_array ͷ
 */
ACL_API ACL_ARRAY *acl_xml2_getElementsByTagName(
	ACL_XML2 *xml, const char *tag);

/**
 *  xml ле༶ǩͬ xml ڵļ
 * @param xml {ACL_XML2*} xml 
 * @param tags {const char*} ༶ǩ '/' ָǩ xml ݣ
 *  <root> <first> <second> <third name="test1"> text1 </third> </second> </first>
 *  <root> <first> <second> <third name="test2"> text2 </third> </second> </first>
 *  <root> <first> <second> <third name="test3"> text3 </third> </second> </first>
 *  ͨ༶ǩroot/first/second/third һԲзĽڵ
 * @return {ACL_ARRAY*}  xml ڵ㼯,  ̬,  NULL 
 *  ʾûз xml ڵ, ǿֵҪ acl_xml2_free_array ͷ
 */
ACL_API ACL_ARRAY *acl_xml2_getElementsByTags(ACL_XML2 *xml, const char *tags);

/**
 *  xml ле name ֵͬ xml ڵԪؼ
 * @param xml {ACL_XML2*} xml 
 * @param value {const char*} Ϊ name ֵ
 * @return {ACL_ARRAY*}  xml ڵ㼯,  ̬,  NULL 
 *  ʾûз xml ڵ, ǿֵҪ acl_xml2_free_array ͷ
 */
ACL_API ACL_ARRAY *acl_xml2_getElementsByName(ACL_XML2 *xml, const char *value);

/**
 *  xml лиֵ xml ڵԪؼ
 * @param xml {ACL_XML2*} xml 
 * @param name {const char*} 
 * @param value {const char*} ֵ
 * @return {ACL_ARRAY*}  xml ڵ㼯,  ̬,  NULL 
 *  ʾûз xml ڵ, ǿֵҪ acl_xml2_free_array ͷ
 */
ACL_API ACL_ARRAY *acl_xml2_getElementsByAttr(ACL_XML2 *xml,
	const char *name, const char *value);

/**
 *  xml лָ id ֵ xml ڵԪصĳԶ
 * @param xml {ACL_XML2*} xml 
 * @param id {const char*} id ֵ
 * @return {ACL_XML2_ATTR*} ĳ xml ڵĳԶ,  NULL ʾ
 *  ûз, ֵҪͷ
 */
ACL_API ACL_XML2_ATTR *acl_xml2_getAttrById(ACL_XML2 *xml, const char *id);

/**
 *  xml лָ id ֵ xml ڵԪصĳֵ
 * @param xml {ACL_XML2*} xml 
 * @param id {const char*} id ֵ
 * @return {const char*} ĳ xml ڵĳֵ,  NULL ʾûз
 *  
 */
ACL_API const char *acl_xml2_getAttrValueById(ACL_XML2 *xml, const char *id);

/**
 *  xml лָ id ֵ xml ڵԪ
 * @param xml {ACL_XML2*} xml 
 * @param id {const char*} id ֵ
 * @return {ACL_XML2_NODE*} xml ڵԪ,  NULL ʾûз
 *   xml ڵ, ֵҪͷ
 */
ACL_API ACL_XML2_NODE *acl_xml2_getElementById(ACL_XML2 *xml, const char *id);

/**
 *  xml ȡ ? ! ȿͷĽڵ
 * @param xml {ACL_XML2*} xml 
 * @param tag {const char*} ǩ
 * @return {ACL_XML2_NODE*} xml ڵԪ,  NULL ʾûз
 *   xml ڵ, ֵҪͷ
 */
ACL_API ACL_XML2_NODE *acl_xml2_getElementMeta(ACL_XML2 *xml, const char *tag);

/**
 *  xml ַʽ
 * @param xml {ACL_XML2*} xml 
 * @return {const char*} ַʽ NULL ʱʾûи
 */
ACL_API const char *acl_xml2_getEncoding(ACL_XML2 *xml);

/**
 *  xml ݵͣ磺text/xsl
 * @param xml {ACL_XML2*} xml 
 * @return {const char*}  NULL ʾûи
 */
ACL_API const char *acl_xml2_getType(ACL_XML2 *xml);

/**
 *  xml ڵлָԶ
 * @param node {ACL_XML2_NODE*} xml ڵ
 * @param name {const char*} 
 * @return {ACL_XML2_ATTR*} Զ, Ϊձʾ, ֵҪͷ
 */
ACL_API ACL_XML2_ATTR *acl_xml2_getElementAttr(ACL_XML2_NODE *node, const char *name);

/**
 *  xml ڵлֵָ
 * @param node {ACL_XML2_NODE*} xml ڵ
 * @param name {const char*} 
 * @return {const char*} ֵ, Ϊձʾ
 */
ACL_API const char *acl_xml2_getElementAttrVal(ACL_XML2_NODE *node, const char *name);

/**
 *  xml ڵɾĳԶ, Ϊ id , ͬʱ xml->id_table ɾ
 * @param node {ACL_XML2_NODE*} xml ڵ
 * @param name {const char*} 
 * @return {int} 0 ʾɾɹ, -1: ʾɾʧ(пǸԲ)
 */
ACL_API int acl_xml2_removeElementAttr(ACL_XML2_NODE *node, const char *name);

/**
 *  xml ڵ, Ѵ, µֵ滻ֵ, 
 * µԶ
 * @param node {ACL_XML2_NODE*} xml ڵ
 * @param name {const char*} 
 * @param value {const char*} ֵ
 * @return {ACL_XML2_ATTR*} ظԶ(пԭ, Ҳпµ), 
 *  ֵͷ
 */
ACL_API ACL_XML2_ATTR *acl_xml2_addElementAttr(ACL_XML2_NODE *node,
        const char *name, const char *value);

/**
 * ǩڵıΪ xml ڵ㣬úҪڹ xml ʱ
 * @param xml {ACL_XML2*} xml 󣬸öӦ acl_xml2_alloc 
 * @param tagname {const char*} ǩǿַȴ 0
 * @param text {const char*} ڵıݣΪ
 * @return {ACL_XML2_NODE*} ´ xml ڵ㣬÷Զطǿգ
 *  ǷᵼڲԶ
 */
ACL_API ACL_XML2_NODE *acl_xml2_create_node(ACL_XML2 *xml,
	const char* tagname, const char* text);

/**
 *  xml ڵ㣬ʹļΪڵıͬʱԶ XML 봦
 * @param xml {ACL_XML2*} xml 
 * @param tag {const char*} ǩ NULL ַ
 * @param in {ACL_VSTREAM *}  NULL ʱݽΪ xml ڵı
 * @param off {size_t}  in Ϊļʱָļеʼλ
 * @param len {size_t} ָпݳȣΪ 0 ʱһֱ
 * @return {ACL_XML2_NODE*} ´ xml ڵ㣬Զط NULL 
 *  Ƿڲ
 */
ACL_API ACL_XML2_NODE *acl_xml2_create_node_with_text_stream(ACL_XML2 *xml,
	const char *tag, ACL_VSTREAM *in, size_t off, size_t len);

/**
 * һ xml ڵԣúҪڹ xml ʱ
 * @param node {ACL_XML2_NODE*}  acl_xml2_create_node Ľڵ
 * @param name {const char*} Ϊǿַַȴ 0
 * @param value {const char*} ֵΪ
 * @return {ACL_XML2_ATTR*} xml ڵԶ󣬵Ƿʱú
 *  ڲԶ
 */
ACL_API ACL_XML2_ATTR *acl_xml2_node_add_attr(ACL_XML2_NODE *node,
	const char *name, const char *value);

/**
 * һ xml ڵһԣúҪڹ xml ʱ
 * @param node {ACL_XML2_NODE*}  acl_xml2_create_node Ľڵ
 * @param ... һԣ NULL ʱʾ磺
 *  {name1}, {value1}, {name2}, {value2}, ... NULL
 */
ACL_API void acl_xml2_node_add_attrs(ACL_XML2_NODE *node, ...);

/**
 * һ xml ڵıݣúҪڹ xml ʱýڵ֮ǰıʱ
 * ıԭı
 * @param node {ACL_XML2_NODE*}  acl_xml2_create_node Ľڵ
 * @param text {const char*} ı
 */
ACL_API void acl_xml2_node_set_text(ACL_XML2_NODE *node, const char *text);

/**
* һ xml ڵı׷ݣúҪڹ xml ʱڸýڵı
* ׷µı
* @param node {ACL_XML2_NODE*}  acl_xml2_create_node Ľڵ
* @param text {const char*} ı 
 */
ACL_API void acl_xml2_node_add_text(ACL_XML2_NODE *node, const char *text);

/**
 * ļеݸһ xml ڵı
 * @param node {ACL_XML2_NODE*}  acl_xml2_create_node Ľڵ 
 * @param in {ACL_VSTREAM*} 
 * @param off {size_t}  in Ϊļָļеʼλ
 * @param len {size_t} ҪݳȣΪ 0 ʱһֱ
 */
ACL_API void acl_xml2_node_set_text_stream(ACL_XML2_NODE *node,
	ACL_VSTREAM *in, size_t off, size_t len);

/**
 *  xml תַ
 * @param xml {ACL_XML2*} xml 
 * @return {const char*} תַʼַ
 */
ACL_API const char *acl_xml2_build(ACL_XML2* xml);

/**
 *  xml תַ
 * @param xml {const ACL_XML2*} xml 
 * @param vbuf {ACL_VSTRING*} 洢
 * @return {const char*} תַʼַ
 */
ACL_API const char *acl_xml2_build2(const ACL_XML2* xml, ACL_VSTRING *vbuf);

/**
 *  xml תָУעתϢΪõ
 * @param xml {ACL_XML2*} xml 
 * @param fp {ACL_VSTREAM*} 
 */
ACL_API void acl_xml2_dump(ACL_XML2 *xml, ACL_VSTREAM *fp);

/**
 *  xml תָУעתϢΪõ
 * @param xml {ACL_XML2*} xml 
 * @param buf {ACL_VSTRING*} , ҪûԼռ
 */
ACL_API void acl_xml2_dump2(ACL_XML2 *xml, ACL_VSTRING *buf);

/***************************************************************************/
/*          ΪΪͼĽӿ, ûԸҪ½ӿ             */
/***************************************************************************/

/*----------------------------- in acl_xml2.c ------------------------------*/

/**
 *  xml ڵ
 * @param node {ACL_XML2_NODE*} xml ڵ
 * @return {ACL_XML2_ATTR*} ´Ľڵ
 */
ACL_API ACL_XML2_ATTR *acl_xml2_attr_alloc(ACL_XML2_NODE *node);

/**
 * һ xml ڵ
 * @param xml {ACL_XML2*} xml 
 * @return {ACL_XML2_NODE*} xml ڵ
 */
ACL_API ACL_XML2_NODE *acl_xml2_node_alloc(ACL_XML2 *xml);

/**
 * ĳ xml ڵ㼰ӽڵ xml ɾ, ͷŸýڵ㼰ӽڵռռ
 * ͷŸ xml ڵռڴ
 * @param node {ACL_XML2_NODE*} xml ڵ
 * @return {int} ɾĽڵ
 */
ACL_API int acl_xml2_node_delete(ACL_XML2_NODE *node);

/**
 * ĳ xml ڵֵܽڵ(ֵܽڵǶ xml ڵ)
 * @param node1 {ACL_XML2_NODE*} 򱾽ڵ xml ڵ
 * @param node2 {ACL_XML2_NODE*} ӵֵ xml ڵ
 */
ACL_API void acl_xml2_node_append(ACL_XML2_NODE *node1, ACL_XML2_NODE *node2);

/**
 * ĳ xml ڵΪӽڵĳ xml ڵ
 * @param parent {ACL_XML2_NODE*} ڵ
 * @param child {ACL_XML2_NODE*} ӽڵ
 */
ACL_API void acl_xml2_node_add_child(ACL_XML2_NODE *parent, ACL_XML2_NODE *child);

/**
 * ĳ xml ڵĸڵ
 * @param node {ACL_XML2_NODE*} xml ڵ
 * @return {ACL_XML2_NODE*} ڵ, Ϊ NULL ʾ丸ڵ㲻
 */
ACL_API ACL_XML2_NODE *acl_xml2_node_parent(ACL_XML2_NODE *node);

/**
 * ĳ xml ڵĺһֵܽڵ
 * @param node {ACL_XML2_NODE*} xml ڵ
 * @return {ACL_XML2_NODE*}  xml ڵĺһֵܽڵ, ΪNULLʾ
 */
ACL_API ACL_XML2_NODE *acl_xml2_node_next(ACL_XML2_NODE *node);

/**
 * ĳ xml ڵǰһֵܽڵ
 * @param node {ACL_XML2_NODE*} xml ڵ
 * @return {ACL_XML2_NODE*}  xml ڵǰһֵܽڵ, ΪNULLʾ
 */
ACL_API ACL_XML2_NODE *acl_xml2_node_prev(ACL_XML2_NODE *node);

#ifdef __cplusplus
}
#endif
#endif
