#ifndef MOD_XMLNS_H
#define MOD_XMLNS_H

/* These defines are for the implementations.
 * Namespace providers should leave them undefined
 */
#ifdef MOD_XMLNS_EXPAT
typedef XML_Char	xml_char_t ;
#else
#ifdef MOD_XMLNS_LIBXML2
typedef xmlChar		xml_char_t ;
#else
typedef char		xml_char_t ;
#endif
#endif

#include <util_filter.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef struct xmlns_attr_t xmlns_attr_t ;

/** A context parameter passed to handlers
 *
 *  This is the public part of a bigger implementation-dependent struct.
 *  use accessor functions below, esp.
 *	xmlns_get_appdata
 *	xmlns_set_appdata
 */
typedef struct xmlns_public {
  ap_filter_t* f ;		/* f and bb are the current filter and	*/
  apr_bucket_brigade* bb ;	/* brigade, for handlers to use in	*/
				/* ap_fputs, ap_fprintf, etc		*/
} xmlns_public ;

/** ParsedName struct is a basic SAX2-equivalent.
 *
 * Note that the strings are NOT necessarily NULL-terminated - it is
 * implementation-dependent.   Always use the length parameters with them.
 */
typedef struct {
  int nparts ;			/* number of fields defined in this struct:
					1: Only elt is defined
					2: elt and ns are defined
					3: elt, ns and prefix are defined
				*/
  const xml_char_t* ns ;	/* xmlns prefix for this namespace */
  size_t nslen ;		/* Length of ns */
  const xml_char_t* elt ;	/* Element name */
  size_t eltlen ;		/* Length of elt */
  const xml_char_t* prefix ;	/* Currently-defined prefix for namespace */
  size_t prefixlen ;		/* Length of prefix */
} parsedname ;

/** xmlns struct defines callbacks
 *
 * Those returning int may return OK to suppress default handler-absent
 * behaviour, or DECLINED to request default behaviour (print it).
 * Error codes may mean something in future.
 */
typedef struct xmlns {

  int (*StartElement) ( xmlns_public*, const parsedname*, const xmlns_attr_t*) ;
  int (*EndElement) ( xmlns_public*, const parsedname*) ;
  void (*StartNamespace) ( xmlns_public*,
	const xml_char_t*, const xml_char_t* ) ;
  void (*EndNamespace) ( xmlns_public*, const xml_char_t* ) ;

/* Allow a comment handler - 'cos so many people put function in comments.
   The parser will dispatch to this comment handler if this prefix is
   non-null and the start of the comment matches this prefix.
*/
  const char* comment_prefix ;
  int (*CommentHandler) (xmlns_public*, const xml_char_t*) ;

} xmlns ;

/********************************************************************
 *
 * Accessor Functions
 *
 ********************************************************************
 */

/* xmlns_parsename:
 * parses a name into a struct parsedname.
 * Handlers may call this to deal with namespaced attributes
 */
extern void xmlns_parsename(const xml_char_t* name, parsedname* p) ;

/** get/set appdata
 *  The appdata field is a void* context ptr for the use of applications
 *  and serves the purpose of the "void* ctx" argument of SAX APIs in C.
 *  Use these accessor functions to get/set an application ptr.
 *
 *  The URI arg should always be the same ptr - it is matched using ==
 *  for speed.  xmlns_get_appdata3 does string matching, and is
 *  therefore slower.
 */
extern void* xmlns_get_appdata(xmlns_public* x, const void* uri) ;
extern void* xmlns_get_appdata3(xmlns_public* x, const parsedname* nm) ;
extern void* xmlns_set_appdata(xmlns_public* x, const void* uri, void* data) ;

/** These functions probably shouldn't be provided, but turn different
 *  types of markup on/off.  They can be used by an element to
 *  suppress its own contents, but should be used with caution
 *  if at all.
 */
extern void xmlns_enable_characters(xmlns_public*, int onoff) ;
extern void xmlns_enable_cdata(xmlns_public*, int onoff) ;
extern void xmlns_enable_comment(xmlns_public*, int onoff) ;

/** xmlns_suppress_output suppresses all output until it is turned off
 *  e.g. for SSI conditionals (<!--#if ...-->, etc).
 */
extern void xmlns_suppress_output(xmlns_public*, int onoff) ;

/** xmlns_get_attr_name and xmlns_get_attr_val are accessor functions
 *  for getting attribute names and values respectively in
 *  StartElement handlers.  When there are no more attributes,
 *  they return NULL.
 *
 *  Usage:
 *  for ( i = 0 ; ; ++i ) {
 *    name = xmlns_get_attr_name(attrs, i) ;
 *    if ( name == NULL )	// no more attributes
 *      break ;
 *    val = xmlns_get_attr_val(attrs, i) ;
 *    // Do something with name and val
 *  }
 */
const xml_char_t* xmlns_get_attr_name(const xmlns_attr_t*, int) ;
const xml_char_t* xmlns_get_attr_val(const xmlns_attr_t*, int) ;

/** xmlns_get_attr_parsed is an alternative to xmlns_get_attr_name that
 *  parses the attribute into a parsedname instead of returning it as-is.
 *  Return value is 1 if an attribute is parsed; 0 if there are no more
 *  attributes, so it works in a loop in the same form as above.
 */
int xmlns_get_attr_parsed(const xmlns_attr_t*, int, parsedname*) ;


#ifdef __cplusplus
}
#endif

#endif

