File:  [ELWIX - Embedded LightWeight unIX -] / gpl / axl / src / axl_dtd.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Fri Feb 17 12:50:03 2012 UTC (12 years, 3 months ago) by misho
Branches: axl, MAIN
CVS tags: HEAD, AXL0_6_7
version 0.6.7

/*
 *  LibAxl:  Another XML library
 *  Copyright (C) 2006 Advanced Software Production Line, S.L.
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public License
 *  as published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser 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
 *  
 *  You may find a copy of the license under this software is released
 *  at COPYING file. This is LGPL software: you are welcome to
 *  develop proprietary applications using this library without any
 *  royalty or fee but returning back any change, improvement or
 *  addition in the form of source code, project image, documentation
 *  patches, etc. 
 *
 *  For commercial support on build XML enabled solutions contact us:
 *          
 *      Postal address:
 *         Advanced Software Production Line, S.L.
 *         Edificio Alius A, Oficina 102,
 *         C/ Antonio Suarez Nº 10,
 *         Alcalá de Henares 28802 Madrid
 *         Spain
 *
 *      Email address:
 *         info@aspl.es - http://www.aspl.es/xml
 */
#include <axl_decl.h>
#include <axl.h>

#define LOG_DOMAIN "axl-dtd"

struct _axlDtdElementListNode {
	NodeType     type;
	AxlDtdTimes  times;
	axlPointer   data;
};

struct _axlDtdElementList {
	/** 
	 * @brief Allows to configure how is given top level
	 * configuration for nodes to be defined inside the xml
	 * document being configured. As defined in the XML 1.0
	 * Recomendation, available top level choices are: choice or
	 * sequence. 
	 *
	 * They allow to configure allowed nodes to be selected as
	 * childs, from a set of node names, called choice or to
	 * configure which are the set of nodes to be used, in a
	 * particular order, called sequence.
	 *
	 * This variable allows to configure which is the top level
	 * section configuration: either a choice or a sequence.
	 *
	 * Keep in mind that, having only one element inside the
	 * itemList, there is no difference between the sequence and
	 * the choice.
	 */
	AxlDtdNestedType      type;
	
	/** 
	 * @brief Allows to configure how many times is repeated a
	 * selection provided (by this element).
	 */
	AxlDtdTimes           times;

	/** 
	 * @brief Item list, which contains more axlDtdElementList
	 * nodes, configuring elements allowed.
	 */
	axlList             * itemList;
};

struct _axlDtdElement {
	/** 
	 * @brief The document type element declaration name. This is
	 * the name of the xml node being constrained.
	 */
	char                * name;

	/** 
	 * @brief This is the type of the xml node being constrained.
	 */
	AxlDtdElementType     type;
	/** 
	 * @brief List of available items.
	 * 
	 * This variable holds current top level list selection. See
	 * axlDtdElementList.type variable.
	 */
	axlDtdElementList   * list;

	/** 
	 * @brief Minimum item list count to be matched while using
	 * this DTD element rule.
	 */
	int                    minimum_match;
};

struct _axlDtdAttributeDecl {
	/** 
	 * @brief Attribute name. This is the attribute value defined
	 * for the node.
	 */
	char                     * name;
	
	/** 
	 * @brief This is the attribute declaration type. It shows if 
	 */
	AxlDtdAttributeType        type;

	/** 
	 * @brief Allows to model whoe is 
	 */
	AxlDtdAttributeDefaults    defaults;
	
	/** 
	 * @brief This is a default value for the <!ATTLIST
	 * declaration received, in the case a FIXED value is required
	 * or a default value is declarted.
	 */
	char                     * default_value;

	/** 
	 * @brief Internal declaration for enum values defined for
	 * this rule. This list is only initialized in the case enum
	 * values are defined.
	 */
	axlList                  * enumvalues;

};

struct _axlDtdAttribute {
	/** 
	 * @brief The document attribute list declaration name. This
	 * is the name of the node that will receive the constrain
	 * defined.
	 */
	char           * name;
	
	/** 
	 * @brief This is the list of constrains defined for the
	 * node. It as list of \ref axlDtdAttributeDecl which defines
	 * the attribute that is declarted, if it is required, and the
	 * type of its content.
	 */
	axlList        * list;
};

struct _axlDtdEntityExternalData {
	/** 
	 * @brief Contains the system literal reference. This is a URI
	 * reference to the resource pointed by the \ref axlDtdEntity
	 * definition.
	 */
	char * system_literal;
	/** 
	 * @brief Contains the public literal information associated
	 * to the entity definition.
	 */
	char * public_literal;
	/** 
	 * @brief Contains the NDATA information (a notation name
	 * reference).
	 */
	char * ndata;
};

struct _axlDtdEntity {
	/** 
	 * @brief Contains the entity name.
	 */
	char           * name;
	
	/** 
	 * @brief Contains the entity type.
	 */
	axlDtdEntityType type;

	/** 
	 * @brief Content of the entity definition ([9] EntityValue).
	 */
	char           * content;
	
	/** 
	 * @brief An entity definition can have a reference to a
	 * external resource. The following pointer contains
	 * information for the external resource pointed.
	 */
	axlDtdEntityExternalData * data;
};

struct _axlDtd {
	/** 
	 * @brief Holds all entity definitions inside the DTD
	 * declaration (<!ENTITY..>).
	 */
	axlList       * entities;

	/** 
	 * @brief All elements inside the DTD declaration
	 * (<!ELEMENT..> ).
	 */
	axlList       * elements;

	/** 
	 * @brief All attribute type declerations inside the DTD
	 * (<!ATTLIST..>)
	 */
	axlList       * attributes;

	/** 
	 * @brief The element root, for the given DTD declaration.
	 */
	axlDtdElement * root;

	/** 
	 * @brief Internal flag that allows to notify that the DTD
	 * contains ID attribute declaration, making the DTD this
	 * references. 
	 */
	axl_bool       haveIdDecl;

	/** 
	 * @brief Flag that the dtd declaration have attributes which
	 * are flaged as IDREF.
	 */
	axl_bool      haveIdRefDecl;
};

/**
 * \defgroup axl_dtd_module Axl DTD: Document type declaration interface (functions, validation, and DTD parsing)
 */


/** 
 * \addtogroup axl_dtd_module
 * @{
 */


/** 
 * @internal
 *
 * Allows to create a new dtd element list item, which represents a
 * content particule inside an item list or a item list. This allows
 * the recursion defined on the XML 1.0 standard.
 *
 * The function receives the node name and a reference list. According
 * to the values the function creates a node which contains a leaf
 * value or a node which contains a reference to the a new list which
 * is nested.
 */
axlDtdElementListNode * __create_axl_dtd_element_list (char * node_name,
						       axlDtdElementList * list)
{
	axlDtdElementListNode * node;

	node = axl_new (axlDtdElementListNode, 1);

	/* create a node element reference */
	if (node_name != NULL) {
		node->data = node_name;
		node->type = AXL_ELEMENT_NODE;
		return node;
	}

	/* create an element list reference */
	if (list != NULL) {
		node->data = list;
		node->type = AXL_ELEMENT_LIST;
		return node;
	}

	/* if another type is requested, return NULL */
	return NULL;
}

/** 
 * @internal
 *
 * Support function used to destroy all items stored on a item list.
 * 
 * @param node 
 */
void __destroy_axl_dtd_element_list (axlDtdElementListNode * node)
{
	if (node == NULL)
		return;
	/* free the reference to the leaf node if defined */
	if (node->type == AXL_ELEMENT_NODE)
		axl_free (node->data);
	
	/* do not do nothing if the reference is not element list */
	if (node->type == AXL_ELEMENT_LIST)
		axl_dtd_item_list_free (node->data);

	/* free de node itself */
	axl_free (node);
	return;
}

/** 
 * @internal
 *
 * @brief Support function to \ref axl_dtd_parse which creates a new
 * empty DTD reference.
 * 
 * 
 * @return A newly allocated \ref axlDtd reference.
 */
axlDtd * __axl_dtd_new (void)
{
	axlDtd * dtd;

	/* create the DTD element and nothing else. The rest of items
	 * created on demand */
	dtd           = axl_new (axlDtd, 1);

	return dtd;
}

axl_bool __queue_items (axlPointer data, axlPointer _stack)
{
	axlStack * stack = _stack;

	/* queue the data */
	axl_stack_push (stack, data);

	/* return axl_false to make the function to not stop */
	return axl_false;
}

void __axl_dtd_queue_childs (axlStack * stack, axlNode * parent)
{
	axlNode * child;

	/* get the first child */
	child = axl_node_get_first_child (parent);
	while (child != NULL) {

		/* queue the child */
		axl_stack_push (stack, child);
		
		/* get the next child */
		child = axl_node_get_next (child);
	} /* end while */

	return;
}

/** 
 * @internal
 *
 * Support internal function which allows to queue all items inside an
 * axlDtdElementList to be checked.
 * 
 * @param stack The stack where all data will be placed.
 *
 * @param dtd_element_list The dtd element list where the data will be
 * extracted.
 */
void __axl_dtd_queue_items (axlStack * stack, axlList * list) 
{
	/* call to queue items */
	axl_list_lookup (list, __queue_items, stack);

	/* nothing more */
	return;
}

/** 
 * @internal
 *
 * Support function which allows to check if the provided two dtd
 * elements are in fact, parent and child.
 *
 * DTD element have a parent-child relation based in the fact that the
 * first define top level xml nodes that are followed, in the form of
 * childs nodes, by other DTD elements that define more childs, etc...
 *
 * This function allows to check if the provided parent dtd element
 * have references inside its content specification that proves that
 * it is indeed a parent definition.
 * 
 * @param dtd_element_parent The supposed DTD parent element.
 * @param dtd_element_child  The supposedd DTD child element.
 * 
 * @return \ref axl_true if the function can confirm that the parent-child
 * relation exists, \ref axl_false if not or it could be proved.
 */
axl_bool     __axl_dtd_get_is_parent (axlDtdElement * dtd_element_parent,
				      axlDtdElement * dtd_element_child)
{
	axlStack               * stack;
	axlDtdElementListNode  * node;
	axlDtdElementList      * list;

	/* check for leaf nodes, that, by definition, could be a
	 * parent of nothing. */
	if (dtd_element_parent->list == NULL || dtd_element_parent->list->itemList == NULL) {
		return axl_false;
	}

	/* prepare all elements inside the stack to be checked */
	stack = axl_stack_new (NULL);
	__axl_dtd_queue_items (stack, dtd_element_parent->list->itemList);
	

	__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "stack size to operate: %d, list: %d", 
		   axl_stack_size (stack),
		   axl_list_length (dtd_element_parent->list->itemList));

	/* now search for a content particule that makes are reference
	 * to the child DTD element */
	do {
		node = axl_stack_pop (stack);
		switch (node->type) {
		case AXL_ELEMENT_NODE:
			/* leaf node case */
			__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a leaf node, checking it");

			/* seems this is a final node */
			if (axl_cmp (node->data, dtd_element_child->name)) {
				/* seems that the content
				 * specification makes a reference to
				 * the child node. */
				axl_stack_free (stack);
				return axl_true;
			}
			break;
		case AXL_ELEMENT_LIST:
			/* a nested list case */
			__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a complex node queuing its internal elements, while checking parent=%s for child=%s",
				   dtd_element_parent->name, dtd_element_child->name);
			/* the item list read, is a complex value,
			 * queue all items inside to be inspected */
			list = node->data;
			__axl_dtd_queue_items (stack, list->itemList);
			break;
		case AXL_ELEMENT_NOT_DEFINED:
			/* do nothing */
			break;
		}
		
		/* iterate until all elements are evaluated */
	}while (! axl_stack_is_empty (stack));

	/* deallocates no longer used stack */
	axl_stack_free (stack);
	
	/* either it isn't the parent or it can't be proved. */
	return axl_false;
}


/** 
 * @internal
 * 
 * Support function which allows to get which is the most top root
 * node for the provided set of DTD elements.
 */
axlDtdElement * __axl_dtd_get_new_root (axlDtd * dtd) 
{
	int             iterator;
	axl_bool        change_detected;

	axlDtdElement * dtd_element_aux;
	axlDtdElement * dtd_element_the_root_is_on_fire;

	/* set the very first root node */
	dtd_element_the_root_is_on_fire = axl_list_get_nth (dtd->elements, 0);
	
	do {
		/* check which is the top */
		iterator        = 0;
		change_detected = axl_false;
		while (iterator < axl_list_length (dtd->elements)) {
			
			/* get the next reference */
			dtd_element_aux = axl_list_get_nth (dtd->elements, iterator);
			
			/* check which is the top */
			if (__axl_dtd_get_is_parent (dtd_element_aux,
						     dtd_element_the_root_is_on_fire)) {
				/* it seems that the new element is the root
				 * one, update the reference */
				dtd_element_the_root_is_on_fire = dtd_element_aux;
				change_detected = axl_true;
			}
			
			/* update inner loop iterator */
			iterator ++;
		} /* while end */
	}while (change_detected);

	/* return the root found */
	return dtd_element_the_root_is_on_fire;
}

/** 
 * @internal 
 *
 * @brief Adds the axlDtdElement into the given axlDtd definition,
 * checking that everything is properly configured, and ensuring that
 * the root element gets properly configured.
 * 
 * @param dtd The \ref axlDtd object that will receive the
 * axlDtdElement.
 *
 * @param stream The \ref axlStream object that will be destroyed if
 * something wrong is found.
 *
 * @param element The axlDtdElement to be added to the give axlDtd
 * object.
 * 
 * @return axl_true if the given axlDtdElement is compatible inside
 * the axlDtd declaration or axl_false if a error is found.
 */
axl_bool     __axl_dtd_add_element (axlDtd * dtd, axlDtdElement * element, 
				    axlStream * stream, axlError ** error)
{
	int             iterator        = 0;
	axlDtdElement * dtd_element_aux = NULL;

	/* check that there is no element already named like the
	 * element received. If it is the case drop an error */
	while (iterator < axl_list_length (dtd->elements)) {
		dtd_element_aux = axl_list_get_nth (dtd->elements, iterator);
		if (axl_cmp (dtd_element_aux->name, element->name)) {
			__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "DTD element for <%s> == <%s> was defined twice", 
				   dtd_element_aux->name, element->name);

			axl_error_new (-1, "Find that an DTD element was defined twice (no more than one time is allowed)", 
				       stream, error);
			axl_stream_free (stream);
			return axl_false;
		}

		/* update current iterator */
		iterator++;
	}
	
	/* add the new DTD element to the list */
	axl_list_add (dtd->elements, element);
	return axl_true;
}

/** 
 * @internal
 * 
 * Internal support function which adds the provided content particule
 * to the dtd item list received. It also perform all operations
 * required for the chunk_matched option received.
 *
 * In the case the function fails to do its work, it will deallocate
 * the stream, filling the error received.
 *
 * According to the chunk matched value, the function will react
 * adding the element and configuring current element list.
 *
 */
