text: /* $Id$ */
  /* 
   * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
   * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
   */
  #ifndef __PJ_XML_H__
  #define __PJ_XML_H__
  
  /**
   * @file xml.h
   * @brief PJLIB XML Parser/Helper.
   */
  
  #include <pj/types.h>
  #include <pj/list.h>
  
  PJ_BEGIN_DECL
  
  /**
   * @defgroup PJ_TINY_XML Mini/Tiny XML Parser/Helper
   * @ingroup PJ_FILE_FMT
   * @{
   */
  
  /** Typedef for XML attribute. */
  typedef struct pj_xml_attr pj_xml_attr;
  
  /** Typedef for XML nodes. */
  typedef struct pj_xml_node pj_xml_node;
  
  /** This structure declares XML attribute. */
  struct pj_xml_attr
  {
      PJ_DECL_LIST_MEMBER(pj_xml_attr);   /**< Standard list elements.    */
      pj_str_t	name;	                /**< Attribute name.            */
      pj_str_t	value;	                /**< Attribute value.           */
  };
  
  /** This structure describes XML node head inside XML node structure.
   */
  typedef struct pj_xml_node_head
  {
      PJ_DECL_LIST_MEMBER(pj_xml_node);   /**< Standard list elements.    */
  } pj_xml_node_head;
  
  /** This structure describes XML node. */
  struct pj_xml_node
  {
      PJ_DECL_LIST_MEMBER(pj_xml_node);   /**< List @a prev and @a next member */
      pj_str_t		name;		/**< Node name.                      */
      pj_xml_attr		attr_head;      /**< Attribute list.                 */
      pj_xml_node_head	node_head;      /**< Node list.                      */
      pj_str_t		content;	/**< Node content.                   */
  };
  
  /**
   * Parse XML message into XML document with a single root node. The parser
   * is capable of parsing XML processing instruction construct ("<?") and 
   * XML comments ("<!--"), however such constructs will be ignored and will not 
   * be included in the resulted XML node tree.
   *
   * Note that the XML message input buffer MUST be NULL terminated and have
   * length at least len+1 (len MUST NOT include the NULL terminator).
   *
   * @param pool	    Pool to allocate memory from.
   * @param msg	    The XML message to parse, MUST be NULL terminated.
   * @param len	    The length of the message, not including NULL terminator.
   *
   * @return	    XML root node, or NULL if the XML document can not be parsed.
   */
  PJ_DECL(pj_xml_node*) pj_xml_parse( pj_pool_t *pool, char *msg, pj_size_t len);
  
  
  /**
   * Print XML into XML message. Note that the function WILL NOT NULL terminate
   * the output.
   *
   * @param node	    The XML node to print.
   * @param buf	    Buffer to hold the output message.
   * @param len	    The length of the buffer.
   * @param prolog    If set to nonzero, will print XML prolog ("<?xml..")
   *
   * @return	    The size of the printed message, or -1 if there is not 
   *		    sufficient space in the buffer to print the message.
   */
  PJ_DECL(int) pj_xml_print( const pj_xml_node *node, char *buf, pj_size_t len,
  			   pj_bool_t prolog);
  
  /**
   * Clone XML node and all subnodes.
   *
   * @param pool	    Pool to allocate memory for new nodes.
   * @param rhs	    The node to clone.
   *
   * @return	    Cloned XML node, or NULL on fail.
   */
  PJ_DECL(pj_xml_node*) pj_xml_clone( pj_pool_t *pool, const pj_xml_node *rhs);
  
  
  /**
   * Create an empty node.
   *
   * @param pool	    Pool.
   * @param name	    Node name.
   *
   * @return	    The new node.
   */
  PJ_DECL(pj_xml_node*) pj_xml_node_new(pj_pool_t *pool, const pj_str_t *name);
  
  
  /**
   * Create new XML attribute.
   *
   * @param pool	    Pool.
   * @param name	    Attribute name.
   * @param value	    Attribute value.
   *
   * @return	    The new XML attribute.
   */
  PJ_DECL(pj_xml_attr*) pj_xml_attr_new(pj_pool_t *pool, const pj_str_t *name,
  				      const pj_str_t *value);
  
  /**
   * Add node to another node.
   *
   * @param parent    Parent node.
   * @param node	    Node to be added to parent.
   */
  PJ_DECL(void) pj_xml_add_node( pj_xml_node *parent, pj_xml_node *node );
  
  
  /**
   * Add attribute to a node.
   *
   * @param node	    Node.
   * @param attr	    Attribute to add to node.
   */
  PJ_DECL(void) pj_xml_add_attr( pj_xml_node *node, pj_xml_attr *attr );
  
  /**
   * Find first direct child node with the specified name.
   *
   * @param parent    Parent node.
   * @param name	    Node name to find.
   *
   * @return	    XML node found or NULL.
   */
  PJ_DECL(pj_xml_node*) pj_xml_find_node(const pj_xml_node *parent, 
  				       const pj_str_t *name);
  
  /**
   * Find next direct child node with the specified name.
   *
   * @param parent    Parent node.
   * @param node	    node->next is the starting point.
   * @param name	    Node name to find.
   *
   * @return	    XML node found or NULL.
   */
  PJ_DECL(pj_xml_node*) pj_xml_find_next_node(const pj_xml_node *parent, 
  					    const pj_xml_node *node,
  					    const pj_str_t *name);
  
  /**
   * Recursively find the first node with the specified name in the child nodes
   * and their children.
   *
   * @param parent    Parent node.
   * @param name	    Node name to find.
   *
   * @return	    XML node found or NULL.
   */
  PJ_DECL(pj_xml_node*) pj_xml_find_node_rec(const pj_xml_node *parent, 
  					   const pj_str_t *name);
  
  
  /**
   * Find first attribute within a node with the specified name and optional 
   * value.
   *
   * @param node	    XML Node.
   * @param name	    Attribute name to find.
   * @param value	    Optional value to match.
   *
   * @return	    XML attribute found, or NULL.
   */
  PJ_DECL(pj_xml_attr*) pj_xml_find_attr(const pj_xml_node *node, 
  				       const pj_str_t *name,
  				       const pj_str_t *value);
  
  
  /**
   * Find a direct child node with the specified name and match the function.
   *
   * @param parent    Parent node.
   * @param name	    Optional name. If this is NULL, the name will not be
   *		    matched.
   * @param data	    Data to be passed to matching function.
   * @param match	    Optional matching function.
   *
   * @return	    The first matched node, or NULL.
   */
  PJ_DECL(pj_xml_node*) pj_xml_find( const pj_xml_node *parent, 
  				   const pj_str_t *name,
  				   const void *data, 
  				   pj_bool_t (*match)(const pj_xml_node *, 
  						      const void*));
  
  
  /**
   * Recursively find a child node with the specified name and match the 
   * function.
   *
   * @param parent    Parent node.
   * @param name	    Optional name. If this is NULL, the name will not be
   *		    matched.
   * @param data	    Data to be passed to matching function.
   * @param match	    Optional matching function.
   *
   * @return	    The first matched node, or NULL.
   */
  PJ_DECL(pj_xml_node*) pj_xml_find_rec(const pj_xml_node *parent, 
  				      const pj_str_t *name,
  				      const void *data, 
  				      pj_bool_t (*match)(const pj_xml_node*, 
  							 const void*));
  
  
  /**
   * @}
   */
  
  PJ_END_DECL
  
  #endif	/* __PJ_XML_H__ */
  