axl_bool     __axl_dtd_element_content_particule_add (axlDtdElementList  * dtd_item_list, 
						      char               * string_aux, 
						      int                  chunk_matched, 
						      axlStream          * stream, 
						      axlError          **error)
{
	axlDtdElementListNode * node;

	/* check if the item list was creted or not */
	if (dtd_item_list->itemList == NULL) {
		dtd_item_list->itemList = axl_list_new (axl_list_always_return_1, 
							(axlDestroyFunc) __destroy_axl_dtd_element_list);
	}

	/* create the node to be added */
	node = __create_axl_dtd_element_list (string_aux, NULL);

	/* know add the element found */
	axl_list_add (dtd_item_list->itemList, node);

	/* set configuration for item repetition */
	switch (chunk_matched) {
	case 4:
		/* one or many times */
		__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "setting one to many repeat pattern: (+)");
		node->times = ONE_OR_MANY;
		break;
	case 5:
		/* zero or many times */
		__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "setting zero to many repeat pattern: (*)");
		node->times = ZERO_OR_MANY;
		break;
	case 6:
		/* zero or one time */
		__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "setting one to one repeat pattern: (?)");
		node->times = ZERO_OR_ONE;
		break;
	default:
		/* one and only one time */
		__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "setting one and only one repeat pattern: ()");
		node->times = ONE_AND_ONLY_ONE;
	}

	/* return that all is ok */
	return axl_true;
}


/** 
 * @internal
 * 
 * @brief Support function which allows to get current repetition
 * configuration.
 * 
 * @param stream The stream where the operation will be performed.
 * 
 * @return Current configuration read, the function will properly work
 * if it is called when it is espected to find a content specification
 * repetition. If not found, the \ref ONE_AND_ONLY_ONE is returned.
 */
AxlDtdTimes __axl_dtd_get_repetition_conf (axlStream * stream)
{
	axl_return_val_if_fail (stream, ONE_AND_ONLY_ONE);

	if (axl_stream_inspect (stream, "?", 1) > 0) {

		__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found '?' repetition conf");
		/* seems the content specification could appear zero
		 * or one time */
		return ZERO_OR_ONE;

	} else if (axl_stream_inspect (stream, "+", 1) > 0) {

		__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found '+' repetition conf");
		/* seems the content specification must appear one up
		 * to many */
		return ONE_OR_MANY;

	} else if (axl_stream_inspect (stream, "*", 1) > 0) {

		__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found '*' repetition conf");
		/* seems the content specification could appear zero
		 * up to many */
		return ZERO_OR_MANY;
	} 

	/* the content specification must appear */
	return ONE_AND_ONLY_ONE;
}

/** 
 * @internal
 *
 * Support function which creates a child item list, insert it to the
 * parent item list received.
 * 
 * @param parent 
 * 
 * @return 
 */
axlDtdElementList * __axl_dtd_create_and_queue (axlDtdElementList * parent)
{
	axlDtdElementList     * child;
	axlDtdElementListNode * node;
	
	/* create the DTD item list */
	child       = axl_new (axlDtdElementList, 1);

	/* make by default the item list to be defined as "not
	 * defined" until the first separator is found */
	child->type = STILL_UNDEF; 
	
	/* create a node that */
	node = __create_axl_dtd_element_list (NULL, child);

	/* create the parent list reference if weren't */
	if (parent->itemList == NULL) {
		parent->itemList = axl_list_new (axl_list_always_return_1, 
						 (axlDestroyFunc) __destroy_axl_dtd_element_list);
	}

	/* add the node */
	axl_list_add (parent->itemList, node);

	/* return the new child created */
	return child;
}

/** 
 * @internal
 *
 * Updates current chunk readed information to allow perform a better
 * code after calling this function.
 *
 */
void __axl_dtd_element_spec_update_chunk_matched (axlStream * stream, 
						  int * chunk_matched)
{
	/* check for for sequence or choice characters */
	if (axl_stream_inspect (stream, ",", 1) > 0) {
		/* flag that we have found a , (choice)
		 * separator */
		(*chunk_matched) = 1;
		
	} else if (axl_stream_inspect (stream, "|", 1) > 0) {
		/* flag that we have found a | (sequence)
		 * separator */
		(*chunk_matched) = 2;

	} else if (axl_stream_inspect (stream, ")", 1) > 0) {
		/* flag that we have found a | (sequence)
		 * separator */
		(*chunk_matched) = 3;
		
	} else if (axl_stream_inspect (stream, "+", 1) > 0) {
		/* flag that we have found a | (sequence)
		 * separator */
		(*chunk_matched) = 4;
		
	} else if (axl_stream_inspect (stream, "*", 1) > 0) {
		/* flag that we have found a | (sequence)
		 * separator */
		(*chunk_matched) = 5;
		
	} else if (axl_stream_inspect (stream, "?", 1) > 0) {
		/* flag that we have found a | (sequence)
		 * separator */
		(*chunk_matched) = 6;
	}

	return;
}

/** 
 * @internal
 *
 * Support function to read the content particule separator once the
 * repeat pattern was found 
 * 
 */
axl_bool     __axl_dtd_element_spec_update_chunk_matched_for_cp_separator (axlStream * stream, 
									   int * chunk_matched)
{
	/* consume previous white spaces */
	AXL_CONSUME_SPACES (stream);

	/* check for for sequence or choice characters */
	if (axl_stream_inspect (stream, ",", 1) > 0) {
		/* flag that we have found a , (choice)
		 * separator */
		(*chunk_matched) = 1;
		return axl_true;
		
	} else if (axl_stream_inspect (stream, "|", 1) > 0) {
		/* flag that we have found a | (sequence)
		 * separator */
		(*chunk_matched) = 2;
		return axl_true;

	} else if (axl_stream_inspect (stream, ")", 1) > 0) {
		/* flag that we have found a | (sequence)
		 * separator */
		(*chunk_matched) = 3;
		return axl_true;
	}
	
	return axl_false;
}

/** 
 * @internal
 *
 * Support function which allows to read the next content particule.
 */
char * __axl_dtd_read_content_particule (axlStream  * stream, 
					 int        * chunk_matched,
					 axlStack   * dtd_item_stack, 
					 axlError  ** error)
{
	char * string_aux;

	/* read the spec particule stopping when a white space
	 * or other character is found */
	string_aux = axl_stream_get_until (stream, NULL, chunk_matched, axl_true, 8, 
					   /* basic, default delimiters: 0, 1, 2, 3 */
					   " ", ",", "|", ")",
					   /* repetition configuration: 4, 5, 6 */
					   "+", "*", "?",
					   /* new dtd item list being opened: 8 */
					   "(");
	if (string_aux == NULL) {
		axl_error_new (-1, "Expected to find a element content specification particule, but it wasn't found",
			       stream, error);
		axl_stack_free (dtd_item_stack);
		axl_stream_free (stream);
		return NULL;
	}
	
	/* check the user doesn't nest item list in a not
	 * proper way */
	if (*chunk_matched == 8) {
		axl_error_new (-1, "Found a not proper nesting item list for a DTD element, before using ( a separator must be used (CHOICE: |, SEQUENCE: ,)",
			       stream, error);
		axl_stack_free (dtd_item_stack);
		axl_stream_free (stream);
		return NULL;
	}

	/* nullify stream internal reference */
	axl_stream_nullify (stream, LAST_CHUNK);
	
	/* return the content particule found */
	return string_aux;
}

/** 
 * @internal
 *
 * Support function which reads current <!ELEMENT specification,
 * configuring it to the received axlDtdElement.
 * 
 * @param stream The stream where the axlDtdElement spec will be read.
 *
 * @param dtd_element The axlDtdElement that will receive the content
 * spec.
 *
 * @param error An optional \ref axlError, where errors will be
 * reported.
 * 
 * @return \ref axl_true if the content spec was properly read or \ref
 * axl_false if not.
 */
axl_bool     __axl_dtd_read_element_spec (axlStream * stream, axlDtdElement * dtd_element, axlError ** error)
{
	char              * string_aux;
	axl_bool            is_pcdata;
	int                 chunk_matched = -1;
	axlStack          * dtd_item_stack;
	axlDtdElementList * dtd_item_list;
	axl_bool            is_empty;
	
	
	/* create the stack used to control which is
	 * the current context for the items read for
	 * the xml DTD especification (pd, pd2, (pr|po), ..) */
	dtd_item_stack = axl_stack_new (NULL);

	/* create the DTD item list */
	dtd_item_list       = axl_new (axlDtdElementList, 1);

	/* by default, set still undef to change it once a separator
	 * is detected or the function ends. This will help to detect
	 * problems produced by people mixing content element
	 * separators. */
	dtd_item_list->type = STILL_UNDEF; 

	/* set the content spec list to the dtd element read */
	dtd_element->list   = dtd_item_list;
	   
	/* push the item created */
	/* axl_stack_push (dtd_item_stack, dtd_item_list); */
	
	/* consume previous white spaces */
	AXL_CONSUME_SPACES (stream);

	/* check that the content specification have an ( */
	if (! (axl_stream_inspect (stream, "(", 1))) {
		axl_error_new (-1, "Expected to find a element content specification opener \"(\", but it wasn't found",
			       stream, error);
		axl_stack_free (dtd_item_stack);
		axl_stream_free (stream);		
		return axl_false;
	}
	
	do {
		/* consume previous white spaces */
		AXL_CONSUME_SPACES (stream);

		/* a new item list have been opened */
		if (axl_stream_inspect (stream, "(", 1) > 0) {

			__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a DTD item list openining: %d",
				   axl_stack_size (dtd_item_stack));

			/* a new item list is being defined, we have
			 * to queue current dtd_item_list and create a
			 * new item list */
			axl_stack_push (dtd_item_stack, dtd_item_list);
			
			/* create the DTD item list */
			dtd_item_list        = __axl_dtd_create_and_queue (dtd_item_list);

			/* let's continue at the begining */
			continue;
		}
		

		__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "iterating again to get a new content particule (item list size: %d)",
			   axl_dtd_item_list_count (dtd_item_list));

		/* read the next content particule: here is the chunk
		 * matched codes found: 
		 * basic, default delimiters: 
		 * 0, 1, 2, 3 -> " ", ",", "|", ")" 
		 * repetition configuration: 
		 * 4, 5, 6  -> "+", "*", "?",
		 * new dtd item list being opened: 
		 * 8 -> "(" */
		string_aux = __axl_dtd_read_content_particule (stream, &chunk_matched, dtd_item_stack, error);
		if (string_aux == NULL)
			return axl_false;
		
		/* check, and record, that the string read is
		 * PCDATA */
		is_pcdata = axl_cmp (string_aux, "#PCDATA");

		/* add the item read if have something defined */

		__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found content spec particule: (size: %d) '%s'", 
			   strlen (string_aux),
			   string_aux);

		/* check if the have matched a white space: next check is
		 * based on the call to axl_stream_get_until at the caller
		 * function: " " */
		if (chunk_matched == 0) {

			__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, 
				   "found white spaces as delimiter, consuming them (current chunk matched: %d)",
				   chunk_matched);
			
			/* consume previous white spaces */
			AXL_CONSUME_SPACES (stream);

			/* update current chunk_matched to conform to
			 * an stream that have all elements really
			 * close: the following function tries to read
			 * and update chunk_matched variable to point
			 * to the value read for ",", "|", "+", "*",
			 * "?" and ")" because white spaces were found */
			__axl_dtd_element_spec_update_chunk_matched (stream, &chunk_matched);


			__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, 
				   "current chunk matched before update (%d)",
				   chunk_matched);
		}

		/* add the content particule found, this function
		 * already detect that a white space was found and
		 * consumes all white spaces found */
		if (!__axl_dtd_element_content_particule_add (dtd_item_list, string_aux, chunk_matched, stream, error))
			return axl_false;

		if (chunk_matched == 4 || chunk_matched == 5 || chunk_matched == 6) {
			/* found a repetition pattern */
			if (! __axl_dtd_element_spec_update_chunk_matched_for_cp_separator (stream, &chunk_matched)) {
				axl_error_new (-1, "Before a repetition pattern (*,+,?) expected to find a content particule separator",
					       stream, error);
				axl_stack_free (dtd_item_stack);
				axl_stream_free (stream);		
				return axl_false;
			}
		}

		/* set current sequence type accoring to separators
		 * used */
		switch (chunk_matched) {
		case 1:
			if (dtd_item_list->type == CHOICE) {
				axl_error_new (-1, "Detected that the DTD definition is mixing content particules separators at the same level ('|' and ','). First detected a sequence spec (,) but then detected a choice element (|)",
					       stream, error);
				axl_stack_free (dtd_item_stack);
				axl_stream_free (stream);		
				return axl_false;
			}
			dtd_item_list->type = SEQUENCE;
			break;
		case 2:
			if (dtd_item_list->type == SEQUENCE) {
				axl_error_new (-1, "Detected that the DTD definition is mixing content particules separators at the same level ('|' and ','). First detected a choice spec (|) but then detected a sequence element (,)",
					       stream, error);
				axl_stack_free (dtd_item_stack);
				axl_stream_free (stream);		
				return axl_false;
			}
			dtd_item_list->type = CHOICE;
			break;
		}

		/* set element type if a element list terminator was
		 * found ( 3 = ')' = chunk_matched) */
		if ((chunk_matched == 3) && is_pcdata) {
			if (axl_list_length (dtd_item_list->itemList) == 1)
				dtd_element->type = ELEMENT_TYPE_PCDATA;
			else if (axl_list_length (dtd_item_list->itemList) > 1)
				dtd_element->type = ELEMENT_TYPE_MIXED;
		}

		/* pop current element list header */
		if (chunk_matched == 3) {
			do {
				__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a DTD item list termination: stack status: %d",
					   axl_stack_size (dtd_item_stack));
				/* consume previous white spaces */
				AXL_CONSUME_SPACES (stream);
				dtd_item_list->times = __axl_dtd_get_repetition_conf (stream);

				/* consume previous white spaces */
				AXL_CONSUME_SPACES (stream);

				if (axl_stream_inspect (stream, ",", 1) > 0) {
					__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a sequence (,) separator while reading terminator list");

					chunk_matched = 1;
				}
				else if (axl_stream_inspect (stream, "|", 1) > 0) {
					__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a choice (|) separator while reading terminator list");
					chunk_matched = 2;
				}
				
				/* this means that a ) was found, we have to
				 * pop current queue */
				is_empty              = axl_stack_is_empty (dtd_item_stack);
				if (! is_empty) {
					dtd_item_list = axl_stack_pop (dtd_item_stack);
					__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "getting the next item list in the stack, stack status: %d",
						   axl_stack_size (dtd_item_stack));
				}

				/* special case: check if the next element to
				 * be read is a new ) */
				/* consume previous white spaces */
				AXL_CONSUME_SPACES (stream);

			}while ((axl_stream_inspect (stream, ")", 1) > 0) && !is_empty);

			/* drop a log */
			__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "terminator sequence status: chunk matched=%d ans stack status: %d",
				   chunk_matched, axl_stack_size (dtd_item_stack));

		}

		/* check if we have finished */
	} while (chunk_matched != 3 || (! axl_stack_is_empty (dtd_item_stack)));


	__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "content spec terminated, now lookup for the termination");
		
	/* consume previous white spaces */
	/* AXL_CONSUME_SPACES (stream);*/

	/* read here repetition specification */
	/* dtd_item_list->times = __axl_dtd_get_repetition_conf (stream); */
	
	/* set default content element separator */
	if (dtd_item_list->type == STILL_UNDEF)
		dtd_item_list->type = SEQUENCE;
		
	/* free the stack used */
	axl_stack_free (dtd_item_stack);


	__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "DTD content element specification found and parsed ok");


	/* content spec readed properly */
	return axl_true;
}

/** 
 * @internal
 * 
 * Calculates the number of nodes to be matched at minimum for the
 * provided DTD element. 
 * 
 * @param element The DTD element to configure with its minimum item
 * count to be matched.
 */
int __axl_dtd_parse_element_get_compulsory_num (axlDtdElementList * list)
{
	axlDtdElementListNode * itemNode;
	int                     count    = 0;
	int                     iterator = 0;

	/* check for null parameters */
	if (list == NULL)
		return 0;

	/* only count for repetitiong patterns that makes obligatory
	 * to have childs */
	if (list->times == ONE_AND_ONLY_ONE ||
	    list->times == ONE_OR_MANY) {
		
		while (iterator < axl_list_length (list->itemList)) {
			/* get the reference for the item node */
			itemNode = axl_list_get_nth (list->itemList, iterator);
			
			/* check if the repetitiong patter is
			 * compulsory */
			if (itemNode->times == ONE_OR_MANY ||
			    itemNode->times == ONE_AND_ONLY_ONE) {
				/* check if we have an itemNode that has an
				 * Node or a list */
				if (itemNode->type == AXL_ELEMENT_NODE) {
					/* we have an item node */
					count++;
					if (list->type == CHOICE) {
						/* because we have a
						 * choice list, once
						 * validated one item,
						 * it is the minimum
						 * requirement. */
						return count;
					}
				} else {
					/* we have a list */
					count += __axl_dtd_parse_element_get_compulsory_num (itemNode->data);
				}
			}
			
			/* update the index */
			iterator++;
		}
	}
		
	/* return current count */
	return count;
}


/** 
 * @internal
 *
 * Parses a document type element that it is expected to be found at
 * the given stream.
 * 
 * @param dtd The axlDtd where the element type readed must be added.
 *
 * @param stream The stream where the element type if expected to be found.
 *
 * @param error An axlError, optional, reference where error will be
 * reported.
 * 
 * @return axl_true if the element was parsed properly, axl_false if
 * not. The stream associated will be unrefered and the axlError
 * provided will be filled if an error is found.
 */
axl_bool     __axl_dtd_parse_element (axlDtd * dtd, axlStream * stream, axlError ** error)
{
	char              * string_aux;
	int                 matched_chunk = -1;
	axlDtdElement     * element;

	/* init the dtd element list */
	if (dtd->elements == NULL)
		dtd->elements = axl_list_new (axl_list_always_return_1, (axlDestroyFunc) axl_dtd_element_free);

	/* consume previous white spaces */
	AXL_CONSUME_SPACES (stream);

	/* get for the first element declaration */
	if (! (axl_stream_inspect (stream, "<!ELEMENT", 9) > 0)) {
		axl_error_new (-1, "Expected to receive a <!ELEMENT, but it wasn't found", stream, error);
		axl_stream_free (stream);
		return axl_false;
	}

	/* consume previous white spaces */
	AXL_CONSUME_SPACES (stream);
	
	/* get the element name */
	string_aux = axl_stream_get_until (stream, NULL, &matched_chunk, axl_false, 3, ">", "(", " ", "<!ELEMENT");
	if (string_aux == NULL) {
		axl_error_new (-1, "Expected to receive a DTD element name for <!ELEMENT declaration, but not found", stream, error);
		axl_stream_free (stream);
		return axl_false;
	}

	/* check that the DTD have an element name and an element type */
	if ((matched_chunk == 0) || (matched_chunk == 3)) {
		axl_error_new (-1, "Found a DTD <!ELEMENT declaration, without content specification. Missing value, examples: EMPTY, ANY, (..)", stream, error);
		axl_stream_free (stream);
		return axl_false;
	}

	/* nullify internal stream content */
	axl_stream_nullify (stream, LAST_CHUNK);
	
	/* create the DTD element */
	element           = axl_new (axlDtdElement, 1);
	element->name     = string_aux;

	/* consume previous white spaces */
	AXL_CONSUME_SPACES (stream);

	/* now, check for the basic cases: ANY and EMPTY */
	if (axl_stream_peek (stream, "EMPTY", 5) > 0) {
		/* accept previous peek */
		axl_stream_accept (stream);

		/* found empty declaration */
		element->type = ELEMENT_TYPE_EMPTY;

	} else if (axl_stream_peek (stream, "ANY", 3) > 0) {
		/* accept previous peek */
		axl_stream_accept (stream);

		/* found any declaration */
		element->type = ELEMENT_TYPE_ANY;
	} else {
		/* complex element type declaration, let's roll now
		 * get the element content type read current dtd
		 * element spec. 
		 *
		 * By default, any comple element type definition,
		 * have childrens, until PC data definition is found,
		 * which leads to the two possible values: Mixed and
		 * PcData */
		element->type = ELEMENT_TYPE_CHILDREN;
		if (!__axl_dtd_read_element_spec (stream, element, error))
			return axl_false;
	}

	/* add element found */
	if (! __axl_dtd_add_element (dtd, element, stream, error))
		return axl_false;
	
	/* consume previous white spaces */
	AXL_CONSUME_SPACES (stream);

	/* check for the last DTD declaration */
	if (! (axl_stream_inspect (stream, ">", 1))) {
		axl_error_new (-1, "Unable to find last, > terminator for the DTD <!ELEMENT declaration", stream, error);
		axl_stream_free (stream);
		return axl_false;
	}

	/* now, count the number of obligatory elements, required for
	 * the validation process */
	element->minimum_match = __axl_dtd_parse_element_get_compulsory_num (element->list);

	__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found DTD element declaration read complete: minimum matching elements: %d",
		   element->minimum_match);

	/* element type declaration completely read */
	return axl_true;
}

/** 
 * @internal
 * 
 * Destroy the provided reference and its associated data.
 * 
 * @param decl The reference declaration.
 */
void axl_dtd_attribute_decl_free (axlDtdAttributeDecl * decl)
{
	/* free the rule name */
	if (decl->name != NULL)
		axl_free (decl->name);

	/* free the default value */
	if (decl->default_value != NULL)
		axl_free (decl->default_value);

	/* free enum declaration list if defined */
	if (decl->enumvalues != NULL)
		axl_list_free (decl->enumvalues);

	/* free the node itself */
	axl_free (decl);
	
	/* nothing more to do */
	return;
}

/** 
 * @internal function to dealloc an single attribute set decleration.
 * 
 * @param attribute The reference to dealloc.
 */
void axl_dtd_attribute_free (axlDtdAttribute * attribute)
{
	/* free the attribute list, name and the node itself */
	axl_free (attribute->name);
	axl_list_free (attribute->list);
	axl_free (attribute);

	return;
}

axl_bool __find_attr_decl (axlPointer _element, axlPointer data)
{
	axlDtdAttributeDecl * decl = _element;
	char                * name = data;

	/* check the name */
	if (axl_cmp (decl->name, name))
		return axl_true;

	/* it is not the element */
	return axl_false;
}

/** 
 * @brief Allows to check if the stream contains a reference to a
 * entity, calling the resolver to get the replacement text to be
 * placed.
 * 
 * @param resolver The function to be called with the replacement
 * text. This function must return the replacement text or NULL if it
 * fails. Failing to return a reference resolution will make the
 * entity reference to appear as is.
 *
 * @param resolver The entity reference resolver function to be called
 * to solve references found.
 *
 * @param data User defined data provided to the function, passed
 * directly to the resolver function once executed.
 *
 * @param stream The stream where the entity reference could appear.
 *
 * @param prefix The reference prefix to recognize. Values allowed
 * are: % (DTD references) and & (general entity references).
 *
 * @param error Optional reference to the axlError to report textual
 * diagnostic errors.
 *
 * @return The function return \ref axl_false if some error while
 * resolving entity references was found. Otherwise the function
 * return axl_true.
 */
axl_bool axl_dtd_check_entity_ref_and_expand (axlDtdEntityResolver   resolver, 
					      axlPointer             data,
					      axlStream            * stream, 
					      const char           * prefix,
					      axlError            ** error)
					  
{
	char       * string_aux;
	char       * new_value;
	int          index;

	/* check if we have an entity reference using the provided prefix */
	index = axl_stream_get_index (stream);
	if (! (axl_stream_inspect (stream, prefix, 1) > 0))
		return axl_true;

	/* get the entity reference until the end */
	string_aux = axl_stream_get_until (stream, NULL, NULL, axl_true, 1, ";");
	if (string_aux == NULL) {
		axl_error_new (-1, "null value received while expecting to find the entity reference to resolve.", stream, error);
		axl_stream_free (stream);
		return axl_false;
	} /* end if */

	axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found entity reference: %s%s;...resolving", prefix, string_aux);

	/* resolve the reference */
	new_value = (char *) resolver (string_aux, data);
	if (new_value == NULL) {
		axl_stream_move (stream, index);
		return axl_true;
	} /* end if */

	/* accept content consumed */
	axl_stream_accept (stream);

	axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "entity resolved to: %s", new_value);

	/* place the replacement data at the start of the stream */
	new_value = axl_strdup_printf ("%s ", new_value);
	axl_stream_push (stream, new_value, strlen (new_value));
	axl_free (new_value);
	
	return axl_true;
}

/** 
 * @internal Entity resolver used by __axl_dtd_parse_attlist.
 */
const char * __axl_dtd_entity_resolver (const char * entityName, axlPointer data)
{
	/* return the entity resolution */
	return axl_dtd_entity_value ((axlDtd *) data, entityName, PARAMETER_ENTITY);
} /* end if */

axlList * __axl_dtd_parse_enumvalues (const char * _enum_values)
{
	char    ** result;
	int        iterator;
	axlList  * list;

	result   = axl_stream_split (_enum_values, 1, "|");
	iterator = 0;
	list     = axl_list_new (axl_list_always_return_1, axl_free);

	
	while (result[iterator]) {
		/* clean the enum value */
		axl_stream_trim (result[iterator]);

		/* add to the list */
		axl_list_add (list, axl_strdup (result[iterator]));

		/* update the iterator value */
		iterator++;

	} /* end while */
	
	/* free tokens */
	axl_stream_freev (result);
	
	/* return the list */
	return list;
}

/** 
 * @internal function used by \ref axl_dtd_attr_validation function to
 * lookup ATTLIST contraints flaged as unique ID.
 */
axl_bool __find_id_decl (axlPointer _element, axlPointer data)
{
	/* return the comparision */
	return (((axlDtdAttributeDecl *) _element)->type == TOKENIZED_TYPE_ID);
	
} /* end __find_id_decl */


/** 
 * @internal
 * 
 * Parse the <!ATTLIST decleration, registering it into the provided
 * dtd element.
 */
axl_bool __axl_dtd_parse_attlist (axlDtd * dtd, axlStream * stream, axlError ** error)
{
	char                * string_aux    = NULL;
	int                   matched_chunk = -1;
	axlDtdAttribute     * attribute     = NULL;
	axlDtdAttributeDecl * decl          = NULL;
	axlDtdAttributeDecl * declAux       = NULL;
	char                * err_msg;

	/* init the dtd attr list */
	if (dtd->attributes == NULL)
		dtd->attributes = axl_list_new (axl_list_always_return_1, (axlDestroyFunc) axl_dtd_attribute_free);

	/* consume previous white spaces */
	AXL_CONSUME_SPACES (stream);

	/* get the element name */
	string_aux = axl_stream_get_until (stream, NULL, &matched_chunk, axl_false, 1, " ");
	if (string_aux == NULL) {
		axl_error_new (-1, "Expected to receive a DTD attribute name for <!ATTLIST declaration, but not found", stream, error);
		axl_stream_free (stream);
		return axl_false;
	}

	axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found dtd attr declaration for node: <%s>", string_aux);

	/* find the node that holds all attr declarations for the node found */
	attribute         = axl_dtd_get_attr (dtd, string_aux);

	/* check if found */
	if (attribute == NULL) {
		/* create the axlDtdAttribute holder */
		attribute = axl_new (axlDtdAttribute, 1);

		/* record the node to which the list of rules applies */
		axl_stream_nullify (stream, LAST_CHUNK);
		attribute->name   = string_aux;

		/* init the attribute rule list */
		attribute->list   = axl_list_new (axl_list_always_return_1, (axlDestroyFunc) axl_dtd_attribute_decl_free);

		/* now configure this new attribute inside the dtd */
		axl_list_add (dtd->attributes, attribute);
	} /* end if */

	/* now get the list of attributes */
	while (1) {
		axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "finding next att declaration");

		/* consume previous white spaces */
		AXL_CONSUME_SPACES (stream);

		/* check if we have finished */
		if (axl_stream_inspect (stream, ">", 1) > 0)
			break;

		/* get the attribute name the rules applies */
		string_aux = axl_stream_get_until (stream, NULL, &matched_chunk, axl_false, 1, " ");
		if (string_aux == NULL) {
			axl_error_new (-1, "Expected to receive an attribute name for <!ATTLIST declaration, but not found", stream, error);
			axl_stream_free (stream);
			return axl_false;
		}

		/* nully the string and store it new rule created */
		axl_stream_nullify (stream, LAST_CHUNK);

		/* create a new attribute single constraint */
		decl            = axl_new (axlDtdAttributeDecl, 1);
		decl->name      = string_aux;

		/* add the attribute constraint to the list */
		axl_list_add (attribute->list, decl);

		axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "find constraint for attribute name=%s", decl->name);

		/* consume previous white spaces */
		AXL_CONSUME_SPACES (stream);

		axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "checking constraint type..");

		/* check for an entity reference and expand the stream
		 * content with its resolution */
		if (! axl_dtd_check_entity_ref_and_expand (__axl_dtd_entity_resolver, dtd, stream, "%", error))
			return axl_false;

		axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "about to check attr constraint type, stream status: '%s'",
			 axl_stream_get_following (stream, 30));
		
		/* now check the contraint type */
		if (axl_stream_inspect (stream, "NOTATION", 8) > 0) {
			/* parse notation declaration */
		}else if (axl_stream_inspect (stream, "(", 1) > 0) {
			/* parse enum declaration */
			string_aux = axl_stream_get_until (stream, NULL, &matched_chunk, axl_true, 1, ")");
			if (string_aux == NULL) {
				axl_error_new (-1, "expected to find enum declaration but termination caracter ')' was not found", stream, error);
				axl_stream_free (stream);
				return axl_false;
			} /* end if */
			decl->type       = ENUMERATION_TYPE;
			decl->enumvalues = __axl_dtd_parse_enumvalues (string_aux);
		}else {
			/* set the attribute type */
			if (axl_stream_inspect (stream, "CDATA", 5) > 0) {
				decl->type = CDATA_ATTRIBUTE;
			} else if (axl_stream_inspect (stream, "IDREFS", 6) > 0) {
				
				/* flag the type */
				decl->type = TOKENIZED_TYPE_IDREFS;

				/* flag the dtd to have a IDREF declaration */
				dtd->haveIdRefDecl = axl_true;
			} else if (axl_stream_inspect (stream, "IDREF", 5) > 0) {
				/* notify type found */
				decl->type = TOKENIZED_TYPE_IDREF;

				/* flag the dtd to have a IDREF declaration */
				dtd->haveIdRefDecl = axl_true;
				
			} else if (axl_stream_inspect (stream, "ID", 2) > 0) {
				
				/* notify the type found */
				decl->type      = TOKENIZED_TYPE_ID;

				/* flag the dtd to have a ID declaration */
				dtd->haveIdDecl = axl_true;
				
			} else if (axl_stream_inspect (stream, "ENTITY", 6) > 0)
				decl->type = TOKENIZED_TYPE_ENTITY;
			else if (axl_stream_inspect (stream, "ENTITIES", 8) > 0)
				decl->type = TOKENIZED_TYPE_ENTITIES;
			else if (axl_stream_inspect (stream, "NMTOKENS", 8) > 0)
				decl->type = TOKENIZED_TYPE_NMTOKENS;
			else if (axl_stream_inspect (stream, "NMTOKEN", 7) > 0)
				decl->type = TOKENIZED_TYPE_NMTOKEN;
			else {
				axl_error_new (-1, "Unrecognied attr type declaration found, check your <!ATTLIST declaration", stream, error);
				axl_stream_free (stream);
				return axl_false;
			} /* end if */
		} /* end if */

		/* consume previous white spaces */
		AXL_CONSUME_SPACES (stream);

		axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "checking default value declaration, stream status: '%s'",
			 axl_stream_get_following (stream, 30));

		/* get default declaration value */
		if (axl_stream_inspect (stream, "#REQUIRED", 9) > 0) {
			decl->defaults = ATT_REQUIRED;
		} else if (axl_stream_inspect (stream, "#IMPLIED", 8) > 0) {
			decl->defaults = ATT_IMPLIED;
		} else {
			decl->defaults = ATT_IMPLIED;
			if (axl_stream_inspect (stream, "#FIXED", 6) > 0) {
				decl->defaults = ATT_FIXED;

				/* consume previous white spaces */
				AXL_CONSUME_SPACES (stream);
			}

			/* check default value for this case */
			if (! (axl_stream_peek (stream, "\"", 1) > 0 ||
			       axl_stream_peek (stream, "'", 1) > 0)) {
				err_msg = axl_strdup_printf ("Unable to find default attribute declaration (#REQUIRED, #IMPLIED, #FIXED)  for attribute %s, node <%s>",
							     decl->name, attribute->name);
				axl_error_new (-1, err_msg, stream, error);
				axl_stream_free (stream);
				axl_free (err_msg);
				return axl_false;
			} /* end if */
		} /* end if */

		/* check constraint for ID types */
		if (decl->type == TOKENIZED_TYPE_ID) {
			/* check that the node doesn't have any unique
			 * id declared */

			/* check if the node have TOKENIZED_TYPE_ID */
			declAux = axl_list_lookup (attribute->list, __find_id_decl, NULL);
			if (declAux != NULL && !axl_cmp (declAux->name, decl->name)) {
				err_msg = axl_strdup_printf ("Found ATTLIST declaration, with several ID declarations <ATTLIST %s %s..",
							     attribute->name, decl->name);
				axl_error_new (-1, err_msg, stream, error);
				axl_stream_free (stream);
				axl_free (err_msg);
				return axl_false;
			} /* end if */
			
			/* check required and implied */
			if (decl->defaults != ATT_REQUIRED && decl->defaults != ATT_IMPLIED) {
				err_msg = axl_strdup_printf ("Found ATTLIST declaration, with ID, that don't have configured either #IMPLICIT or #REQUIRED for attribute %s, node <%s>",
							     decl->name, attribute->name);
				axl_error_new (-1, err_msg, stream, error);
				axl_stream_free (stream);
				axl_free (err_msg);
				return axl_false;
			} /* end if */
		} /* end if */

		/* consume previous white spaces */
		AXL_CONSUME_SPACES (stream);

		/* nullify to check this value later */
		string_aux = NULL;
		if (axl_stream_inspect (stream, "\"", 1) > 0) {
			/* get until */
			string_aux = axl_stream_get_until (stream, NULL, NULL, axl_true, 1, "\"");
		} else if (axl_stream_inspect (stream, "'", 1) > 0) {
			/* get until */
			string_aux = axl_stream_get_until (stream, NULL, NULL, axl_true, 1, "\'");
		} /* end if */

		/* check if default value was found */
		if (string_aux != NULL) {

			/* found default value, check if we have an
			 * enumeration type, enforcing that the value
			 * defined to be inside the enumeration */
			if (decl->type == ENUMERATION_TYPE) {
				if (axl_list_lookup (decl->enumvalues, axl_list_find_string, string_aux) == NULL) {
					axl_error_new (-1, 
						       "Configured a default value for an attribute list which only accepts a set of enum values that do not containt it.",
						       stream, error);
					axl_stream_free (stream);
					return axl_false;
				} /* end if */
			} /* end if */

			/* nullify value and make string_aux to be
			 * owned by the axlDtdAttributeDecl
			 * reference */
			axl_stream_nullify (stream, LAST_CHUNK);
			decl->default_value = string_aux;
		} /* end if */

	} /* end while */
       	
	/* properly parsed */
	return axl_true;
}

/** 
 * @internal
 * 
 * Destroy the provided entity reference and all allocated memory.
 * 
 * @param entity The entity the deallocate.
 */
void axl_dtd_entity_free (axlDtdEntity * entity)
{
	/* the entity reference */
	axl_return_if_fail (entity);

	/* free the entity name */
	if (entity->name)
		axl_free (entity->name);
	
	/* free the content */
	if (entity->content)
		axl_free (entity->content);

	/* free external data if defined */
	if (entity->data) {
		/* free system literal */
		if (entity->data->system_literal)
			axl_free (entity->data->system_literal);
		
		/* free public literal */
		if (entity->data->public_literal)
			axl_free (entity->data->public_literal);

		/* free ndata literal */
		if (entity->data->ndata)
			axl_free (entity->data->ndata);

		/* free the node itself */
		axl_free (entity->data);
	}

	/* free the node */
	axl_free (entity);

	return;
}

/** 
 * @internal
 *
 * Parses an entity definition from the current status of the stream
 * provided.
 */
axl_bool __axl_dtd_parse_entity (axlDtd * dtd, axlStream * stream, axlError ** error)
{
	char         * string_aux;
	int            matched_chunk;
	axlDtdEntity * entity;

	/* init the dtd element list */
	if (dtd->entities == NULL)
		dtd->entities = axl_list_new (axl_list_always_return_1, (axlDestroyFunc) axl_dtd_entity_free);
	
	/* consume previous white spaces */
	AXL_CONSUME_SPACES (stream);

	/* get for the first element declaration */
	if (! (axl_stream_inspect (stream, "<!ENTITY", 8) > 0)) {
		axl_error_new (-1, "Expected to receive a <!ENTITY, but it wasn't found", stream, error);
		axl_stream_free (stream);
		return axl_false;
	}

	/* consume previous white spaces */
	AXL_CONSUME_SPACES (stream);

	/* create a new entity */
	entity = axl_new (axlDtdEntity, 1);

	/* set the entity and return axl_true */
	axl_list_add (dtd->entities, entity);

	/* check for parameter entity definition */
	if (axl_stream_inspect (stream, "%", 1) > 0) {
		/* set the entity type */
		entity->type = PARAMETER_ENTITY;
		
		/* consume previous white spaces */
		AXL_CONSUME_SPACES (stream);

	} else
		entity->type = GENERAL_ENTITY;

	/* get the element name */
	string_aux = axl_stream_get_until (stream, NULL, &matched_chunk, axl_false, 1, " ");
	if (string_aux == NULL) {
		axl_error_new (-1, "Expected to receive a DTD entity name for <!ENTITY declaration, but not found", stream, error);
		axl_stream_free (stream);
		return axl_false;
	}

	/* set the name */
	axl_stream_nullify (stream, LAST_CHUNK);
	entity->name = string_aux;

	/* consume previous white spaces */
	AXL_CONSUME_SPACES (stream);

	/* now check if we have an external reference */
	if (axl_stream_inspect (stream, "PUBLIC", 6) > 0) {
		/* we have a public external resource definition */
		
	}else if (axl_stream_inspect (stream, "SYSTEM", 6) > 0) {
		/* we have a system definition */
		
	}else {
		/* we have a plain value get the content remove next "
		   and ' if defined */
		if (! ((axl_stream_inspect (stream, "\"", 1) > 0))) {
			if (! (axl_stream_inspect (stream, "\'", 1) > 0)) {
				axl_error_new (-2, "Expected to find entity value initiator (\") or ('), every entity value must start with them", 
					       stream, error);
				axl_stream_free (stream);
				return axl_false;
			}
			/* knowing that ' was matched, now get the attribute value */
			string_aux = axl_stream_get_until (stream, NULL, &matched_chunk, axl_true, 1, "'");
		}else {
			/* knowhing that " was matched, now get the attribute value */
			string_aux = axl_stream_get_until (stream, NULL, &matched_chunk, axl_true, 1, "\"");
		}

		__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "entity value found: [%s]", string_aux);
		
		/* nullify internal reference so we have the
		 * only one reference to entity content value
		 * inside string_aux */
		axl_stream_nullify (stream, LAST_CHUNK);

		/* set the value */
		entity->content = string_aux;
	}

	/* consume previous white spaces */
	AXL_CONSUME_SPACES (stream);

	/* check last item to parse */
	if (! (axl_stream_inspect (stream, ">", 1) > 0)) {
		axl_error_new (-2, "Expected to find entity definition terminator (>), but it wasn't found", 
			       stream, error);
		axl_stream_free (stream);
		return axl_false;
	}

	return axl_true;
}


/** 
 * @internal
 * 
 * Implements DTD parsing, reading it from a direct buffer, or a file
 * path or a file handle.
 */
axlDtd * __axl_dtd_parse_common (const char * entity, int entity_size, 
				 const char * file_path, int fd_handle, 
				 axlError ** error)
{
	axlStream * stream;
	axlDtd    * dtd;
	int         iterator;
	
	/* create the stream associated */
	stream = axl_stream_new (entity, entity_size, file_path, fd_handle, error);
	axl_return_val_if_fail (stream, NULL);

	dtd    = __axl_dtd_new ();
	axl_stream_link (stream, dtd, (axlDestroyFunc) axl_dtd_free);

	iterator = 0;
	while (axl_stream_remains (stream)) {
		/* get rid from comments found */
		if (! axl_doc_consume_comments (NULL, stream, error))
			return NULL;
		
		/* check for element declaration */
		if (axl_stream_peek (stream, "<!ELEMENT", 9) > 0) {
			__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found DTD element declaration");
			/* found element declaration */
			if (! __axl_dtd_parse_element (dtd, stream, error))
				return NULL;
			
			continue;

		}

		/* check for attribute list declarations */
		if (axl_stream_inspect (stream, "<!ATTLIST", 9) > 0) {
			__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found DTD attribute list declaration");

			/* parse it */
			if (! __axl_dtd_parse_attlist (dtd, stream, error))
				return NULL;
			
			continue;
		}

		/* check for the entity declaration */
		if (axl_stream_peek (stream, "<!ENTITY", 8) > 0) {
			__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found DTD entity declaration");

			/* parse the entity definition */
			if (! __axl_dtd_parse_entity (dtd, stream, error))
				return NULL;

			continue;
		}

		/* stop the loop */
		if (iterator == 3) {
			axl_error_new (-1, "unable to process DTD content, unable to find expected information (no <!ELEMENT, <!ATTLIST or <!ENTITY declaration)", stream, error);
			axl_stream_free (stream);
			return NULL;
		}
		iterator++;
	}


	__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "DTD elements totally loaded, building references..");

	/* update current root reference, the DTD root for the DTD
	 * document already parsed */
	if (dtd->elements != NULL) 
		dtd->root = __axl_dtd_get_new_root (dtd);

	/* check if the DTD has ID declarations if found IDREF
	 * declarations */
	if (! dtd->haveIdDecl && dtd->haveIdRefDecl) {
		axl_error_new (-1, "DTD semantic error, found IDREF attribute declaration but no attribute ID declaration was found.", stream, error);
		axl_stream_free (stream);
		return NULL;
	}
	
	__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "DTD load COMPLETE");

	axl_stream_unlink (stream);
	axl_stream_free (stream);
	return dtd;
}

/** 
 * @brief Allows to parse the provided entity, which is expected to
 * contain a DTD (Document Type Definition).
 * 
 * @param entity The document type definition to parse.
 *
 * @param entity_size The document size, or -1 to make the function to
 * figure out current size.
 *
 * @param error An optional \ref axlError where errors will be reported.
 * 
 * @return A newly allocated \ref axlDtd that must be deallocated when
 * no longer need with \ref axl_dtd_free. The function could return
 * NULL on failure detected. On that case, it is requred to check \ref
 * axlError variable, if defined.
 */
axlDtd   * axl_dtd_parse (const char * entity, 
			  int          entity_size,
			  axlError ** error)
{

	return __axl_dtd_parse_common (entity, entity_size, NULL, -1, error);
}

/** 
 * @brief Allows to parse the provided DTD definition, which is found
 * on the provided file path.
 * 
 * @param file_path The file path where it is expected to receive a
 * DTD file.
 *
 * @param error An optional \ref axlError reference where all errors found will be reported.
 * 
 * @return A newly allocated \ref axlDtd instance or NULL if it fails.
 *
 * <b>Making a DTD to be inline loaded: </b><br>
 * 
 * It may be helpful to make the DTD definition available at your
 * binary, inline compiled, to avoid distributing DTD files along with
 * libraries, etc. This also solves installation problems like
 * provisioning a default location to make your application to find
 * such files.
 *
 * With the following command you can create an inline representation
 * from your DTD file:
 * \code
 * >> axl-knife --input your-file.dtd --dtd-to-c --output your-file.dtd.h --ifnewer
 * \endcode
 *
 * This will create a header with an C-macro style definition of your
 * DTD. Now, you can include it using:
 *
 * \code
 * #include <your-file.dtd.h>
 * \endcode
 *
 * In the case you are developing a library, it is recommended to do
 * such include at the body implementation (usually .c or .cpp files,
 * to avoid requiring your API consumers to also include your DTD
 * inline definition). 
 *
 * Now, to load your DTD file, use the following:
 *
 * \code
 * axlError * err = NULL;
 * axlDtd   * dtd = axl_dtd_parse (YOUR_FILE_DTD, -1, &err);
 * if (dtd == NULL) {
 *    // This won't happen unless axl-runtime error found, since axl-knife 
 *    // checks your dtd file before producing the in-line definition.
 *    // However, bug happens! check this.
 * }
 * \endcode
 */
axlDtd   * axl_dtd_parse_from_file (const char * file_path,
				    axlError ** error)
{
	return __axl_dtd_parse_common (NULL, -1, file_path, -1, error);
}


/** 
 * @internal
 * 
 * Support function for axl_dtd_validate which checks if the provided
 * parent have its childs configuration according to the values
 * expresed on the sequenced represented by the itemList.
 *
 * The function return axl_true if the validation was ok, or axl_false
 * if something have failed. It also creates an error, using the
 * optional axlError reference received.
 */
axl_bool     __axl_dtd_validate_sequence (axlNode            * parent, 
					  int                * child_position,
					  axlDtdElementList  * itemList, 
					  axlError          ** error,
					  axl_bool             try_match,
					  axl_bool             top_level)
{
	int                      iterator        = 0;
	int                      child_pos       = *child_position;
	axlNode                * node;
	axlDtdElementListNode  * itemNode;
	axl_bool                 status          = axl_false;
	axl_bool                 one_matched;
	AxlDtdTimes              times;
	

	axl_return_val_if_fail (parent, axl_false);
	axl_return_val_if_fail (itemList, axl_false);


	__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "validating a sequence list: iterator=%d, item list count=%d, at child position=%d",
		 iterator, axl_dtd_item_list_count (itemList), child_pos);

	/* iterate over the sequence, checking its order */
	while (iterator < axl_dtd_item_list_count (itemList)) {
		
		__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "getting next item node from the DTD item list at: %d",
			 iterator);
		
		/* get the item node specification */
		itemNode    = axl_dtd_item_list_get_node (itemList, iterator);
		one_matched = axl_false;
		times       = axl_dtd_item_node_get_repeat (itemNode);

		do {

			__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "getting node at child position: %d",
				   child_pos);

			/* get the node that is located at the same position
			 * than the sequence */
			if (child_pos < axl_node_get_child_num (parent)) {
				node     = axl_node_get_child_nth (parent, child_pos);
			} else
				node     = NULL;

			/* the node child list have ended, check if
			 * this situation was expected */
			if (node == NULL) {
				__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "no more child nodes to validate at %d, for parent: %s, times: %d, iterator: %d, item count: %d",
					   child_pos, axl_node_get_name (parent), times,
					   iterator, axl_dtd_item_list_count (itemList));
				/* check if we were working with a
				 * list, which have matched at least
				 * one item */
				if (times == ONE_OR_MANY && one_matched && status) {
					if ((iterator + 1) == axl_dtd_item_list_count (itemList)) {
						*child_position = child_pos;
						__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "sequence validated with child position (III): %d", child_pos);
						return axl_true;
					} 

					/* reached this point we have
					   matched a one to many with
					   at least one match */
					break;
				}
				
				/* check that the rest of the
				 * specification item is optional,
				 * including the one used */
				status = axl_true;
				do {
					if (times != ZERO_OR_MANY &&
					    times != ZERO_OR_ONE) {

						__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found item, inside the DTD item list, that is not optional: %d (repeat value: %d)", 
							   iterator, times);
						status = axl_false;
						break;
					}

					/* update index and get the next item */
					iterator++;
					if (iterator < axl_dtd_item_list_count (itemList))
						itemNode = axl_dtd_item_list_get_node (itemList, iterator);
				}while (status && (iterator < axl_dtd_item_list_count (itemList)));

				/* check status before checking the rest of the item spec */
				if (status) {
					*child_position = child_pos;

					__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "sequence validated with child position (II): %d", child_pos);

					return axl_true;
				}
				
				/* check if a try match is being runned */
				if (! try_match) {
					axl_error_report (error, -1 , 
						       "Found that DTD specifies more nodes to be hold by the parent (<%s>), but no more childs were found",
						       axl_node_get_name (parent));
				}

				__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found that no nodes left to satisfy DTD validation operation");
				*child_position = child_pos;
				return axl_false;
			}

			/* check node type */
			if (axl_dtd_item_node_get_type (itemNode) == AXL_ELEMENT_LIST) {

				__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "the item node is an item list, dtd item list position: %d, child position: %d=<%s>",
					 iterator, child_pos, axl_node_get_name (node));

				/* element list found, validate its content */
				if (! __axl_dtd_validate_item_list (axl_dtd_item_node_get_list (itemNode),
								    parent, &child_pos, error, axl_false)) {
					__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "sub item list validation have failed (not critical)");
					/* check if we are the top
					 * level list and the itemNode
					 * checked is the last one
					 * item on the item list */
					if (top_level && ((iterator + 1) == axl_node_get_child_num (parent))) {
						__axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "found that the last item list wasn't matched");
						
					}

					*child_position = child_pos;
					return axl_false;
				}

				__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "validated item list, child position after: %d",
					   child_pos);
				/* because child position updating and
				 * repeat matching is already handled
				 * by dtd_validate_item_list function
				 * we just continue with the next
				 * iteration */
				break;

			} else if (axl_dtd_item_node_get_type (itemNode) == AXL_ELEMENT_NODE) {
				/* check the name against the spec */

				__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, 
					   "the item node is a final content particule definition: %s",
					   axl_dtd_item_node_get_value (itemNode));

				status = NODE_CMP_NAME (node, axl_dtd_item_node_get_value (itemNode));
			}

			/* check previous status */
			if ((times == ONE_AND_ONLY_ONE) || 
			    (times == ONE_OR_MANY && one_matched == axl_false)) {
				if (! status) {
					/* only report an upper level
					 * error if we are not running
					 * a try match */
					if (! try_match) {

						__axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, 
							   "Found different node (<%s>) for a sequence expected (<%s>), at child position: %d, item list pos: %d",
							   axl_node_get_name (node), 
							   axl_dtd_item_node_get_value (itemNode),
							   child_pos, iterator);
						axl_error_report (error, -1, 
								  "Found different node (<%s>) for a sequence expected (<%s>), at child position: %d, item list pos: %d",
								  axl_node_get_name (node), 
								  axl_dtd_item_node_get_value (itemNode),
								  child_pos, iterator);
					}
					/* return that a match wasn't possible */
					*child_position = child_pos;
					return axl_false;			
				}
			}

			/* according to the repetition pattern, update loop indexes */
			__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "updating child nodes references: %d, repeat type: %d, status=%d",
				   child_pos, times, status);


			/* one only item to match and exactly one */
			if (times == ONE_AND_ONLY_ONE) {
				child_pos++;
				__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "updated child position to: %d, repeat type: %d, status=%d",
					   child_pos, times, status);
				break;
			}

			/* one or many items to match */
			if (times == ONE_OR_MANY) { 

				__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "matched one to many item node: status=%d one_matched=%d",
					   status, one_matched);

				/* if the match have failed and
				 * previous matches was ok, it seems
				 * we have reached the next
				 * items. Just break the loop */
				if (status == axl_false && one_matched == axl_true) 
					break;

				child_pos++;
				one_matched = axl_true;
				continue; /* don't break the loop */
			}

			/* zero or optionally one item to match */			
			if (times == ZERO_OR_ONE) {
				/* if previous status was ok, it seems
				 * that we have matched the optional
				 * character. In that case, move the
				 * index to the following value. If
				 * not, just break the loop. */
				if (status == axl_true)
					child_pos++;
				break;
			}

			/* zero or many items to match */
			if (times == ZERO_OR_MANY) {
				if (status == axl_true) {
					one_matched = axl_true;
					child_pos++;
					continue;
				}
				break;
			}


			/* until break the loop */
		}while (axl_true);

		/* update iterator index */
		iterator++;
	}

	/* check if more nodes where specified than the DTD spec */
	times = axl_dtd_item_list_repeat (itemList);
	if ((times == ONE_OR_MANY || times == ONE_AND_ONLY_ONE) && 
	    top_level && (child_pos  < axl_node_get_child_num (parent))) {

		/* drop a log */
		__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "parent node <%s> have more childs=%d than the childs iterated=%d, top_level=%d",
			   axl_node_get_name (parent),
			   axl_node_get_child_num (parent),
			   child_pos, top_level);

		/* do not report an error found if a try match is
		 * being run */
		if (! try_match) {
			axl_error_new (-1, "More childs, than the ones especified in the DTD, were found",
				       NULL, error);
		}
		/* return that the match wasn't possible */
		*child_position = child_pos;
		return axl_false;
	}

	/* return that the sequence has been validated */
	*child_position = child_pos;

	__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "sequence validated with child position (I): %d", child_pos);

	return axl_true;
}

/** 
 * @internal
 * 
 * Internal support function to validate the choice list.
 */
axl_bool     __axl_dtd_validate_choice (axlNode             * parent, 
					int                 * child_position, 
					axlDtdElementList   * itemList, 
					axlError           ** error,
					axl_bool              try_match, 
					axl_bool              top_level)
{
	axlNode               * node;
	axlDtdElementListNode * itemNode;
	int                     iterator;
	axl_bool                status;
	AxlDtdTimes             times;
	axl_bool                one_match;

	
	if (*child_position < axl_node_get_child_num (parent)) {
		/* get a reference to be matched by the choice list */
		node = axl_node_get_child_nth (parent, *child_position);
		__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "validated choice list at position: %d=<%s>", *child_position, axl_node_get_name (node));
	} else {
		/* tried to match a choice list with a child index
		 * outside the maximum number of childs */
		if (! try_match) {
			axl_error_new (-1, "Unable to match choice list, it seems that the are not enough childs to validate the choice list",
				       NULL, error);
		}
		return axl_false;
	}

	iterator = 0; 
	while (iterator < axl_dtd_item_list_count (itemList)) {
		/* get the DTD item list to match */
		itemNode = axl_dtd_item_list_get_node   (itemList, iterator);
		times    = axl_dtd_item_node_get_repeat (itemNode);

		if (axl_dtd_item_node_get_type (itemNode) == AXL_ELEMENT_NODE) {
			/* reset match configuration */
			one_match = axl_false;
		repeat_for_node:
			/* a node was found */
			status    = NODE_CMP_NAME (node, axl_dtd_item_node_get_value (itemNode));

			/* know, if the node was matched check it
			 * repetition configuration */
			if (status) {
				/* update child position */
				(*child_position)++;

				if (times == ONE_AND_ONLY_ONE || times == ZERO_OR_ONE) {
					/* the node was matched and
					 * the itemNode has a one and
					 * only one configuration,
					 * just return that the choice
					 * list was matched */
					return axl_true;
				}
				if (times == ONE_OR_MANY || times == ZERO_OR_MANY) {
					/* because the node was matched, but the repetition
					 * pattern allows to match more nodes we have to
					 * iterate a bit more */
					node = axl_node_get_child_nth (parent, *child_position);
					if (node == NULL) {
						/* because we already matched at least one item, 
						 * we can assume that the itemNode was successfully 
						 * matched for both cases (*) and (+). */
						return axl_true;
					}
					/* flag the one match */
					one_match = axl_true;
					
					/* if the node reference is
					 * not NULL, try to match the
					 * next item */
					goto repeat_for_node;
				}
			} /* end if */
			
			/* before returning, that that we have matched
			 * previously, at least, one node for
			 * one-to-many and zero-to-many pattern */
			if ((times == ONE_OR_MANY || times == ZERO_OR_MANY) && one_match) {
				return axl_true;
			}

		} else if (axl_dtd_item_node_get_type (itemNode) == AXL_ELEMENT_LIST) {
			/* an element list was found, call to validate it */
			/* element list found, validate its content */
			if (__axl_dtd_validate_item_list (axl_dtd_item_node_get_list (itemNode),
							  parent, child_position, error, axl_false)) {
				/* item list matched */
				return axl_true;
			}
		}

		/* no item was matched, update iterator indexes */
		iterator++;
	}

	/* seems that the choice list wasn't matched */
	if (! try_match) {
		axl_error_new (-1, "Unable to match choice list, after checking all posibilities, choice list wasn't validated", 
			       NULL, error);
	}
	return axl_false;
}

/** 
 * @internal 
 *
 * Tries to perform a validation, based on the item list received and
 * the repetition configuration.
 * 
 * @param itemList The item list containing DTD content spec
 * information used to validate.
 *
 * @param parent The parent node where the validation process is being
 * applied. The content spec refers to the childs the parent has.
 *
 * @param stack An stack used by the overall process to store the
 * subsequent parents to be validated. This stack must be released if
 * a error is found.
 *
 * @param error An optional axlError reference containing the error
 * textual diagnostic if found.
 * 
 * @return axl_true if the validation was ok, otherwise axl_false is
 * returned.
 */
axl_bool     __axl_dtd_validate_item_list (axlDtdElementList  * itemList,
					   axlNode            * parent, 
					   int                * child_position,
					   axlError          ** error,
					   axl_bool             top_level)
{
	int          temp_child_pos;
	axl_bool     status;
	axl_bool     already_matched;


	__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "validating an item list with repeat pattern: %d, at %d, top level=%d",
		   axl_dtd_item_list_repeat (itemList), *child_position, top_level);

	/* now check repetition type */
	switch (axl_dtd_item_list_repeat (itemList)) {
	case ONE_AND_ONLY_ONE:
		__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a (one and only one) spec..");
		if (axl_dtd_item_list_type (itemList) == SEQUENCE) {

			__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "using a SEQUENCE form");
			/* it is a choice, so the item list specifies
			 * the nodes that could appear */
			if (!__axl_dtd_validate_sequence (parent, child_position, itemList, error, 
							  axl_false, top_level)) {
				return axl_false;
			}
		}else {
			__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "using a CHOICE form");
			/* it is a sequence, so, item list
			 * specification represents the nodes, in the
			 * order they must appear */
			if (!__axl_dtd_validate_choice (parent, child_position, itemList, error,
							axl_false, top_level)) {
				return axl_false;
			}
			__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "choice list was properly validated");
		}
		break;
	case ZERO_OR_ONE:

		__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a (zero or one) spec..");
		if (axl_dtd_item_list_type (itemList) == SEQUENCE) {

			__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "using a SEQUENCE form, parent: <%s>",
				   axl_node_get_name (parent));
			/* because we are running a zero or one item
			 * list matching, we don't care if it doesn't
			 * match. In the case it match, the child
			 * position is updated and next calls will be
			 * properly aligned. In the match doesn't
			 * happens, it also don't matter because the
			 * pattern allow to not match */
			temp_child_pos = *child_position;
			if (!__axl_dtd_validate_sequence (parent, child_position, itemList, error, 
							  axl_true, top_level)) {
				/* check that the match wasn't
				 * produced, at any level */
				if (temp_child_pos != *child_position) {
					__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "item list mismatch (%d != %d)", 
						   temp_child_pos, *child_position);
					axl_error_new (-1, "Found an DTD item list definition, that should be matched entirely or not, zero or one time, but it was matched partially",
						       NULL, error);
					return axl_false;
				}

				return axl_false;
			}
			
		}else {
			__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "    using a CHOICE form");

			/* it is a sequence, so, item list
			 * specification represents the nodes, in the
			 * order they must appear */
			__axl_dtd_validate_choice (parent, child_position, itemList, error,
						   axl_true, top_level);
		}
		break;
	case ZERO_OR_MANY:

		__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a (zero or many) spec..");
		if (axl_dtd_item_list_type (itemList) == SEQUENCE) {

			__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "    using a SEQUENCE (size: %d) form ",
				   axl_dtd_item_list_count (itemList));
			/* one this case, several matches must be
			 * tried, until the validation fails */
			do {
				temp_child_pos = *child_position;
				status         = __axl_dtd_validate_sequence (parent, child_position, itemList, error, 
									      axl_true, top_level);

				__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "sequence match status=%d", status);
				if (! status) {
					/* check that the match wasn't
					 * produced, at any level */
					if ((temp_child_pos != *child_position)) {

						__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "item list mismatch (%d != %d)", 
							   temp_child_pos, *child_position);
						axl_error_new (-1, "Found an DTD item list definition, that should be matched entirely or not, zero or many times, but it was matched partially",
							       NULL, error);
						return axl_false;
					}
				}
			}while (status);
		}else {

			__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "    using a CHOICE form");
			/* it is a sequence, so, item list
			 * specification represents the nodes, in the
			 * order they must appear */
			do {
				status = __axl_dtd_validate_choice (parent, child_position, itemList, error,
								    axl_true, top_level);
			}while (status);
		}
		break;
	case ONE_OR_MANY:
		/* one or many sequence spec (+) */
		__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a (zero or many) spec..");
		if (axl_dtd_item_list_type (itemList) == SEQUENCE) {

			__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "    using a SEQUENCE (size: %d) form ",
				   axl_dtd_item_list_count (itemList));

			/* one this case, several matches must be
			 * tried, until the validation fails */
			already_matched = axl_false;
			do {
				temp_child_pos = *child_position;
				/* try to match the one or many
				   sequence according to the value
				   stored inside already matched */
				status         = __axl_dtd_validate_sequence (parent, child_position, itemList, error, 
									      already_matched, top_level);

				__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "sequence match status=%d", status);
				if (! status) {
					/* check that the match wasn't
					 * produced, at any level */
					if ((temp_child_pos != *child_position)) {

						__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "item list mismatch, matched partially (%d != %d)", 
							   temp_child_pos, *child_position);
						axl_error_new (-1, 
							       "Found an DTD item list definition, that should be matched entirely or not, one or many times, but it was matched partially",
							       NULL, error);
						return axl_false;
					}
				}else {
					/* set that we have matched, at least, one item */
					already_matched = axl_true;
				}

				

			}while (status);
		}else {

			__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "    using a CHOICE form");
			/* it is a sequence, so, item list
			 * specification represents the nodes, in the
			 * order they must appear */
			already_matched = axl_false;
			do {
				/* the next choice matching is done
				 * according to the value stored in
				 * already matched */
				status = __axl_dtd_validate_choice (parent, child_position, itemList, error,
								    already_matched, top_level);
				/* if the validation successed, set
				 * that next matched are not required
				 * to be successful ones */
				if (status)
					already_matched = axl_true;
			}while (status);
		}
		break;
	default:
		/* this case will never be reached */
#define INTERNAL_ERROR_01 "critical error reached a place that shows the dtd parser is not properly defining the repetition pattern for the current itemList."
		__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, INTERNAL_ERROR_01);
		axl_error_new (-1, INTERNAL_ERROR_01, NULL, error);
		return axl_false;
	}


	__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "validate item list terminated, now check post-conditions, top_level=%d, item list type=%d, child pos=%d, childs num=%d",
		   top_level, axl_dtd_item_list_type (itemList), *child_position, axl_node_get_child_num (parent));

	/* check that, in the case that the choice item list is being
	 * validated, ensure it has validated all nodes, especially if
	 * we are the top level definition */
	if (top_level && (axl_dtd_item_list_type (itemList) == CHOICE)) {
		if (((*child_position) + 1) < axl_node_get_child_num (parent)) {
		    

			__axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "found that the choice list didn't cover all childs (%d), while parent=<%s> has: (%d)",
				   (*child_position), axl_node_get_name (parent), axl_node_get_child_num (parent));
			axl_error_new (-1, "Found that the validation process didn't cover all nodes, while using a choice list. This means that the xml document have more content than the DTD spec",
				       NULL, error);
			return axl_false;
		}
	}
	
	/* element type children validated */
	return axl_true;       
}

/** 
 * @internal
 *
 * Support function validate parent nodes which are element type
 * children ones.
 */
axl_bool     __axl_dtd_validate_element_type_children (axlDtdElement  * element, 
						       axlNode        * parent, 
						       axl_bool         top_level,
						       axlError      ** error)
{
	axlDtdElementList * itemList;
	int                 child_pos = 0;
	char              * err_msg;

	/* get a reference to the item list */
	itemList = axl_dtd_get_item_list (element);

	/* check for xml nodes with fewer content than the initially
	 * expected. */
	if (axl_node_get_child_num (parent) < element->minimum_match) {
		err_msg = axl_strdup_printf ("Found that the parent node (<%s>) received doesn't contains enough xml nodes inside to get a proper validation (childs found (%d) != childs that should be found (%d)). This means that the xml document have fewer content than the DTD spec.",
					     axl_node_get_name (parent), 
					     axl_node_get_child_num (parent), 
					     element->minimum_match);
		axl_error_new (-1, err_msg, NULL, error);
		axl_free (err_msg);
		return axl_false;
	}

	/* validate the item list, starting from the child 0 */
	if (__axl_dtd_validate_item_list (itemList, parent, &child_pos, error, top_level)) {
		/* check if, at least, all minimum elements was
		 * matched */
		__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "checking minimum node match: (%d < min: %d) (%d < childs: %d) node=<%s>", 
			   child_pos, element->minimum_match,
			   child_pos, axl_node_get_child_num (parent),
			   axl_node_get_name (parent));
			
		if (child_pos < axl_node_get_child_num (parent)) {
			axl_error_report (error, -1,
					  "Found that the validation process didn't cover all nodes (%d < min:%d) (%d < childs:%d). All xml child nodes inside the parent=<%s> wasn't covered. This means that the xml document have more content than the DTD spec defines.",
					  child_pos, element->minimum_match, child_pos, axl_node_get_child_num (parent), 
					  axl_node_get_name (parent));
			return axl_false;
		}
		/* seems that the minimum match */
		return axl_true;
	}

	return axl_false;
}

/** 
 * @internal
 * Internal support function to validate #PCDATA nodes.
 */
axl_bool     __axl_dtd_validate_element_type_pcdata (axlDtdElement  * element, 
						     axlNode        * parent, 
						     axlStack       * stack, 
						     axlError      ** error)
{
	/* check for childs */
	if (axl_node_have_childs (parent)) {
		__axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "node <%s> should be #PCDATA and it contains childs",
			   axl_node_get_name (parent));
		axl_error_new (-1, 
			       "Found a node for which its espeficiation makes it to be a node with only data and no childs, and it currently contains childs",
			       NULL, error);
		return axl_false;
	}
	
	/* return that the validation was ok */
	return axl_true;
}

/** 
 * @internal
 * 
 * Support function to validate empty nodes.
 */
axl_bool     __axl_dtd_validate_element_type_empty (axlDtdElement  * element,
						    axlNode        * parent,
						    axlStack       * stack,
						    axlError      ** error)
{
	char * err_msg;

	/* check the node is indeed, empty */
	if (! axl_node_is_empty (parent)) {
		err_msg = axl_strdup_printf (
			"Found a node <%s> that it is especified that must be empty, but it isn't",
			axl_node_get_name (parent));
		axl_error_new (-1, err_msg, NULL, error);
		axl_free (err_msg);
		return axl_false;
	}

	/* check the node doesn't have childs */
	if (axl_node_have_childs (parent)) {
		err_msg = axl_strdup_printf (
			"Found a node <%s> that it is especified that must be empty, but it has childs",
			axl_node_get_name (parent));
		axl_error_new (-1, err_msg, NULL, error);
		axl_free (err_msg);
		return axl_false;
	}
	
	/* return that the validation was ok */
	return axl_true;
}

axl_bool __axl_dtd_attr_validate_foreach (const char * key, const char * value, axlPointer data, axlPointer data2)
{
	axlDtdAttribute     * attribute = data;
	axlError           ** error     = data2;
	axlDtdAttributeDecl * decl;
	char                * err_msg;

	/* get declaration associated */
	decl = axl_list_lookup (attribute->list, __find_attr_decl, (axlPointer) key);
	
	if (decl == NULL) {
		/* found an error */
		err_msg = axl_strdup_printf ("Found an attribute (%s) which is not specified by the attribute declaration for <%s>",
					     key, attribute->name);
		axl_error_new (-1, err_msg, NULL, error);
		
		/* free the cursor and the error message */
		axl_free (err_msg);

		/* return axl_true here because we want to stop the process */
		return axl_true;
		
	} /* end if */

	/* if the declaration is found, now check its
	 * contraints */
	axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "checking contraint for attribute: %s=%s", decl->name, value);
	if (decl->type == CDATA_ATTRIBUTE) {
		/* found free attribute declaration, go ahed */
	} else if (decl->type == ENUMERATION_TYPE) {
		/* found an enumeration type, check and return */
		if (axl_list_lookup (decl->enumvalues, axl_list_find_string, (char *) value) == NULL) {
			/* found an error */
			err_msg = axl_strdup_printf ("Found an attribute (%s) with a value not allowed by the enum declaration (%s) for the node <%s>",
						     key, value, attribute->name);
			axl_error_new (-1, err_msg, NULL, error);
			
			/* free the cursor and the error message */
			axl_free (err_msg);
			return axl_true;
		}
	} else {
		/* not supported yet */
	}

	/* return axl_false to continue with the process */
	return axl_false;
}

axl_bool __axl_dtd_attr_validate_required (axlPointer element, axlPointer data)
{
	axlNode             * node = data;
	axlDtdAttributeDecl * decl = element;

	switch (decl->defaults) {
	case ATT_REQUIRED:
		/* attribute required */
		return !HAS_ATTR (node, decl->name);
	case ATT_FIXED:
		return !HAS_ATTR_VALUE (node, decl->name, decl->default_value);
	default:
		break;
	} /* end switch */

	/* return axl_false for this because it is not obligatory
	 * to have the attribute defined. */
	return axl_false;
}

/** 
 * @internal Functions which validates the attribute declaration for
 * the node provided, using attribute declarations found.
 * 
 * @param node The node to check for its attributes.
 *
 * @param dtd The dtd used to validate the node provided.
 *
 * @param error A reference to the axlError where the textual
 * diagnostic error will be reported.
 * 
 * @return axl_true if the node is validated, axl_false if not.
 */
axl_bool axl_dtd_attr_validate (axlNode * node, axlDtd * dtd, axlError ** error, axlHash * id_validation, axlList * idref_validation)
{
	axlDtdAttribute     * attribute;
	axlDtdAttributeDecl * decl;
	char                * err_msg;
	int                   iterator;
	axlError            * _error = NULL;

	/* find attribute contraints for the node */
	attribute = axl_dtd_get_attr (dtd, axl_node_get_name (node));
	if (attribute == NULL)
		return axl_true;

	/* we have an especification, run it */

	/* for each attribute found, check against the spec */
	axl_node_attr_foreach (node, __axl_dtd_attr_validate_foreach, attribute, &_error);

	/* check the error */
	if (! axl_error_was_ok (_error)) {
		/* reconfigure error returned */
		if (error != NULL)
			*error = _error;
		return axl_false;
	} /* end if */
		
	
	/* now, for each contraint, check that all required nodes
	 * exists */
	decl = axl_list_lookup (attribute->list, __axl_dtd_attr_validate_required, node);
	if (decl != NULL) {
		if (decl->defaults == ATT_FIXED)
			err_msg = axl_strdup_printf ("attribute required '%s' (or its value), due to #FIXED declaration, not found for node <%s>", 
						     decl->name, attribute->name);
		else 
			err_msg = axl_strdup_printf ("attribute required '%s', due to #REQUIRED declaration, not found for node <%s>", 
						     decl->name, attribute->name);
		axl_error_new (-1, err_msg, NULL, error);
		axl_free (err_msg);
		return axl_false;
	} /* end if */

	/* check declarations */
	if (dtd->haveIdDecl) {

		__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found DTD has ID unique attribute declaration..");
		
		/* check if the node have TOKENIZED_TYPE_ID */
		decl = axl_list_lookup (attribute->list, __find_id_decl, NULL);
		
		/* if we have a tokenized */
		if (decl != NULL) {

			__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found ID unique attribute declaration %s=\"%s\"..",
				   decl->name, ATTR_VALUE (node, decl->name));

			/* check if the attribute value for the decl that is
			 * flagged as ID is already found at the
			 * id_validation */
			if (axl_hash_exists (id_validation, (axlPointer) ATTR_VALUE (node, decl->name))) {
				err_msg = axl_strdup_printf ("DTD declared the attribute '%s' as unique (ID) for the node %s, but was found used several times",
							     decl->name, attribute->name);
				axl_error_new (-1, err_msg, NULL, error);
				axl_free (err_msg);
				return axl_false;
			} /* end if */
			
			/* seems the attribute was not used, nice!, store it */
			axl_hash_insert (id_validation, (axlPointer) ATTR_VALUE (node, decl->name), (axlPointer) ATTR_VALUE (node, decl->name));
		} /* end if */
	} /* end if */

	if (dtd->haveIdRefDecl) {
		/* find the id ref declaration */
		
		iterator = 0;
		while (iterator < axl_list_length (attribute->list)) {
			
			/* get the attribute declaration at the
			 * particular position */
			decl = axl_list_get_nth (attribute->list, iterator);
			if (decl->type == TOKENIZED_TYPE_IDREF) {
				/* found a reference, but do not check
				 * it at this place becase the
				 * reference could be placed at any
				 * part in the document event after
				 * the reference pointed is
				 * defined. store and check later */
				if (ATTR_VALUE (node, decl->name)) {
					/* store the id ref reference
					 * if defined */
					axl_list_add (idref_validation, (axlPointer) ATTR_VALUE (node, decl->name));
				}
			} /* end if */

			/* get the next */
			iterator++;
			
		} /* end if */
		
	} /* end if */

	axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "attributes validated for node=<%s>", attribute->name);
	
	return axl_true;
}

/** 
 * @internal Function used by axl_dtd_validate_references to ensure
 * that all references found point to a valid reference defined.
 */
axl_bool __axl_dtd_reference_check (axlPointer _element, axlPointer data)
{
#if defined(SHOW_DEBUG_LOG)
	const char * value = _element;

	__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "checking id ref: %s", value);
#endif

	return ! axl_hash_exists ((axlHash *) data, _element);
}

/** 
 * @internal Function that validates all references found (from IDREF
 * attribute) to unique references (defined by ID attributes).
 *
 */
axl_bool axl_dtd_validate_references (axlHash * id_validation, axlList * idref_validation, axlError ** error)
{
	char * reference;
	char * err_msg;
	
	/* if no empty at the valiadtion reference list, means not
	 * reference was done, so there is no room for errors */
	if (idref_validation == NULL) 
		return axl_true;
	
	__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "id_validation reference: 0x%x", id_validation);

	/* find first reference not found */
	reference = axl_list_lookup (idref_validation, __axl_dtd_reference_check, id_validation);
	
	if (reference != NULL) {
		/* found a reference not defined, report it to the
		 * application level */
		err_msg = axl_strdup_printf ("Found a reference defined ('%s') which is not found in any ID attribute in the document",
					     reference);
		axl_error_new (-1, err_msg, NULL, error);
		axl_free (err_msg);

		return axl_false;
	} /* end if */
	
	/* validation ok */
	return axl_true;
}

/** 
 * @brief Allows to validate the given XML document (\ref axlDoc)
 * against the given document type definition (DTD, \ref axlDtd).
 *
 * This function allows to validate your XML documents providing the
 * document type definition, that was read using \ref axl_dtd_parse or
 * \ref axl_dtd_parse_from_file.
 *
 * Keep in mind that a document could be well-formed and valid. The
 * only difference is that valid XML document are those that, meet all
 * XML rules, but also are clasified and recognized as XML documents
 * with some particular structure, that is represented (or
 * constrained) with providing a DTD definition.
 *
 * @param doc The \ref axlDoc containing the XML document to be
 * validated.
 *
 * @param dtd The \ref axlDtd containing the DTD definition used to
 * validate the document.
 *
 * @param error An optional reference to a \ref axlError object where
 * validation errors are reported.
 *
 * @return axl_true if the document is valid, axl_false if not.
 */
axl_bool           axl_dtd_validate        (axlDoc * doc, axlDtd * dtd,
					    axlError ** error)
{
	axlNode            * parent;
	axlStack           * stack;
	axlHash            * id_validation = NULL;
	axlList            * idref_validation = NULL;
	
	axlDtdElement      * element;
	axl_bool             top_level;
	char               * err_msg;
	axl_bool             result;
	
	/* perform some checkings */
	axl_return_val_if_fail (doc, axl_false);
	axl_return_val_if_fail (dtd, axl_false);

	__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "starting DTD validation");

	/* validate the very first root node */
	parent  = axl_doc_get_root (doc);
	element = axl_dtd_get_root (dtd);
	if ((element != NULL) && ! NODE_CMP_NAME (parent, axl_dtd_get_element_name (element))) {

		/* because a DTD document could have several top level
		 * elements, ensure this is not the case */
		element = axl_dtd_get_element (dtd, axl_node_get_name (parent));
		if (element == NULL) { /*  || ! axl_dtd_element_is_toplevel (dtd, element)) { */
			/* root node doesn't match */
			err_msg = axl_strdup_printf ("Found that root node doesn't match (%s != %s!",
						     axl_node_get_name (parent), 
						     axl_dtd_get_element_name (element));
			axl_error_new (-1, err_msg, NULL, error);
			axl_free (err_msg);
			return axl_false;

		} /* end if */
	} /* end if */

	/* check if the node has DTD element declaration */
	if (element == NULL) {
		err_msg = axl_strdup_printf ("There is not DTD element declaration to validate the node <%s>", 
					     axl_node_get_name (parent));
		axl_error_new (-1, err_msg, NULL, error);
		axl_free (err_msg);
		return axl_false;
	} /* end if */

	/* check if the dtd contains a Id declaration */
	if (dtd->haveIdDecl) {
		/* seems the user have declarted ID attributes init the hash */
		id_validation = axl_hash_new (axl_hash_string, axl_hash_equal_string);
	} /* end if */

	/* check if the dtd contains Id ref declarations */
	if (dtd->haveIdRefDecl) {
		/* create a list that could contain all references done */
		idref_validation = axl_list_new (axl_list_always_return_1, NULL);
	} /* end if */

	/* check empty content spec */
	if (axl_dtd_get_element_type (element) == ELEMENT_TYPE_EMPTY) {
		/* check if the document provided have only one node */
		result = axl_node_is_empty (parent) && !axl_node_have_childs (parent) && axl_dtd_attr_validate (parent, dtd, error, id_validation, idref_validation);

		/* check references */
		if (result)
			result = axl_dtd_validate_references (id_validation, idref_validation, error);
		
		/* free and return */
		axl_hash_free (id_validation);

		/* free the list */
		axl_list_free (idref_validation);
		return result;
	} /* end if */

	/* queue initial nodes to validate */
	stack     = axl_stack_new (NULL);
	

	/* set that the only top level node is the first one */
	top_level = axl_true;

	do {
		__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "doing a DTD iteration: <%s>...",
			   axl_node_get_name (parent));

		/* validate attributes */
		if (! axl_dtd_attr_validate (parent, dtd, error, id_validation, idref_validation)) {
			/* free the stack */
			axl_stack_free (stack);

			/* free id_validation */
			axl_hash_free (id_validation);

			/* free the list */
			axl_list_free (idref_validation);
			return axl_false;
		}

		/* reach this position, the <parent> reference contains
		 * a reference to the parent node, which will be used
		 * to validate current child content against current
		 * configuration for dtd element constraining it.
		 * 
		 * equally, the <element> reference contains a dtd
		 * reference to the already checked DTD element which
		 * configure this parent node. */
		switch (axl_dtd_get_element_type (element)) {
		case ELEMENT_TYPE_PCDATA:
			__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "  find  PCDATA dtd element=%s: parent=<%s>, ",
				   axl_dtd_get_element_name (element), 
				   axl_node_get_name (parent));

			/* ok, a leaf node was found, know it is
			 * required to check that the node doesn't
			 * have more childs and only have content,
			 * that is, it is not empty  */
			if (!__axl_dtd_validate_element_type_pcdata (element, parent, stack, error)) {
				/* free id_validation */
				axl_hash_free (id_validation);

				/* free the stack */
				axl_stack_free (stack);
				
				/* free the list */
				axl_list_free (idref_validation);
				return axl_false;
			}
			break;
		case ELEMENT_TYPE_CHILDREN:

			__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "  find  CHILDREN dtd element");
			/* ok, a parent node that have childs */
			if (!__axl_dtd_validate_element_type_children (element, parent, top_level, error)) {
				/* free id_validation */
				axl_hash_free (id_validation);

				/* free the stack */
				axl_stack_free (stack);

				/* free the list */
				axl_list_free (idref_validation);
				
				return axl_false;
			}
			break;
		case ELEMENT_TYPE_EMPTY:
			__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "  find  EMPTY dtd element");
			/* the element especification is empty, the
			 * node being validated must also be the
			 * same */
			if (!__axl_dtd_validate_element_type_empty (element, parent, stack, error)) {
				/* free id_validation */
				axl_hash_free (id_validation);

				/* free the stack */
				axl_stack_free (stack);

				/* free the list */
				axl_list_free (idref_validation);

				return axl_false;
			}
			break;
		case ELEMENT_TYPE_ANY:
			__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "  find  ANY dtd element");
			/* the anything is allowed cased from this
			 * parent node. */
			goto continue_with_validation;
		case ELEMENT_TYPE_MIXED:
			__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "  find  MIXED dtd element");

			/* the mixed case, where nodes and PC data
			 * could be mixed */
			break;
		default:
			/* do not do any thing on this case */
			break;
		}
			
		/* queue more childs, as future parents to be
		 * validated on the provided queue, only in the case
		 * the parent node have childs */
		if (axl_node_have_childs (parent)) {

			__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "parent node <%s> have childs, adding its childs (stack size: %d)",
				   axl_node_get_name (parent),
				   axl_stack_size (stack));

			/* queue childs to be processed */
			__axl_dtd_queue_childs (stack, parent);

			__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "parent node <%s> childs: %d, (stack size: %d)",
				   axl_node_get_name (parent), axl_node_get_child_num (parent),
				   axl_stack_size (stack));
		}
		
		/* set the parent reference to NULL */
		parent = NULL;
			
		/* update the reference to the new parent node, only
		 * if there are new parents on the stack */
	continue_with_validation:
		if (! axl_stack_is_empty (stack)) {


			/* get a new reference */
			parent  = axl_stack_pop (stack);
			
			/* get a reference to the DTD element to used */
			element = axl_dtd_get_element (dtd, axl_node_get_name (parent));
			if (element == NULL) {
				__axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "found that the node <%s> doesn't have DTD especification", 
					   axl_node_get_name (parent));
				/* prepare the error message */
				err_msg = axl_strdup_printf ("Found a node <%s> that doesn't have a DTD element espefication to validate it, DTD validation failed",
							     axl_node_get_name (parent));
				axl_error_new (-1, err_msg, NULL, error);
				axl_free (err_msg);

				/* free id_validation */
				axl_hash_free (id_validation);

				/* free the list */
				axl_list_free (idref_validation);

				/* free the stack */
				axl_stack_free (stack);
				return axl_false;
			} /* end if */
		} /* end if */

		/* set the top level status */
		top_level = axl_false;
		
		/* until the stack is empty */
	}while (parent != NULL);

	/* check references */
	result = axl_dtd_validate_references (id_validation, idref_validation, error);

	/* deallocate stack used */
	axl_stack_free (stack);

	/* free id_validation */
	axl_hash_free (id_validation);

	/* free the list */
	axl_list_free (idref_validation);

	__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "DTD validation, %s", result ? "ok" : "failed");

	/* the document is valid */
	return result;
}

/** 
 * @brief Allows to check if the provided two references represents
 * DTD documents with the same rules. 
 * 
 * @param dtd First reference to compare.
 * @param dtd2 Second reference to compare.
 *
 * @return axl_true if both references represent the same document. If
 * some of the references received are NULL the function returns
 * axl_false.
 *
 * NOTE: The function does not have the ability to perform a smart
 * equal operation like detecting DTD that are semantically
 * equivalent. It only checks internal structure. 
 */
axl_bool                 axl_dtd_are_equal        (axlDtd * dtd,
						   axlDtd * dtd2)
{
	int iterator;
	int iterator2;
	int iterator3;
	axlDtdEntity          * entity,      * entity2;
	axlDtdElement         * element,     * element2;
	axlDtdElementListNode * node,        * node2;
	axlDtdAttribute       * attribute,   * attribute2;
	axlDtdAttributeDecl   * attr_decl,   * attr_decl2;

	/* check references received */
	if (dtd == NULL)
		return axl_false;
	if (dtd2 == NULL)
		return axl_false;

	/* check each rule inside both documents */
	if (axl_list_length (dtd->entities) != axl_list_length (dtd2->entities))
		return axl_false;
	if (axl_list_length (dtd->elements) != axl_list_length (dtd2->elements))
		return axl_false;
	if (axl_list_length (dtd->attributes) != axl_list_length (dtd2->attributes))
		return axl_false;
	if (dtd->haveIdRefDecl != dtd2->haveIdRefDecl)
		return axl_false;
	if (dtd->haveIdDecl != dtd2->haveIdDecl)
		return axl_false;

	/* now check inner elements (ENTITIES) */
	iterator = 0;
	while (iterator < axl_list_length (dtd->entities)) {
		/* get referneces */
		entity  = axl_list_get_nth (dtd->entities, iterator);
		entity2 = axl_list_get_nth (dtd2->entities, iterator);

		/* check types */
		if (entity->type != entity2->type)
			return axl_false;

		/* check names */
		if (! axl_cmp (entity->name, entity2->name)) 
			return axl_false;

		/* check content */
		if (! axl_cmp (entity->content, entity2->content))
			return axl_false;

		/* check external data */
		if (entity->data == NULL && entity2->data != NULL)
			return axl_false;
		if (entity->data != NULL && entity2->data == NULL)
			return axl_false;
		if (entity->data != NULL && entity2->data != NULL) {
			if (! axl_cmp (entity->data->system_literal, entity2->data->system_literal))
				return axl_false;
			if (! axl_cmp (entity->data->public_literal, entity2->data->public_literal))
				return axl_false;
			if (! axl_cmp (entity->data->ndata, entity2->data->ndata))
				return axl_false;
		} /* end if */

		/* next iterator */
		iterator++;
	} /* end while */

	/* now check inner elements (ELEMENTS) */
	iterator = 0;
	while (iterator < axl_list_length (dtd->elements)) {
		/* get referneces */
		element  = axl_list_get_nth (dtd->elements, iterator);
		element2 = axl_list_get_nth (dtd2->elements, iterator);

		/* check types */
		if (element->type != element2->type)
			return axl_false;

		/* minimum match */
		if (element->minimum_match != element2->minimum_match)
			return axl_false;

		/* check names */
		if (! axl_cmp (element->name, element2->name)) 
			return axl_false;

		/* check element list */
		if (element->list == NULL && element2->list != NULL)
			return axl_false;
		if (element->list != NULL && element2->list == NULL)
			return axl_false;
		if (element->list != NULL && element2->list != NULL) {

			/* check internal values */
			if (element->list->type != element2->list->type)
				return axl_false;
			if (element->list->times != element2->list->times)
				return axl_false;

			iterator2 = 0;
			while (iterator2 < axl_list_length (element->list->itemList)) {
				
				/* get references */
				node  = axl_list_get_nth (element->list->itemList, iterator2);
				node2 = axl_list_get_nth (element2->list->itemList, iterator2);

				if (node->type != node->type)
					return axl_false;
				if (node->times != node2->times)
					return axl_false;
				
				/* next value */
				iterator2++;

			} /* end while */
			
		} /* end if */

		/* next iterator */
		iterator++;
	} /* end while */

	/* now check inner elements (ATTRIBUTES) */
	iterator = 0;
	while (iterator < axl_list_length (dtd->attributes)) {
		/* get referneces */
		attribute  = axl_list_get_nth (dtd->attributes, iterator);
		attribute2 = axl_list_get_nth (dtd2->attributes, iterator);

		/* check names */
		if (! axl_cmp (attribute->name, attribute2->name)) 
			return axl_false;

		/* check values */
		if (attribute->list == NULL && attribute2->list != NULL)
			return axl_false;
		if (attribute->list != NULL && attribute2->list == NULL)
			return axl_false;
		if (attribute->list != NULL && attribute2->list != NULL) {

			/* check list length */
			if (axl_list_length (attribute->list) != axl_list_length (attribute2->list))
				return axl_false;

			/* check internal values */
			iterator2 = 0;
			while (iterator2 < axl_list_length (attribute->list)) {
				
				/* get references */
				attr_decl   = axl_list_get_nth (attribute->list,  iterator2);
				attr_decl2  = axl_list_get_nth (attribute2->list, iterator2);

				if (attr_decl->type != attr_decl2->type)
					return axl_false;
				if (attr_decl->defaults != attr_decl2->defaults)
					return axl_false;
				if (! axl_cmp (attr_decl->name, attr_decl2->name))
					return axl_false;
				
				if (attr_decl->enumvalues == NULL && attr_decl2->enumvalues != NULL)
					return axl_false;
				if (attr_decl->enumvalues != NULL && attr_decl2->enumvalues == NULL)
					return axl_false;
				if (attr_decl->enumvalues != NULL && attr_decl2->enumvalues != NULL) {
					if (axl_list_length (attr_decl->enumvalues) != axl_list_length (attr_decl2->enumvalues))
						return axl_false;
					iterator3 = 0;
					while (iterator3 < axl_list_length (attr_decl->enumvalues)) {
						/* check values */
						if (! axl_cmp (axl_list_get_nth (attr_decl->enumvalues, iterator3),
							       axl_list_get_nth (attr_decl2->enumvalues, iterator3)))
							return axl_false;

						/* next value */
						iterator3++;
					} /* end while */
				} /* end if */
				
				/* next value */
				iterator2++;

			} /* end while */
			
		} /* end if */

		/* next iterator */
		iterator++;
	} /* end while */

	return axl_true;
	
}

/** 
 * @brief Allows to get the root node for the provided DTD.
 *
 * Every DTD have a root node defined, which is the root node accepted
 * for the set of XML document considered to be valid under the
 * definition of the DTD provided.
 *
 * The value returned is the name of the root node that must have the
 * XML document being validated.
 * 
 * @param dtd The \ref axlDtd where the root node name will be
 * returned.
 * 
 * @return A reference to the internal representation of the root node
 * Value must not be deallocated.
 */
axlDtdElement  * axl_dtd_get_root        (axlDtd * dtd)
{
	axl_return_val_if_fail (dtd, NULL);
	
	/* return current status for the root node */
	if (dtd->root == NULL) {
		__axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "dtd root element not defined");
		return NULL;
	}
	return dtd->root;
}

/** 
 * @internal function used by \ref axl_dtd_get_element to perform node
 * lookups.
 */
axl_bool __find_dtd_element (axlPointer _element, axlPointer data)
{
	axlDtdElement * element = _element;
	char          * name    = data;

	/* check the name */
	if (axl_cmp (element->name, name))
		return axl_true;

	/* it is not the element */
	return axl_false;
}

/** 
 * @brief Allows to get the DTD element (\ref axlDtdElement), inside
 * the provided DTD (\ref axlDtd), that represent the spefication for
 * the node called by the provided name.
 * 
 * @param dtd The DTD (\ref axlDtd) where the lookup will be
 * performed.
 *
 * @param name The element name to lookup.
 * 
 * @return A reference to the \ref axlDtdElement searched or NULL if
 * fails. The function also returns NULL if values received are NULL.
 */
axlDtdElement      * axl_dtd_get_element      (axlDtd * dtd, const char * name)
{

	axl_return_val_if_fail (dtd, NULL);
	axl_return_val_if_fail (name, NULL);

	/* perform the lookup */
	return axl_list_lookup (dtd->elements, __find_dtd_element, (axlPointer) name);
}

/** 
 * @internal function used by \ref axl_dtd_get_attr to perform node
 * lookups.
 */
axl_bool __find_dtd_attr (axlPointer _element, axlPointer data)
{
	axlDtdAttribute * attr = _element;
	char            * name = data;

	/* check the name */
	if (axl_cmp (attr->name, name))
		return axl_true;

	/* it is not the element */
	return axl_false;
}

/** 
 * @brief Allows to get the set of attribute declerations for a
 * particular node. 
 *
 * The \ref axlDtdAttribute declaration contains all constraints
 * configured for attributes found for the particular xml node
 * (identified by <b>name</b>).
 * 
 * @param dtd A reference to the DTD document.
 *
 * @param nodeName The xml node that is requested to return all attribute
 * declarations.
 * 
 * @return A reference to the \ref axlDtdAttribute or NULL if it
 * fails.
 */
axlDtdAttribute    * axl_dtd_get_attr         (axlDtd * dtd,
					       const char * nodeName)
{
	axl_return_val_if_fail (dtd, NULL);
	axl_return_val_if_fail (nodeName, NULL);

	/* perform the lookup */
	return axl_list_lookup (dtd->attributes, __find_dtd_attr, (axlPointer) nodeName);
}

/** 
 * @brief Allows to get the number of constraints that have been
 * configured for the particular node.
 * 
 * @param dtd The reference to the DTD document.
 *
 * @param nodeName The name of the node that is being asked for its
 * constraints.
 * 
 * @return 0 or the number of contraints. The function return -1 if
 * any of the parameter received is null.
 */
int                  axl_dtd_get_attr_contraints (axlDtd * dtd,
						  const char * nodeName)
{
	axlDtdAttribute * attr;

	axl_return_val_if_fail (dtd, -1);
	axl_return_val_if_fail (nodeName, -1);

	/* get the attribute specification for the node */
	attr = axl_dtd_get_attr (dtd, nodeName);

	/* return the number of items */
	return axl_list_length (attr->list);
}

/** 
 * @brief Returns the name of the provided \ref axlDtdElement.
 * 
 * @param element A reference to a \ref axlDtdElement where the name
 * will be returned.
 * 
 * @return A reference to the internal DTD element name. Returned
 * value mustn't be deallocated.
 */
char           * axl_dtd_get_element_name (axlDtdElement * element)
{
	axl_return_val_if_fail (element,  NULL);

	return element->name;
}

/** 
 * @brief Returns current element type for the provided \ref axlDtdElement.
 * 
 * @param element The axlDtdElement where its type will be returned.
 * 
 * @return Current element type for the provided node.
 */
AxlDtdElementType    axl_dtd_get_element_type (axlDtdElement * element)
{
	axl_return_val_if_fail (element, ELEMENT_TYPE_UNKNOWN);
	
	return element->type;
}

/** 
 * @brief Returns current DTD content specification, represented by the Item list.
 * 
 * @param element The DTD element (\ref axlDtdElement) which is being
 * requested to return its \ref axlDtdElementList.
 * 
 * @return The \ref axlDtdElementList reference. The value returned
 * must not be deallocated. The function returns NULL if the reference received is NULL.
 */
axlDtdElementList  * axl_dtd_get_item_list    (axlDtdElement * element)
{
	axl_return_val_if_fail (element, NULL);

	return element->list; 
}

/** 
 * @brief Allows to check if the provided DTD ELEMENT representation
 * is a top level definition.
 * 
 * @param dtd The DTD document where the operation will be performed.
 * @param element The \ref axlDtdElement to check.
 * 
 * @return \ref axl_true if the dtd element is a top level element or
 * \ref axl_false if not. The function returns \ref axl_false if the
 * provided reference is NULL.
 */
axl_bool                    axl_dtd_element_is_toplevel (axlDtd * dtd, axlDtdElement * element)
{
	/* support several top level definitions */
	int             iterator;
	axlDtdElement * dtd_element_aux;

	axl_return_val_if_fail (dtd,     axl_false);
	axl_return_val_if_fail (element, axl_false);

	/* check which is the top */
	iterator        = 0;
	while (iterator < axl_list_length (dtd->elements)) {
			
		/* get the next reference */
		dtd_element_aux = axl_list_get_nth (dtd->elements, iterator);
			
		/* check which is the top */
		if (__axl_dtd_get_is_parent (dtd_element_aux, element)) {
			/* the element provided have a parent */
			return axl_false;
		}
			
		/* update inner loop iterator */
		iterator ++;
	} /* while end */

	/* return that the provided node doesn't have a parent node */
	return axl_true;
}

/** 
 * @brief Returns the number of item nodes (\ref
 * axlDtdElementListNode) inside the item list received (\ref axlDtdElementList).
 * 
 * @param itemList The \ref axlDtdElementList where the count
 * operation is being requested.
 * 
 * @return The number of item list the provided \ref axlDtdElementList
 * reference has. The function return -1 if the provided reference is
 * NULL.
 */
int                  axl_dtd_item_list_count  (axlDtdElementList * itemList)
{
	axl_return_val_if_fail (itemList, -1);

	if (itemList->itemList == NULL)
		return 0;

	return axl_list_length (itemList->itemList);
}

/** 
 * @brief Allows to get current configuration for the provided item
 * list, which is the content specification for a DTD element.
 * 
 * @param itemList The item list where the operation will be
 * performed.
 * 
 * @return Current configuration (\ref SEQUENCE or a \ref CHOICE).
 */
AxlDtdNestedType     axl_dtd_item_list_type   (axlDtdElementList * itemList)
{
	axl_return_val_if_fail (itemList, -1);

	return itemList->type;
}

/** 
 * @brief Allows to get current configuration for DTD content spec
 * repetition.
 * 
 * @param itemList The content spec where the query will be performed.
 * 
 * @return Current configuration for times to be repeated DTD element
 * content specification.
 */
AxlDtdTimes          axl_dtd_item_list_repeat (axlDtdElementList * itemList)
{
	axl_return_val_if_fail (itemList, DTD_TIMES_UNKNOWN);

	/* returns current times configuration */
	return itemList->times;
}

/** 
 * @brief Allows to get the provided item node reference (\ref
 * axlDtdElementListNode) from the provided item list (\ref
 * axlDtdElementList).
 *
 * Provided position ranges from 0 up to \ref axl_dtd_item_list_count.
 * 
 * @param itemList The itemList where the operation will be performed.
 * @param position The position where the item node will be looked up.
 * 
 * @return A reference to the \ref axlDtdElementListNode, or NULL if
 * there is no item node at the selected index.  The function return
 * NULL if the provided position is a non positive value or it is
 * greater than the current item list count (\ref
 * axl_dtd_item_list_count) or the provided item list reference is
 * NULL.
 */
axlDtdElementListNode * axl_dtd_item_list_get_node (axlDtdElementList * itemList, 
						    int position)
{
	axl_return_val_if_fail (itemList, NULL);
	axl_return_val_if_fail (position >= 0, NULL);
	axl_return_val_if_fail (position < axl_dtd_item_list_count (itemList), NULL);
	
	return axl_list_get_nth (itemList->itemList, position);
}

/** 
 * @brief Allows to get current node type for the provided DTD element
 * type content particule or item node (\ref axlDtdElementListNode).
 *
 * @param node The node where the type is being requested.
 * 
 * @return It returns if the item node contains a final leaf node,
 * making a reference to an explicit node naming that is allowed to be
 * used in the context where is found the provided \ref
 * axlDtdElementListNode or a \ref axlDtdElementList containing more
 * nodes or lists. 
 */
NodeType             axl_dtd_item_node_get_type (axlDtdElementListNode * node)
{
	axl_return_val_if_fail (node, AXL_ELEMENT_NOT_DEFINED);
	return node->type;
}

/** 
 * @brief Returns the item list inside the provided node.
 *
 * The node is supported to contain an item list reference or NULL
 * will be returned. Check \ref axl_dtd_item_node_get_type.
 * 
 * @param node The node where the operation will be performed.
 * 
 * @return The item list inside the node or NULL if fails.
 */
axlDtdElementList   * axl_dtd_item_node_get_list (axlDtdElementListNode * node)
{
	axl_return_val_if_fail (node, NULL);
	axl_return_val_if_fail (node->type == AXL_ELEMENT_LIST, NULL);

	return node->data;
}

/** 
 * @brief Allows to get the dtd item list value, which represents the
 * node name that is being constrained/represented.
 * 
 * @param node The item node where the value is being requested.
 * 
 * @return The value inside the item node, supposing it contains an
 * leaf item node or NULL if fails. The value returned must not be
 * deallocated.
 */
char               * axl_dtd_item_node_get_value (axlDtdElementListNode * node)
{
	axl_return_val_if_fail (node, NULL);
	if (node->type != AXL_ELEMENT_NODE) 
		return "requested-value-on-a-list";

	return node->data;
}

/** 
 * @brief Allows to get current configuration for the provided content
 * particule for the times to be repeated.
 * 
 * @param node The content particule where the query will be
 * performed.
 * 
 * @return Return current repetition configuration. 
 */
AxlDtdTimes          axl_dtd_item_node_get_repeat (axlDtdElementListNode * node)
{
	axlDtdElementList * list;

	axl_return_val_if_fail (node, DTD_TIMES_UNKNOWN);


	if (node->type == AXL_ELEMENT_NODE) {
		/* return value requested */
		return node->times;
	}

	if (node->type == AXL_ELEMENT_LIST) {
		/* return the requested value for an item list */
		list = node->data;
		return list->times;
	}
	
	/* return that we don't know man */
	return DTD_TIMES_UNKNOWN;
}


/** 
 * @internal
 *
 * Internal function which allows to lookup the DTD entity reference
 * provided the name and the type.
 */
axlDtdEntity * __axl_dtd_entity_lookup (axlDtd            * dtd, 
					const char        * name,
					axlDtdEntityType    type)
{
	axlDtdEntity  * entity;
	int             iterator;
	int             length;

	/* check values received */
	axl_return_val_if_fail (dtd,  NULL);
	axl_return_val_if_fail (name, NULL);

	/* lookup for the item */
	iterator = 0;
	length   = axl_list_length (dtd->entities);
	while (iterator < length) {

		/* get the entity at the provided position */
		entity = axl_list_get_nth (dtd->entities, iterator);

		/* check the type and the name */
		if ((entity->type == type) && axl_cmp (entity->name, name))
			return entity;
		
		/* update iterator */
		iterator++;
	} /* end while */

	return NULL;
}

/** 
 * @brief Allows to check if the provided entity name, with the
 * provided type is defined on the given DTD object.
 * 
 * @param dtd The \ref axlDtd instance where the entity lookup will be
 * performed.
 *
 * @param name The entity name to lookup.
 *
 * @param type The entity type to lookup.
 * 
 * @return axl_true if an entity is found named as provided with the type
 * provided. Othewise, axl_false is returned.
 */
axl_bool                 axl_dtd_entity_exists    (axlDtd            * dtd, 
						   const char        * name,
						   axlDtdEntityType    type)
{
	/* return if the entity exists */
	return (__axl_dtd_entity_lookup (dtd, name, type) != NULL);
}

/** 
 * @brief Allows to get the content configured inside the entity that
 * is identified by the provided name and the provided type.
 * 
 * @param dtd The DTD where the lookup will be performed.
 *
 * @param name The entity name to lookup for its content.
 *
 * @param type The entity type to match.
 * 
 * @return An internal reference to the content associated to the
 * entity found or NULL. In case the content is defined (as return
 * value) it must not be deallocated.
 */
char               * axl_dtd_entity_value     (axlDtd            * dtd, 
					       const char        * name,
					       axlDtdEntityType    type)
{
	axlDtdEntity * entity;

	/* get the entity reference */
	entity = __axl_dtd_entity_lookup (dtd, name, type);
	
	/* check the entity reference */
	axl_return_val_if_fail (entity, NULL);

	/* return the content */
	return entity->content;
}

/** 
 * @brief Allows to destroy the provided \ref axlDtd  document.
 * 
 * @param dtd The \ref axlDtd document to destroy.
 */
void       axl_dtd_free  (axlDtd * dtd)
{
	if (dtd == NULL) {
		__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "received a null DTD reference, doing nothing");
		return;
	}
	
	__axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "releasing the DTD reference");
	/* free dtd elements */
	if (dtd->elements)
		axl_list_free (dtd->elements);

	/* free entities */
	if (dtd->entities)
		axl_list_free (dtd->entities);

	/* free attributes */
	if (dtd->attributes)
		axl_list_free (dtd->attributes);

	/* free the node itself */
	axl_free (dtd);

	return;
}


/** 
 * @internal
 *
 * @brief Allows to release the memory hold by the given
 * axlDtdElement.
 * 
 * @param element The axlDtdElement to release.
 */
void       axl_dtd_element_free (axlDtdElement * element)
{
	if (element == NULL)
		return;

	/* free element name */
	if (element->name != NULL)
		axl_free (element->name);

	/* free element list definitions */
	axl_dtd_item_list_free (element->list);
	
	/* free element itself */
	axl_free (element);

	return;
}

/** 
 * @internal 
 *
 * @brief Deallocates memory used by the \ref axlDtdElementList
 * reference.
 * 
 * @param list The reference to deallocate.
 */
void axl_dtd_item_list_free (axlDtdElementList * list)
{
	if (list == NULL)
		return;
	
	/* check and deallocate the list provided */
	if (list->itemList != NULL)
		axl_list_free (list->itemList);
	
	/* deallocates the node itself */
	axl_free (list);
	return;
}

/* @} */


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>