Annotation of gpl/axl/src/axl_dtd.c, revision 1.1.1.2

1.1       misho       1: /*
                      2:  *  LibAxl:  Another XML library
                      3:  *  Copyright (C) 2006 Advanced Software Production Line, S.L.
                      4:  *
                      5:  *  This program is free software; you can redistribute it and/or
                      6:  *  modify it under the terms of the GNU Lesser General Public License
                      7:  *  as published by the Free Software Foundation; either version 2.1 of
                      8:  *  the License, or (at your option) any later version.
                      9:  *
                     10:  *  This program is distributed in the hope that it will be useful,
                     11:  *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
                     12:  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  
                     13:  *  GNU Lesser General Public License for more details.
                     14:  *
                     15:  *  You should have received a copy of the GNU Lesser General Public
                     16:  *  License along with this program; if not, write to the Free
                     17:  *  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
                     18:  *  02111-1307 USA
                     19:  *  
                     20:  *  You may find a copy of the license under this software is released
                     21:  *  at COPYING file. This is LGPL software: you are welcome to
                     22:  *  develop proprietary applications using this library without any
                     23:  *  royalty or fee but returning back any change, improvement or
                     24:  *  addition in the form of source code, project image, documentation
                     25:  *  patches, etc. 
                     26:  *
                     27:  *  For commercial support on build XML enabled solutions contact us:
                     28:  *          
                     29:  *      Postal address:
                     30:  *         Advanced Software Production Line, S.L.
                     31:  *         Edificio Alius A, Oficina 102,
                     32:  *         C/ Antonio Suarez Nº 10,
                     33:  *         Alcalá de Henares 28802 Madrid
                     34:  *         Spain
                     35:  *
                     36:  *      Email address:
                     37:  *         info@aspl.es - http://www.aspl.es/xml
                     38:  */
                     39: #include <axl_decl.h>
                     40: #include <axl.h>
                     41: 
                     42: #define LOG_DOMAIN "axl-dtd"
                     43: 
                     44: struct _axlDtdElementListNode {
                     45:        NodeType     type;
                     46:        AxlDtdTimes  times;
                     47:        axlPointer   data;
                     48: };
                     49: 
                     50: struct _axlDtdElementList {
                     51:        /** 
                     52:         * @brief Allows to configure how is given top level
                     53:         * configuration for nodes to be defined inside the xml
                     54:         * document being configured. As defined in the XML 1.0
                     55:         * Recomendation, available top level choices are: choice or
                     56:         * sequence. 
                     57:         *
                     58:         * They allow to configure allowed nodes to be selected as
                     59:         * childs, from a set of node names, called choice or to
                     60:         * configure which are the set of nodes to be used, in a
                     61:         * particular order, called sequence.
                     62:         *
                     63:         * This variable allows to configure which is the top level
                     64:         * section configuration: either a choice or a sequence.
                     65:         *
                     66:         * Keep in mind that, having only one element inside the
                     67:         * itemList, there is no difference between the sequence and
                     68:         * the choice.
                     69:         */
                     70:        AxlDtdNestedType      type;
                     71:        
                     72:        /** 
                     73:         * @brief Allows to configure how many times is repeated a
                     74:         * selection provided (by this element).
                     75:         */
                     76:        AxlDtdTimes           times;
                     77: 
                     78:        /** 
                     79:         * @brief Item list, which contains more axlDtdElementList
                     80:         * nodes, configuring elements allowed.
                     81:         */
                     82:        axlList             * itemList;
                     83: };
                     84: 
                     85: struct _axlDtdElement {
                     86:        /** 
                     87:         * @brief The document type element declaration name. This is
                     88:         * the name of the xml node being constrained.
                     89:         */
                     90:        char                * name;
                     91: 
                     92:        /** 
                     93:         * @brief This is the type of the xml node being constrained.
                     94:         */
                     95:        AxlDtdElementType     type;
                     96:        /** 
                     97:         * @brief List of available items.
                     98:         * 
                     99:         * This variable holds current top level list selection. See
                    100:         * axlDtdElementList.type variable.
                    101:         */
                    102:        axlDtdElementList   * list;
                    103: 
                    104:        /** 
                    105:         * @brief Minimum item list count to be matched while using
                    106:         * this DTD element rule.
                    107:         */
                    108:        int                    minimum_match;
                    109: };
                    110: 
                    111: struct _axlDtdAttributeDecl {
                    112:        /** 
                    113:         * @brief Attribute name. This is the attribute value defined
                    114:         * for the node.
                    115:         */
                    116:        char                     * name;
                    117:        
                    118:        /** 
                    119:         * @brief This is the attribute declaration type. It shows if 
                    120:         */
                    121:        AxlDtdAttributeType        type;
                    122: 
                    123:        /** 
                    124:         * @brief Allows to model whoe is 
                    125:         */
                    126:        AxlDtdAttributeDefaults    defaults;
                    127:        
                    128:        /** 
                    129:         * @brief This is a default value for the <!ATTLIST
                    130:         * declaration received, in the case a FIXED value is required
                    131:         * or a default value is declarted.
                    132:         */
                    133:        char                     * default_value;
                    134: 
                    135:        /** 
                    136:         * @brief Internal declaration for enum values defined for
                    137:         * this rule. This list is only initialized in the case enum
                    138:         * values are defined.
                    139:         */
                    140:        axlList                  * enumvalues;
                    141: 
                    142: };
                    143: 
                    144: struct _axlDtdAttribute {
                    145:        /** 
                    146:         * @brief The document attribute list declaration name. This
                    147:         * is the name of the node that will receive the constrain
                    148:         * defined.
                    149:         */
                    150:        char           * name;
                    151:        
                    152:        /** 
                    153:         * @brief This is the list of constrains defined for the
                    154:         * node. It as list of \ref axlDtdAttributeDecl which defines
                    155:         * the attribute that is declarted, if it is required, and the
                    156:         * type of its content.
                    157:         */
                    158:        axlList        * list;
                    159: };
                    160: 
                    161: struct _axlDtdEntityExternalData {
                    162:        /** 
                    163:         * @brief Contains the system literal reference. This is a URI
                    164:         * reference to the resource pointed by the \ref axlDtdEntity
                    165:         * definition.
                    166:         */
                    167:        char * system_literal;
                    168:        /** 
                    169:         * @brief Contains the public literal information associated
                    170:         * to the entity definition.
                    171:         */
                    172:        char * public_literal;
                    173:        /** 
                    174:         * @brief Contains the NDATA information (a notation name
                    175:         * reference).
                    176:         */
                    177:        char * ndata;
                    178: };
                    179: 
                    180: struct _axlDtdEntity {
                    181:        /** 
                    182:         * @brief Contains the entity name.
                    183:         */
                    184:        char           * name;
                    185:        
                    186:        /** 
                    187:         * @brief Contains the entity type.
                    188:         */
                    189:        axlDtdEntityType type;
                    190: 
                    191:        /** 
                    192:         * @brief Content of the entity definition ([9] EntityValue).
                    193:         */
                    194:        char           * content;
                    195:        
                    196:        /** 
                    197:         * @brief An entity definition can have a reference to a
                    198:         * external resource. The following pointer contains
                    199:         * information for the external resource pointed.
                    200:         */
                    201:        axlDtdEntityExternalData * data;
                    202: };
                    203: 
                    204: struct _axlDtd {
                    205:        /** 
                    206:         * @brief Holds all entity definitions inside the DTD
                    207:         * declaration (<!ENTITY..>).
                    208:         */
                    209:        axlList       * entities;
                    210: 
                    211:        /** 
                    212:         * @brief All elements inside the DTD declaration
                    213:         * (<!ELEMENT..> ).
                    214:         */
                    215:        axlList       * elements;
                    216: 
                    217:        /** 
                    218:         * @brief All attribute type declerations inside the DTD
                    219:         * (<!ATTLIST..>)
                    220:         */
                    221:        axlList       * attributes;
                    222: 
                    223:        /** 
                    224:         * @brief The element root, for the given DTD declaration.
                    225:         */
                    226:        axlDtdElement * root;
                    227: 
                    228:        /** 
                    229:         * @brief Internal flag that allows to notify that the DTD
                    230:         * contains ID attribute declaration, making the DTD this
                    231:         * references. 
                    232:         */
                    233:        axl_bool       haveIdDecl;
                    234: 
                    235:        /** 
                    236:         * @brief Flag that the dtd declaration have attributes which
                    237:         * are flaged as IDREF.
                    238:         */
                    239:        axl_bool      haveIdRefDecl;
                    240: };
                    241: 
                    242: /**
                    243:  * \defgroup axl_dtd_module Axl DTD: Document type declaration interface (functions, validation, and DTD parsing)
                    244:  */
                    245: 
                    246: 
                    247: /** 
                    248:  * \addtogroup axl_dtd_module
                    249:  * @{
                    250:  */
                    251: 
                    252: 
                    253: /** 
                    254:  * @internal
                    255:  *
                    256:  * Allows to create a new dtd element list item, which represents a
                    257:  * content particule inside an item list or a item list. This allows
                    258:  * the recursion defined on the XML 1.0 standard.
                    259:  *
                    260:  * The function receives the node name and a reference list. According
                    261:  * to the values the function creates a node which contains a leaf
                    262:  * value or a node which contains a reference to the a new list which
                    263:  * is nested.
                    264:  */
                    265: axlDtdElementListNode * __create_axl_dtd_element_list (char * node_name,
                    266:                                                       axlDtdElementList * list)
                    267: {
                    268:        axlDtdElementListNode * node;
                    269: 
                    270:        node = axl_new (axlDtdElementListNode, 1);
                    271: 
                    272:        /* create a node element reference */
                    273:        if (node_name != NULL) {
                    274:                node->data = node_name;
                    275:                node->type = AXL_ELEMENT_NODE;
                    276:                return node;
                    277:        }
                    278: 
                    279:        /* create an element list reference */
                    280:        if (list != NULL) {
                    281:                node->data = list;
                    282:                node->type = AXL_ELEMENT_LIST;
                    283:                return node;
                    284:        }
                    285: 
                    286:        /* if another type is requested, return NULL */
                    287:        return NULL;
                    288: }
                    289: 
                    290: /** 
                    291:  * @internal
                    292:  *
                    293:  * Support function used to destroy all items stored on a item list.
                    294:  * 
                    295:  * @param node 
                    296:  */
                    297: void __destroy_axl_dtd_element_list (axlDtdElementListNode * node)
                    298: {
                    299:        if (node == NULL)
                    300:                return;
                    301:        /* free the reference to the leaf node if defined */
                    302:        if (node->type == AXL_ELEMENT_NODE)
                    303:                axl_free (node->data);
                    304:        
                    305:        /* do not do nothing if the reference is not element list */
                    306:        if (node->type == AXL_ELEMENT_LIST)
                    307:                axl_dtd_item_list_free (node->data);
                    308: 
                    309:        /* free de node itself */
                    310:        axl_free (node);
                    311:        return;
                    312: }
                    313: 
                    314: /** 
                    315:  * @internal
                    316:  *
                    317:  * @brief Support function to \ref axl_dtd_parse which creates a new
                    318:  * empty DTD reference.
                    319:  * 
                    320:  * 
                    321:  * @return A newly allocated \ref axlDtd reference.
                    322:  */
                    323: axlDtd * __axl_dtd_new (void)
                    324: {
                    325:        axlDtd * dtd;
                    326: 
                    327:        /* create the DTD element and nothing else. The rest of items
                    328:         * created on demand */
                    329:        dtd           = axl_new (axlDtd, 1);
                    330: 
                    331:        return dtd;
                    332: }
                    333: 
                    334: axl_bool __queue_items (axlPointer data, axlPointer _stack)
                    335: {
                    336:        axlStack * stack = _stack;
                    337: 
                    338:        /* queue the data */
                    339:        axl_stack_push (stack, data);
                    340: 
                    341:        /* return axl_false to make the function to not stop */
                    342:        return axl_false;
                    343: }
                    344: 
                    345: void __axl_dtd_queue_childs (axlStack * stack, axlNode * parent)
                    346: {
                    347:        axlNode * child;
                    348: 
                    349:        /* get the first child */
                    350:        child = axl_node_get_first_child (parent);
                    351:        while (child != NULL) {
                    352: 
                    353:                /* queue the child */
                    354:                axl_stack_push (stack, child);
                    355:                
                    356:                /* get the next child */
                    357:                child = axl_node_get_next (child);
                    358:        } /* end while */
                    359: 
                    360:        return;
                    361: }
                    362: 
                    363: /** 
                    364:  * @internal
                    365:  *
                    366:  * Support internal function which allows to queue all items inside an
                    367:  * axlDtdElementList to be checked.
                    368:  * 
                    369:  * @param stack The stack where all data will be placed.
                    370:  *
                    371:  * @param dtd_element_list The dtd element list where the data will be
                    372:  * extracted.
                    373:  */
                    374: void __axl_dtd_queue_items (axlStack * stack, axlList * list) 
                    375: {
                    376:        /* call to queue items */
                    377:        axl_list_lookup (list, __queue_items, stack);
                    378: 
                    379:        /* nothing more */
                    380:        return;
                    381: }
                    382: 
                    383: /** 
                    384:  * @internal
                    385:  *
                    386:  * Support function which allows to check if the provided two dtd
                    387:  * elements are in fact, parent and child.
                    388:  *
                    389:  * DTD element have a parent-child relation based in the fact that the
                    390:  * first define top level xml nodes that are followed, in the form of
                    391:  * childs nodes, by other DTD elements that define more childs, etc...
                    392:  *
                    393:  * This function allows to check if the provided parent dtd element
                    394:  * have references inside its content specification that proves that
                    395:  * it is indeed a parent definition.
                    396:  * 
                    397:  * @param dtd_element_parent The supposed DTD parent element.
                    398:  * @param dtd_element_child  The supposedd DTD child element.
                    399:  * 
                    400:  * @return \ref axl_true if the function can confirm that the parent-child
                    401:  * relation exists, \ref axl_false if not or it could be proved.
                    402:  */
                    403: axl_bool     __axl_dtd_get_is_parent (axlDtdElement * dtd_element_parent,
                    404:                                      axlDtdElement * dtd_element_child)
                    405: {
                    406:        axlStack               * stack;
                    407:        axlDtdElementListNode  * node;
                    408:        axlDtdElementList      * list;
                    409: 
                    410:        /* check for leaf nodes, that, by definition, could be a
                    411:         * parent of nothing. */
                    412:        if (dtd_element_parent->list == NULL || dtd_element_parent->list->itemList == NULL) {
                    413:                return axl_false;
                    414:        }
                    415: 
                    416:        /* prepare all elements inside the stack to be checked */
                    417:        stack = axl_stack_new (NULL);
                    418:        __axl_dtd_queue_items (stack, dtd_element_parent->list->itemList);
                    419:        
                    420: 
                    421:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "stack size to operate: %d, list: %d", 
                    422:                   axl_stack_size (stack),
                    423:                   axl_list_length (dtd_element_parent->list->itemList));
                    424: 
                    425:        /* now search for a content particule that makes are reference
                    426:         * to the child DTD element */
                    427:        do {
                    428:                node = axl_stack_pop (stack);
                    429:                switch (node->type) {
                    430:                case AXL_ELEMENT_NODE:
                    431:                        /* leaf node case */
                    432:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a leaf node, checking it");
                    433: 
                    434:                        /* seems this is a final node */
                    435:                        if (axl_cmp (node->data, dtd_element_child->name)) {
                    436:                                /* seems that the content
                    437:                                 * specification makes a reference to
                    438:                                 * the child node. */
                    439:                                axl_stack_free (stack);
                    440:                                return axl_true;
                    441:                        }
                    442:                        break;
                    443:                case AXL_ELEMENT_LIST:
                    444:                        /* a nested list case */
                    445:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a complex node queuing its internal elements, while checking parent=%s for child=%s",
                    446:                                   dtd_element_parent->name, dtd_element_child->name);
                    447:                        /* the item list read, is a complex value,
                    448:                         * queue all items inside to be inspected */
                    449:                        list = node->data;
                    450:                        __axl_dtd_queue_items (stack, list->itemList);
                    451:                        break;
                    452:                case AXL_ELEMENT_NOT_DEFINED:
                    453:                        /* do nothing */
                    454:                        break;
                    455:                }
                    456:                
                    457:                /* iterate until all elements are evaluated */
                    458:        }while (! axl_stack_is_empty (stack));
                    459: 
                    460:        /* deallocates no longer used stack */
                    461:        axl_stack_free (stack);
                    462:        
                    463:        /* either it isn't the parent or it can't be proved. */
                    464:        return axl_false;
                    465: }
                    466: 
                    467: 
                    468: /** 
                    469:  * @internal
                    470:  * 
                    471:  * Support function which allows to get which is the most top root
                    472:  * node for the provided set of DTD elements.
                    473:  */
                    474: axlDtdElement * __axl_dtd_get_new_root (axlDtd * dtd) 
                    475: {
                    476:        int             iterator;
                    477:        axl_bool        change_detected;
                    478: 
                    479:        axlDtdElement * dtd_element_aux;
                    480:        axlDtdElement * dtd_element_the_root_is_on_fire;
                    481: 
                    482:        /* set the very first root node */
                    483:        dtd_element_the_root_is_on_fire = axl_list_get_nth (dtd->elements, 0);
                    484:        
                    485:        do {
                    486:                /* check which is the top */
                    487:                iterator        = 0;
                    488:                change_detected = axl_false;
                    489:                while (iterator < axl_list_length (dtd->elements)) {
                    490:                        
                    491:                        /* get the next reference */
                    492:                        dtd_element_aux = axl_list_get_nth (dtd->elements, iterator);
                    493:                        
                    494:                        /* check which is the top */
                    495:                        if (__axl_dtd_get_is_parent (dtd_element_aux,
                    496:                                                     dtd_element_the_root_is_on_fire)) {
                    497:                                /* it seems that the new element is the root
                    498:                                 * one, update the reference */
                    499:                                dtd_element_the_root_is_on_fire = dtd_element_aux;
                    500:                                change_detected = axl_true;
                    501:                        }
                    502:                        
                    503:                        /* update inner loop iterator */
                    504:                        iterator ++;
                    505:                } /* while end */
                    506:        }while (change_detected);
                    507: 
                    508:        /* return the root found */
                    509:        return dtd_element_the_root_is_on_fire;
                    510: }
                    511: 
                    512: /** 
                    513:  * @internal 
                    514:  *
                    515:  * @brief Adds the axlDtdElement into the given axlDtd definition,
                    516:  * checking that everything is properly configured, and ensuring that
                    517:  * the root element gets properly configured.
                    518:  * 
                    519:  * @param dtd The \ref axlDtd object that will receive the
                    520:  * axlDtdElement.
                    521:  *
                    522:  * @param stream The \ref axlStream object that will be destroyed if
                    523:  * something wrong is found.
                    524:  *
                    525:  * @param element The axlDtdElement to be added to the give axlDtd
                    526:  * object.
                    527:  * 
                    528:  * @return axl_true if the given axlDtdElement is compatible inside
                    529:  * the axlDtd declaration or axl_false if a error is found.
                    530:  */
                    531: axl_bool     __axl_dtd_add_element (axlDtd * dtd, axlDtdElement * element, 
                    532:                                    axlStream * stream, axlError ** error)
                    533: {
                    534:        int             iterator        = 0;
                    535:        axlDtdElement * dtd_element_aux = NULL;
                    536: 
                    537:        /* check that there is no element already named like the
                    538:         * element received. If it is the case drop an error */
                    539:        while (iterator < axl_list_length (dtd->elements)) {
                    540:                dtd_element_aux = axl_list_get_nth (dtd->elements, iterator);
                    541:                if (axl_cmp (dtd_element_aux->name, element->name)) {
                    542:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "DTD element for <%s> == <%s> was defined twice", 
                    543:                                   dtd_element_aux->name, element->name);
                    544: 
                    545:                        axl_error_new (-1, "Find that an DTD element was defined twice (no more than one time is allowed)", 
                    546:                                       stream, error);
                    547:                        axl_stream_free (stream);
                    548:                        return axl_false;
                    549:                }
                    550: 
                    551:                /* update current iterator */
                    552:                iterator++;
                    553:        }
                    554:        
                    555:        /* add the new DTD element to the list */
                    556:        axl_list_add (dtd->elements, element);
                    557:        return axl_true;
                    558: }
                    559: 
                    560: /** 
                    561:  * @internal
                    562:  * 
                    563:  * Internal support function which adds the provided content particule
                    564:  * to the dtd item list received. It also perform all operations
                    565:  * required for the chunk_matched option received.
                    566:  *
                    567:  * In the case the function fails to do its work, it will deallocate
                    568:  * the stream, filling the error received.
                    569:  *
                    570:  * According to the chunk matched value, the function will react
                    571:  * adding the element and configuring current element list.
                    572:  *
                    573:  */
                    574: axl_bool     __axl_dtd_element_content_particule_add (axlDtdElementList  * dtd_item_list, 
                    575:                                                      char               * string_aux, 
                    576:                                                      int                  chunk_matched, 
                    577:                                                      axlStream          * stream, 
                    578:                                                      axlError          **error)
                    579: {
                    580:        axlDtdElementListNode * node;
                    581: 
                    582:        /* check if the item list was creted or not */
                    583:        if (dtd_item_list->itemList == NULL) {
                    584:                dtd_item_list->itemList = axl_list_new (axl_list_always_return_1, 
                    585:                                                        (axlDestroyFunc) __destroy_axl_dtd_element_list);
                    586:        }
                    587: 
                    588:        /* create the node to be added */
                    589:        node = __create_axl_dtd_element_list (string_aux, NULL);
                    590: 
                    591:        /* know add the element found */
                    592:        axl_list_add (dtd_item_list->itemList, node);
                    593: 
                    594:        /* set configuration for item repetition */
                    595:        switch (chunk_matched) {
                    596:        case 4:
                    597:                /* one or many times */
                    598:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "setting one to many repeat pattern: (+)");
                    599:                node->times = ONE_OR_MANY;
                    600:                break;
                    601:        case 5:
                    602:                /* zero or many times */
                    603:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "setting zero to many repeat pattern: (*)");
                    604:                node->times = ZERO_OR_MANY;
                    605:                break;
                    606:        case 6:
                    607:                /* zero or one time */
                    608:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "setting one to one repeat pattern: (?)");
                    609:                node->times = ZERO_OR_ONE;
                    610:                break;
                    611:        default:
                    612:                /* one and only one time */
                    613:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "setting one and only one repeat pattern: ()");
                    614:                node->times = ONE_AND_ONLY_ONE;
                    615:        }
                    616: 
                    617:        /* return that all is ok */
                    618:        return axl_true;
                    619: }
                    620: 
                    621: 
                    622: /** 
                    623:  * @internal
                    624:  * 
                    625:  * @brief Support function which allows to get current repetition
                    626:  * configuration.
                    627:  * 
                    628:  * @param stream The stream where the operation will be performed.
                    629:  * 
                    630:  * @return Current configuration read, the function will properly work
                    631:  * if it is called when it is espected to find a content specification
                    632:  * repetition. If not found, the \ref ONE_AND_ONLY_ONE is returned.
                    633:  */
                    634: AxlDtdTimes __axl_dtd_get_repetition_conf (axlStream * stream)
                    635: {
                    636:        axl_return_val_if_fail (stream, ONE_AND_ONLY_ONE);
                    637: 
                    638:        if (axl_stream_inspect (stream, "?", 1) > 0) {
                    639: 
                    640:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found '?' repetition conf");
                    641:                /* seems the content specification could appear zero
                    642:                 * or one time */
                    643:                return ZERO_OR_ONE;
                    644: 
                    645:        } else if (axl_stream_inspect (stream, "+", 1) > 0) {
                    646: 
                    647:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found '+' repetition conf");
                    648:                /* seems the content specification must appear one up
                    649:                 * to many */
                    650:                return ONE_OR_MANY;
                    651: 
                    652:        } else if (axl_stream_inspect (stream, "*", 1) > 0) {
                    653: 
                    654:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found '*' repetition conf");
                    655:                /* seems the content specification could appear zero
                    656:                 * up to many */
                    657:                return ZERO_OR_MANY;
                    658:        } 
                    659: 
                    660:        /* the content specification must appear */
                    661:        return ONE_AND_ONLY_ONE;
                    662: }
                    663: 
                    664: /** 
                    665:  * @internal
                    666:  *
                    667:  * Support function which creates a child item list, insert it to the
                    668:  * parent item list received.
                    669:  * 
                    670:  * @param parent 
                    671:  * 
                    672:  * @return 
                    673:  */
                    674: axlDtdElementList * __axl_dtd_create_and_queue (axlDtdElementList * parent)
                    675: {
                    676:        axlDtdElementList     * child;
                    677:        axlDtdElementListNode * node;
                    678:        
                    679:        /* create the DTD item list */
                    680:        child       = axl_new (axlDtdElementList, 1);
                    681: 
                    682:        /* make by default the item list to be defined as "not
                    683:         * defined" until the first separator is found */
                    684:        child->type = STILL_UNDEF; 
                    685:        
                    686:        /* create a node that */
                    687:        node = __create_axl_dtd_element_list (NULL, child);
                    688: 
                    689:        /* create the parent list reference if weren't */
                    690:        if (parent->itemList == NULL) {
                    691:                parent->itemList = axl_list_new (axl_list_always_return_1, 
                    692:                                                 (axlDestroyFunc) __destroy_axl_dtd_element_list);
                    693:        }
                    694: 
                    695:        /* add the node */
                    696:        axl_list_add (parent->itemList, node);
                    697: 
                    698:        /* return the new child created */
                    699:        return child;
                    700: }
                    701: 
                    702: /** 
                    703:  * @internal
                    704:  *
                    705:  * Updates current chunk readed information to allow perform a better
                    706:  * code after calling this function.
                    707:  *
                    708:  */
                    709: void __axl_dtd_element_spec_update_chunk_matched (axlStream * stream, 
                    710:                                                  int * chunk_matched)
                    711: {
                    712:        /* check for for sequence or choice characters */
                    713:        if (axl_stream_inspect (stream, ",", 1) > 0) {
                    714:                /* flag that we have found a , (choice)
                    715:                 * separator */
                    716:                (*chunk_matched) = 1;
                    717:                
                    718:        } else if (axl_stream_inspect (stream, "|", 1) > 0) {
                    719:                /* flag that we have found a | (sequence)
                    720:                 * separator */
                    721:                (*chunk_matched) = 2;
                    722: 
                    723:        } else if (axl_stream_inspect (stream, ")", 1) > 0) {
                    724:                /* flag that we have found a | (sequence)
                    725:                 * separator */
                    726:                (*chunk_matched) = 3;
                    727:                
                    728:        } else if (axl_stream_inspect (stream, "+", 1) > 0) {
                    729:                /* flag that we have found a | (sequence)
                    730:                 * separator */
                    731:                (*chunk_matched) = 4;
                    732:                
                    733:        } else if (axl_stream_inspect (stream, "*", 1) > 0) {
                    734:                /* flag that we have found a | (sequence)
                    735:                 * separator */
                    736:                (*chunk_matched) = 5;
                    737:                
                    738:        } else if (axl_stream_inspect (stream, "?", 1) > 0) {
                    739:                /* flag that we have found a | (sequence)
                    740:                 * separator */
                    741:                (*chunk_matched) = 6;
                    742:        }
                    743: 
                    744:        return;
                    745: }
                    746: 
                    747: /** 
                    748:  * @internal
                    749:  *
                    750:  * Support function to read the content particule separator once the
                    751:  * repeat pattern was found 
                    752:  * 
                    753:  */
                    754: axl_bool     __axl_dtd_element_spec_update_chunk_matched_for_cp_separator (axlStream * stream, 
                    755:                                                                           int * chunk_matched)
                    756: {
                    757:        /* consume previous white spaces */
                    758:        AXL_CONSUME_SPACES (stream);
                    759: 
                    760:        /* check for for sequence or choice characters */
                    761:        if (axl_stream_inspect (stream, ",", 1) > 0) {
                    762:                /* flag that we have found a , (choice)
                    763:                 * separator */
                    764:                (*chunk_matched) = 1;
                    765:                return axl_true;
                    766:                
                    767:        } else if (axl_stream_inspect (stream, "|", 1) > 0) {
                    768:                /* flag that we have found a | (sequence)
                    769:                 * separator */
                    770:                (*chunk_matched) = 2;
                    771:                return axl_true;
                    772: 
                    773:        } else if (axl_stream_inspect (stream, ")", 1) > 0) {
                    774:                /* flag that we have found a | (sequence)
                    775:                 * separator */
                    776:                (*chunk_matched) = 3;
                    777:                return axl_true;
                    778:        }
                    779:        
                    780:        return axl_false;
                    781: }
                    782: 
                    783: /** 
                    784:  * @internal
                    785:  *
                    786:  * Support function which allows to read the next content particule.
                    787:  */
                    788: char * __axl_dtd_read_content_particule (axlStream  * stream, 
                    789:                                         int        * chunk_matched,
                    790:                                         axlStack   * dtd_item_stack, 
                    791:                                         axlError  ** error)
                    792: {
                    793:        char * string_aux;
                    794: 
                    795:        /* read the spec particule stopping when a white space
                    796:         * or other character is found */
                    797:        string_aux = axl_stream_get_until (stream, NULL, chunk_matched, axl_true, 8, 
                    798:                                           /* basic, default delimiters: 0, 1, 2, 3 */
                    799:                                           " ", ",", "|", ")",
                    800:                                           /* repetition configuration: 4, 5, 6 */
                    801:                                           "+", "*", "?",
                    802:                                           /* new dtd item list being opened: 8 */
                    803:                                           "(");
                    804:        if (string_aux == NULL) {
                    805:                axl_error_new (-1, "Expected to find a element content specification particule, but it wasn't found",
                    806:                               stream, error);
                    807:                axl_stack_free (dtd_item_stack);
                    808:                axl_stream_free (stream);
                    809:                return NULL;
                    810:        }
                    811:        
                    812:        /* check the user doesn't nest item list in a not
                    813:         * proper way */
                    814:        if (*chunk_matched == 8) {
                    815:                axl_error_new (-1, "Found a not proper nesting item list for a DTD element, before using ( a separator must be used (CHOICE: |, SEQUENCE: ,)",
                    816:                               stream, error);
                    817:                axl_stack_free (dtd_item_stack);
                    818:                axl_stream_free (stream);
                    819:                return NULL;
                    820:        }
                    821: 
                    822:        /* nullify stream internal reference */
                    823:        axl_stream_nullify (stream, LAST_CHUNK);
                    824:        
                    825:        /* return the content particule found */
                    826:        return string_aux;
                    827: }
                    828: 
                    829: /** 
                    830:  * @internal
                    831:  *
                    832:  * Support function which reads current <!ELEMENT specification,
                    833:  * configuring it to the received axlDtdElement.
                    834:  * 
                    835:  * @param stream The stream where the axlDtdElement spec will be read.
                    836:  *
                    837:  * @param dtd_element The axlDtdElement that will receive the content
                    838:  * spec.
                    839:  *
                    840:  * @param error An optional \ref axlError, where errors will be
                    841:  * reported.
                    842:  * 
                    843:  * @return \ref axl_true if the content spec was properly read or \ref
                    844:  * axl_false if not.
                    845:  */
                    846: axl_bool     __axl_dtd_read_element_spec (axlStream * stream, axlDtdElement * dtd_element, axlError ** error)
                    847: {
                    848:        char              * string_aux;
                    849:        axl_bool            is_pcdata;
                    850:        int                 chunk_matched = -1;
                    851:        axlStack          * dtd_item_stack;
                    852:        axlDtdElementList * dtd_item_list;
                    853:        axl_bool            is_empty;
                    854:        
                    855:        
                    856:        /* create the stack used to control which is
                    857:         * the current context for the items read for
                    858:         * the xml DTD especification (pd, pd2, (pr|po), ..) */
                    859:        dtd_item_stack = axl_stack_new (NULL);
                    860: 
                    861:        /* create the DTD item list */
                    862:        dtd_item_list       = axl_new (axlDtdElementList, 1);
                    863: 
                    864:        /* by default, set still undef to change it once a separator
                    865:         * is detected or the function ends. This will help to detect
                    866:         * problems produced by people mixing content element
                    867:         * separators. */
                    868:        dtd_item_list->type = STILL_UNDEF; 
                    869: 
                    870:        /* set the content spec list to the dtd element read */
                    871:        dtd_element->list   = dtd_item_list;
                    872:           
                    873:        /* push the item created */
                    874:        /* axl_stack_push (dtd_item_stack, dtd_item_list); */
                    875:        
                    876:        /* consume previous white spaces */
                    877:        AXL_CONSUME_SPACES (stream);
                    878: 
                    879:        /* check that the content specification have an ( */
                    880:        if (! (axl_stream_inspect (stream, "(", 1))) {
                    881:                axl_error_new (-1, "Expected to find a element content specification opener \"(\", but it wasn't found",
                    882:                               stream, error);
                    883:                axl_stack_free (dtd_item_stack);
                    884:                axl_stream_free (stream);               
                    885:                return axl_false;
                    886:        }
                    887:        
                    888:        do {
                    889:                /* consume previous white spaces */
                    890:                AXL_CONSUME_SPACES (stream);
                    891: 
                    892:                /* a new item list have been opened */
                    893:                if (axl_stream_inspect (stream, "(", 1) > 0) {
                    894: 
                    895:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a DTD item list openining: %d",
                    896:                                   axl_stack_size (dtd_item_stack));
                    897: 
                    898:                        /* a new item list is being defined, we have
                    899:                         * to queue current dtd_item_list and create a
                    900:                         * new item list */
                    901:                        axl_stack_push (dtd_item_stack, dtd_item_list);
                    902:                        
                    903:                        /* create the DTD item list */
                    904:                        dtd_item_list        = __axl_dtd_create_and_queue (dtd_item_list);
                    905: 
                    906:                        /* let's continue at the begining */
                    907:                        continue;
                    908:                }
                    909:                
                    910: 
                    911:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "iterating again to get a new content particule (item list size: %d)",
                    912:                           axl_dtd_item_list_count (dtd_item_list));
                    913: 
                    914:                /* read the next content particule: here is the chunk
                    915:                 * matched codes found: 
                    916:                 * basic, default delimiters: 
                    917:                 * 0, 1, 2, 3 -> " ", ",", "|", ")" 
                    918:                 * repetition configuration: 
                    919:                 * 4, 5, 6  -> "+", "*", "?",
                    920:                 * new dtd item list being opened: 
                    921:                 * 8 -> "(" */
                    922:                string_aux = __axl_dtd_read_content_particule (stream, &chunk_matched, dtd_item_stack, error);
                    923:                if (string_aux == NULL)
                    924:                        return axl_false;
                    925:                
                    926:                /* check, and record, that the string read is
                    927:                 * PCDATA */
                    928:                is_pcdata = axl_cmp (string_aux, "#PCDATA");
                    929: 
                    930:                /* add the item read if have something defined */
                    931: 
                    932:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found content spec particule: (size: %d) '%s'", 
                    933:                           strlen (string_aux),
                    934:                           string_aux);
                    935: 
                    936:                /* check if the have matched a white space: next check is
                    937:                 * based on the call to axl_stream_get_until at the caller
                    938:                 * function: " " */
                    939:                if (chunk_matched == 0) {
                    940: 
                    941:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, 
                    942:                                   "found white spaces as delimiter, consuming them (current chunk matched: %d)",
                    943:                                   chunk_matched);
                    944:                        
                    945:                        /* consume previous white spaces */
                    946:                        AXL_CONSUME_SPACES (stream);
                    947: 
                    948:                        /* update current chunk_matched to conform to
                    949:                         * an stream that have all elements really
                    950:                         * close: the following function tries to read
                    951:                         * and update chunk_matched variable to point
                    952:                         * to the value read for ",", "|", "+", "*",
                    953:                         * "?" and ")" because white spaces were found */
                    954:                        __axl_dtd_element_spec_update_chunk_matched (stream, &chunk_matched);
                    955: 
                    956: 
                    957:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, 
                    958:                                   "current chunk matched before update (%d)",
                    959:                                   chunk_matched);
                    960:                }
                    961: 
                    962:                /* add the content particule found, this function
                    963:                 * already detect that a white space was found and
                    964:                 * consumes all white spaces found */
                    965:                if (!__axl_dtd_element_content_particule_add (dtd_item_list, string_aux, chunk_matched, stream, error))
                    966:                        return axl_false;
                    967: 
                    968:                if (chunk_matched == 4 || chunk_matched == 5 || chunk_matched == 6) {
                    969:                        /* found a repetition pattern */
                    970:                        if (! __axl_dtd_element_spec_update_chunk_matched_for_cp_separator (stream, &chunk_matched)) {
                    971:                                axl_error_new (-1, "Before a repetition pattern (*,+,?) expected to find a content particule separator",
                    972:                                               stream, error);
                    973:                                axl_stack_free (dtd_item_stack);
                    974:                                axl_stream_free (stream);               
                    975:                                return axl_false;
                    976:                        }
                    977:                }
                    978: 
                    979:                /* set current sequence type accoring to separators
                    980:                 * used */
                    981:                switch (chunk_matched) {
                    982:                case 1:
                    983:                        if (dtd_item_list->type == CHOICE) {
                    984:                                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 (|)",
                    985:                                               stream, error);
                    986:                                axl_stack_free (dtd_item_stack);
                    987:                                axl_stream_free (stream);               
                    988:                                return axl_false;
                    989:                        }
                    990:                        dtd_item_list->type = SEQUENCE;
                    991:                        break;
                    992:                case 2:
                    993:                        if (dtd_item_list->type == SEQUENCE) {
                    994:                                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 (,)",
                    995:                                               stream, error);
                    996:                                axl_stack_free (dtd_item_stack);
                    997:                                axl_stream_free (stream);               
                    998:                                return axl_false;
                    999:                        }
                   1000:                        dtd_item_list->type = CHOICE;
                   1001:                        break;
                   1002:                }
                   1003: 
                   1004:                /* set element type if a element list terminator was
                   1005:                 * found ( 3 = ')' = chunk_matched) */
                   1006:                if ((chunk_matched == 3) && is_pcdata) {
                   1007:                        if (axl_list_length (dtd_item_list->itemList) == 1)
                   1008:                                dtd_element->type = ELEMENT_TYPE_PCDATA;
                   1009:                        else if (axl_list_length (dtd_item_list->itemList) > 1)
                   1010:                                dtd_element->type = ELEMENT_TYPE_MIXED;
                   1011:                }
                   1012: 
                   1013:                /* pop current element list header */
                   1014:                if (chunk_matched == 3) {
                   1015:                        do {
                   1016:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a DTD item list termination: stack status: %d",
                   1017:                                           axl_stack_size (dtd_item_stack));
                   1018:                                /* consume previous white spaces */
                   1019:                                AXL_CONSUME_SPACES (stream);
                   1020:                                dtd_item_list->times = __axl_dtd_get_repetition_conf (stream);
                   1021: 
                   1022:                                /* consume previous white spaces */
                   1023:                                AXL_CONSUME_SPACES (stream);
                   1024: 
                   1025:                                if (axl_stream_inspect (stream, ",", 1) > 0) {
                   1026:                                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a sequence (,) separator while reading terminator list");
                   1027: 
                   1028:                                        chunk_matched = 1;
                   1029:                                }
                   1030:                                else if (axl_stream_inspect (stream, "|", 1) > 0) {
                   1031:                                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a choice (|) separator while reading terminator list");
                   1032:                                        chunk_matched = 2;
                   1033:                                }
                   1034:                                
                   1035:                                /* this means that a ) was found, we have to
                   1036:                                 * pop current queue */
                   1037:                                is_empty              = axl_stack_is_empty (dtd_item_stack);
                   1038:                                if (! is_empty) {
                   1039:                                        dtd_item_list = axl_stack_pop (dtd_item_stack);
                   1040:                                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "getting the next item list in the stack, stack status: %d",
                   1041:                                                   axl_stack_size (dtd_item_stack));
                   1042:                                }
                   1043: 
                   1044:                                /* special case: check if the next element to
                   1045:                                 * be read is a new ) */
                   1046:                                /* consume previous white spaces */
                   1047:                                AXL_CONSUME_SPACES (stream);
                   1048: 
                   1049:                        }while ((axl_stream_inspect (stream, ")", 1) > 0) && !is_empty);
                   1050: 
                   1051:                        /* drop a log */
                   1052:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "terminator sequence status: chunk matched=%d ans stack status: %d",
                   1053:                                   chunk_matched, axl_stack_size (dtd_item_stack));
                   1054: 
                   1055:                }
                   1056: 
                   1057:                /* check if we have finished */
                   1058:        } while (chunk_matched != 3 || (! axl_stack_is_empty (dtd_item_stack)));
                   1059: 
                   1060: 
                   1061:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "content spec terminated, now lookup for the termination");
                   1062:                
                   1063:        /* consume previous white spaces */
                   1064:        /* AXL_CONSUME_SPACES (stream);*/
                   1065: 
                   1066:        /* read here repetition specification */
                   1067:        /* dtd_item_list->times = __axl_dtd_get_repetition_conf (stream); */
                   1068:        
                   1069:        /* set default content element separator */
                   1070:        if (dtd_item_list->type == STILL_UNDEF)
                   1071:                dtd_item_list->type = SEQUENCE;
                   1072:                
                   1073:        /* free the stack used */
                   1074:        axl_stack_free (dtd_item_stack);
                   1075: 
                   1076: 
                   1077:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "DTD content element specification found and parsed ok");
                   1078: 
                   1079: 
                   1080:        /* content spec readed properly */
                   1081:        return axl_true;
                   1082: }
                   1083: 
                   1084: /** 
                   1085:  * @internal
                   1086:  * 
                   1087:  * Calculates the number of nodes to be matched at minimum for the
                   1088:  * provided DTD element. 
                   1089:  * 
                   1090:  * @param element The DTD element to configure with its minimum item
                   1091:  * count to be matched.
                   1092:  */
                   1093: int __axl_dtd_parse_element_get_compulsory_num (axlDtdElementList * list)
                   1094: {
                   1095:        axlDtdElementListNode * itemNode;
                   1096:        int                     count    = 0;
                   1097:        int                     iterator = 0;
                   1098: 
                   1099:        /* check for null parameters */
                   1100:        if (list == NULL)
                   1101:                return 0;
                   1102: 
                   1103:        /* only count for repetitiong patterns that makes obligatory
                   1104:         * to have childs */
                   1105:        if (list->times == ONE_AND_ONLY_ONE ||
                   1106:            list->times == ONE_OR_MANY) {
                   1107:                
                   1108:                while (iterator < axl_list_length (list->itemList)) {
                   1109:                        /* get the reference for the item node */
                   1110:                        itemNode = axl_list_get_nth (list->itemList, iterator);
                   1111:                        
                   1112:                        /* check if the repetitiong patter is
                   1113:                         * compulsory */
                   1114:                        if (itemNode->times == ONE_OR_MANY ||
                   1115:                            itemNode->times == ONE_AND_ONLY_ONE) {
                   1116:                                /* check if we have an itemNode that has an
                   1117:                                 * Node or a list */
                   1118:                                if (itemNode->type == AXL_ELEMENT_NODE) {
                   1119:                                        /* we have an item node */
                   1120:                                        count++;
                   1121:                                        if (list->type == CHOICE) {
                   1122:                                                /* because we have a
                   1123:                                                 * choice list, once
                   1124:                                                 * validated one item,
                   1125:                                                 * it is the minimum
                   1126:                                                 * requirement. */
                   1127:                                                return count;
                   1128:                                        }
                   1129:                                } else {
                   1130:                                        /* we have a list */
                   1131:                                        count += __axl_dtd_parse_element_get_compulsory_num (itemNode->data);
                   1132:                                }
                   1133:                        }
                   1134:                        
                   1135:                        /* update the index */
                   1136:                        iterator++;
                   1137:                }
                   1138:        }
                   1139:                
                   1140:        /* return current count */
                   1141:        return count;
                   1142: }
                   1143: 
                   1144: 
                   1145: /** 
                   1146:  * @internal
                   1147:  *
                   1148:  * Parses a document type element that it is expected to be found at
                   1149:  * the given stream.
                   1150:  * 
                   1151:  * @param dtd The axlDtd where the element type readed must be added.
                   1152:  *
                   1153:  * @param stream The stream where the element type if expected to be found.
                   1154:  *
                   1155:  * @param error An axlError, optional, reference where error will be
                   1156:  * reported.
                   1157:  * 
                   1158:  * @return axl_true if the element was parsed properly, axl_false if
                   1159:  * not. The stream associated will be unrefered and the axlError
                   1160:  * provided will be filled if an error is found.
                   1161:  */
                   1162: axl_bool     __axl_dtd_parse_element (axlDtd * dtd, axlStream * stream, axlError ** error)
                   1163: {
                   1164:        char              * string_aux;
                   1165:        int                 matched_chunk = -1;
                   1166:        axlDtdElement     * element;
                   1167: 
                   1168:        /* init the dtd element list */
                   1169:        if (dtd->elements == NULL)
                   1170:                dtd->elements = axl_list_new (axl_list_always_return_1, (axlDestroyFunc) axl_dtd_element_free);
                   1171: 
                   1172:        /* consume previous white spaces */
                   1173:        AXL_CONSUME_SPACES (stream);
                   1174: 
                   1175:        /* get for the first element declaration */
                   1176:        if (! (axl_stream_inspect (stream, "<!ELEMENT", 9) > 0)) {
                   1177:                axl_error_new (-1, "Expected to receive a <!ELEMENT, but it wasn't found", stream, error);
                   1178:                axl_stream_free (stream);
                   1179:                return axl_false;
                   1180:        }
                   1181: 
                   1182:        /* consume previous white spaces */
                   1183:        AXL_CONSUME_SPACES (stream);
                   1184:        
                   1185:        /* get the element name */
                   1186:        string_aux = axl_stream_get_until (stream, NULL, &matched_chunk, axl_false, 3, ">", "(", " ", "<!ELEMENT");
                   1187:        if (string_aux == NULL) {
                   1188:                axl_error_new (-1, "Expected to receive a DTD element name for <!ELEMENT declaration, but not found", stream, error);
                   1189:                axl_stream_free (stream);
                   1190:                return axl_false;
                   1191:        }
                   1192: 
                   1193:        /* check that the DTD have an element name and an element type */
                   1194:        if ((matched_chunk == 0) || (matched_chunk == 3)) {
                   1195:                axl_error_new (-1, "Found a DTD <!ELEMENT declaration, without content specification. Missing value, examples: EMPTY, ANY, (..)", stream, error);
                   1196:                axl_stream_free (stream);
                   1197:                return axl_false;
                   1198:        }
                   1199: 
                   1200:        /* nullify internal stream content */
                   1201:        axl_stream_nullify (stream, LAST_CHUNK);
                   1202:        
                   1203:        /* create the DTD element */
                   1204:        element           = axl_new (axlDtdElement, 1);
                   1205:        element->name     = string_aux;
                   1206: 
                   1207:        /* consume previous white spaces */
                   1208:        AXL_CONSUME_SPACES (stream);
                   1209: 
                   1210:        /* now, check for the basic cases: ANY and EMPTY */
                   1211:        if (axl_stream_peek (stream, "EMPTY", 5) > 0) {
                   1212:                /* accept previous peek */
                   1213:                axl_stream_accept (stream);
                   1214: 
                   1215:                /* found empty declaration */
                   1216:                element->type = ELEMENT_TYPE_EMPTY;
                   1217: 
                   1218:        } else if (axl_stream_peek (stream, "ANY", 3) > 0) {
                   1219:                /* accept previous peek */
                   1220:                axl_stream_accept (stream);
                   1221: 
                   1222:                /* found any declaration */
                   1223:                element->type = ELEMENT_TYPE_ANY;
                   1224:        } else {
                   1225:                /* complex element type declaration, let's roll now
                   1226:                 * get the element content type read current dtd
                   1227:                 * element spec. 
                   1228:                 *
                   1229:                 * By default, any comple element type definition,
                   1230:                 * have childrens, until PC data definition is found,
                   1231:                 * which leads to the two possible values: Mixed and
                   1232:                 * PcData */
                   1233:                element->type = ELEMENT_TYPE_CHILDREN;
                   1234:                if (!__axl_dtd_read_element_spec (stream, element, error))
                   1235:                        return axl_false;
                   1236:        }
                   1237: 
                   1238:        /* add element found */
                   1239:        if (! __axl_dtd_add_element (dtd, element, stream, error))
                   1240:                return axl_false;
                   1241:        
                   1242:        /* consume previous white spaces */
                   1243:        AXL_CONSUME_SPACES (stream);
                   1244: 
                   1245:        /* check for the last DTD declaration */
                   1246:        if (! (axl_stream_inspect (stream, ">", 1))) {
                   1247:                axl_error_new (-1, "Unable to find last, > terminator for the DTD <!ELEMENT declaration", stream, error);
                   1248:                axl_stream_free (stream);
                   1249:                return axl_false;
                   1250:        }
                   1251: 
                   1252:        /* now, count the number of obligatory elements, required for
                   1253:         * the validation process */
                   1254:        element->minimum_match = __axl_dtd_parse_element_get_compulsory_num (element->list);
                   1255: 
                   1256:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found DTD element declaration read complete: minimum matching elements: %d",
                   1257:                   element->minimum_match);
                   1258: 
                   1259:        /* element type declaration completely read */
                   1260:        return axl_true;
                   1261: }
                   1262: 
                   1263: /** 
                   1264:  * @internal
                   1265:  * 
                   1266:  * Destroy the provided reference and its associated data.
                   1267:  * 
                   1268:  * @param decl The reference declaration.
                   1269:  */
                   1270: void axl_dtd_attribute_decl_free (axlDtdAttributeDecl * decl)
                   1271: {
                   1272:        /* free the rule name */
                   1273:        if (decl->name != NULL)
                   1274:                axl_free (decl->name);
                   1275: 
                   1276:        /* free the default value */
                   1277:        if (decl->default_value != NULL)
                   1278:                axl_free (decl->default_value);
                   1279: 
                   1280:        /* free enum declaration list if defined */
                   1281:        if (decl->enumvalues != NULL)
                   1282:                axl_list_free (decl->enumvalues);
                   1283: 
                   1284:        /* free the node itself */
                   1285:        axl_free (decl);
                   1286:        
                   1287:        /* nothing more to do */
                   1288:        return;
                   1289: }
                   1290: 
                   1291: /** 
                   1292:  * @internal function to dealloc an single attribute set decleration.
                   1293:  * 
                   1294:  * @param attribute The reference to dealloc.
                   1295:  */
                   1296: void axl_dtd_attribute_free (axlDtdAttribute * attribute)
                   1297: {
                   1298:        /* free the attribute list, name and the node itself */
                   1299:        axl_free (attribute->name);
                   1300:        axl_list_free (attribute->list);
                   1301:        axl_free (attribute);
                   1302: 
                   1303:        return;
                   1304: }
                   1305: 
                   1306: axl_bool __find_attr_decl (axlPointer _element, axlPointer data)
                   1307: {
                   1308:        axlDtdAttributeDecl * decl = _element;
                   1309:        char                * name = data;
                   1310: 
                   1311:        /* check the name */
                   1312:        if (axl_cmp (decl->name, name))
                   1313:                return axl_true;
                   1314: 
                   1315:        /* it is not the element */
                   1316:        return axl_false;
                   1317: }
                   1318: 
                   1319: /** 
                   1320:  * @brief Allows to check if the stream contains a reference to a
                   1321:  * entity, calling the resolver to get the replacement text to be
                   1322:  * placed.
                   1323:  * 
                   1324:  * @param resolver The function to be called with the replacement
                   1325:  * text. This function must return the replacement text or NULL if it
                   1326:  * fails. Failing to return a reference resolution will make the
                   1327:  * entity reference to appear as is.
                   1328:  *
                   1329:  * @param resolver The entity reference resolver function to be called
                   1330:  * to solve references found.
                   1331:  *
                   1332:  * @param data User defined data provided to the function, passed
                   1333:  * directly to the resolver function once executed.
                   1334:  *
                   1335:  * @param stream The stream where the entity reference could appear.
                   1336:  *
                   1337:  * @param prefix The reference prefix to recognize. Values allowed
                   1338:  * are: % (DTD references) and & (general entity references).
                   1339:  *
                   1340:  * @param error Optional reference to the axlError to report textual
                   1341:  * diagnostic errors.
                   1342:  *
                   1343:  * @return The function return \ref axl_false if some error while
                   1344:  * resolving entity references was found. Otherwise the function
                   1345:  * return axl_true.
                   1346:  */
                   1347: axl_bool axl_dtd_check_entity_ref_and_expand (axlDtdEntityResolver   resolver, 
                   1348:                                              axlPointer             data,
                   1349:                                              axlStream            * stream, 
                   1350:                                              const char           * prefix,
                   1351:                                              axlError            ** error)
                   1352:                                          
                   1353: {
                   1354:        char       * string_aux;
                   1355:        char       * new_value;
                   1356:        int          index;
                   1357: 
                   1358:        /* check if we have an entity reference using the provided prefix */
                   1359:        index = axl_stream_get_index (stream);
                   1360:        if (! (axl_stream_inspect (stream, prefix, 1) > 0))
                   1361:                return axl_true;
                   1362: 
                   1363:        /* get the entity reference until the end */
                   1364:        string_aux = axl_stream_get_until (stream, NULL, NULL, axl_true, 1, ";");
                   1365:        if (string_aux == NULL) {
                   1366:                axl_error_new (-1, "null value received while expecting to find the entity reference to resolve.", stream, error);
                   1367:                axl_stream_free (stream);
                   1368:                return axl_false;
                   1369:        } /* end if */
                   1370: 
                   1371:        axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found entity reference: %s%s;...resolving", prefix, string_aux);
                   1372: 
                   1373:        /* resolve the reference */
                   1374:        new_value = (char *) resolver (string_aux, data);
                   1375:        if (new_value == NULL) {
                   1376:                axl_stream_move (stream, index);
                   1377:                return axl_true;
                   1378:        } /* end if */
                   1379: 
                   1380:        /* accept content consumed */
                   1381:        axl_stream_accept (stream);
                   1382: 
                   1383:        axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "entity resolved to: %s", new_value);
                   1384: 
                   1385:        /* place the replacement data at the start of the stream */
                   1386:        new_value = axl_strdup_printf ("%s ", new_value);
                   1387:        axl_stream_push (stream, new_value, strlen (new_value));
                   1388:        axl_free (new_value);
                   1389:        
                   1390:        return axl_true;
                   1391: }
                   1392: 
                   1393: /** 
                   1394:  * @internal Entity resolver used by __axl_dtd_parse_attlist.
                   1395:  */
                   1396: const char * __axl_dtd_entity_resolver (const char * entityName, axlPointer data)
                   1397: {
                   1398:        /* return the entity resolution */
                   1399:        return axl_dtd_entity_value ((axlDtd *) data, entityName, PARAMETER_ENTITY);
                   1400: } /* end if */
                   1401: 
                   1402: axlList * __axl_dtd_parse_enumvalues (const char * _enum_values)
                   1403: {
                   1404:        char    ** result;
                   1405:        int        iterator;
                   1406:        axlList  * list;
                   1407: 
                   1408:        result   = axl_stream_split (_enum_values, 1, "|");
                   1409:        iterator = 0;
                   1410:        list     = axl_list_new (axl_list_always_return_1, axl_free);
                   1411: 
                   1412:        
                   1413:        while (result[iterator]) {
                   1414:                /* clean the enum value */
                   1415:                axl_stream_trim (result[iterator]);
                   1416: 
                   1417:                /* add to the list */
                   1418:                axl_list_add (list, axl_strdup (result[iterator]));
                   1419: 
                   1420:                /* update the iterator value */
                   1421:                iterator++;
                   1422: 
                   1423:        } /* end while */
                   1424:        
                   1425:        /* free tokens */
                   1426:        axl_stream_freev (result);
                   1427:        
                   1428:        /* return the list */
                   1429:        return list;
                   1430: }
                   1431: 
                   1432: /** 
                   1433:  * @internal function used by \ref axl_dtd_attr_validation function to
                   1434:  * lookup ATTLIST contraints flaged as unique ID.
                   1435:  */
                   1436: axl_bool __find_id_decl (axlPointer _element, axlPointer data)
                   1437: {
                   1438:        /* return the comparision */
                   1439:        return (((axlDtdAttributeDecl *) _element)->type == TOKENIZED_TYPE_ID);
                   1440:        
                   1441: } /* end __find_id_decl */
                   1442: 
                   1443: 
                   1444: /** 
                   1445:  * @internal
                   1446:  * 
                   1447:  * Parse the <!ATTLIST decleration, registering it into the provided
                   1448:  * dtd element.
                   1449:  */
                   1450: axl_bool __axl_dtd_parse_attlist (axlDtd * dtd, axlStream * stream, axlError ** error)
                   1451: {
                   1452:        char                * string_aux    = NULL;
                   1453:        int                   matched_chunk = -1;
                   1454:        axlDtdAttribute     * attribute     = NULL;
                   1455:        axlDtdAttributeDecl * decl          = NULL;
                   1456:        axlDtdAttributeDecl * declAux       = NULL;
                   1457:        char                * err_msg;
                   1458: 
                   1459:        /* init the dtd attr list */
                   1460:        if (dtd->attributes == NULL)
                   1461:                dtd->attributes = axl_list_new (axl_list_always_return_1, (axlDestroyFunc) axl_dtd_attribute_free);
                   1462: 
                   1463:        /* consume previous white spaces */
                   1464:        AXL_CONSUME_SPACES (stream);
                   1465: 
                   1466:        /* get the element name */
                   1467:        string_aux = axl_stream_get_until (stream, NULL, &matched_chunk, axl_false, 1, " ");
                   1468:        if (string_aux == NULL) {
                   1469:                axl_error_new (-1, "Expected to receive a DTD attribute name for <!ATTLIST declaration, but not found", stream, error);
                   1470:                axl_stream_free (stream);
                   1471:                return axl_false;
                   1472:        }
                   1473: 
                   1474:        axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found dtd attr declaration for node: <%s>", string_aux);
                   1475: 
                   1476:        /* find the node that holds all attr declarations for the node found */
                   1477:        attribute         = axl_dtd_get_attr (dtd, string_aux);
                   1478: 
                   1479:        /* check if found */
                   1480:        if (attribute == NULL) {
                   1481:                /* create the axlDtdAttribute holder */
                   1482:                attribute = axl_new (axlDtdAttribute, 1);
                   1483: 
                   1484:                /* record the node to which the list of rules applies */
                   1485:                axl_stream_nullify (stream, LAST_CHUNK);
                   1486:                attribute->name   = string_aux;
                   1487: 
                   1488:                /* init the attribute rule list */
                   1489:                attribute->list   = axl_list_new (axl_list_always_return_1, (axlDestroyFunc) axl_dtd_attribute_decl_free);
                   1490: 
                   1491:                /* now configure this new attribute inside the dtd */
                   1492:                axl_list_add (dtd->attributes, attribute);
                   1493:        } /* end if */
                   1494: 
                   1495:        /* now get the list of attributes */
                   1496:        while (1) {
                   1497:                axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "finding next att declaration");
                   1498: 
                   1499:                /* consume previous white spaces */
                   1500:                AXL_CONSUME_SPACES (stream);
                   1501: 
                   1502:                /* check if we have finished */
                   1503:                if (axl_stream_inspect (stream, ">", 1) > 0)
                   1504:                        break;
                   1505: 
                   1506:                /* get the attribute name the rules applies */
                   1507:                string_aux = axl_stream_get_until (stream, NULL, &matched_chunk, axl_false, 1, " ");
                   1508:                if (string_aux == NULL) {
                   1509:                        axl_error_new (-1, "Expected to receive an attribute name for <!ATTLIST declaration, but not found", stream, error);
                   1510:                        axl_stream_free (stream);
                   1511:                        return axl_false;
                   1512:                }
                   1513: 
                   1514:                /* nully the string and store it new rule created */
                   1515:                axl_stream_nullify (stream, LAST_CHUNK);
                   1516: 
                   1517:                /* create a new attribute single constraint */
                   1518:                decl            = axl_new (axlDtdAttributeDecl, 1);
                   1519:                decl->name      = string_aux;
                   1520: 
                   1521:                /* add the attribute constraint to the list */
                   1522:                axl_list_add (attribute->list, decl);
                   1523: 
                   1524:                axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "find constraint for attribute name=%s", decl->name);
                   1525: 
                   1526:                /* consume previous white spaces */
                   1527:                AXL_CONSUME_SPACES (stream);
                   1528: 
                   1529:                axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "checking constraint type..");
                   1530: 
                   1531:                /* check for an entity reference and expand the stream
                   1532:                 * content with its resolution */
                   1533:                if (! axl_dtd_check_entity_ref_and_expand (__axl_dtd_entity_resolver, dtd, stream, "%", error))
                   1534:                        return axl_false;
                   1535: 
                   1536:                axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "about to check attr constraint type, stream status: '%s'",
                   1537:                         axl_stream_get_following (stream, 30));
                   1538:                
                   1539:                /* now check the contraint type */
                   1540:                if (axl_stream_inspect (stream, "NOTATION", 8) > 0) {
                   1541:                        /* parse notation declaration */
                   1542:                }else if (axl_stream_inspect (stream, "(", 1) > 0) {
                   1543:                        /* parse enum declaration */
                   1544:                        string_aux = axl_stream_get_until (stream, NULL, &matched_chunk, axl_true, 1, ")");
                   1545:                        if (string_aux == NULL) {
                   1546:                                axl_error_new (-1, "expected to find enum declaration but termination caracter ')' was not found", stream, error);
                   1547:                                axl_stream_free (stream);
                   1548:                                return axl_false;
                   1549:                        } /* end if */
                   1550:                        decl->type       = ENUMERATION_TYPE;
                   1551:                        decl->enumvalues = __axl_dtd_parse_enumvalues (string_aux);
                   1552:                }else {
                   1553:                        /* set the attribute type */
                   1554:                        if (axl_stream_inspect (stream, "CDATA", 5) > 0) {
                   1555:                                decl->type = CDATA_ATTRIBUTE;
                   1556:                        } else if (axl_stream_inspect (stream, "IDREFS", 6) > 0) {
                   1557:                                
                   1558:                                /* flag the type */
                   1559:                                decl->type = TOKENIZED_TYPE_IDREFS;
                   1560: 
                   1561:                                /* flag the dtd to have a IDREF declaration */
                   1562:                                dtd->haveIdRefDecl = axl_true;
                   1563:                        } else if (axl_stream_inspect (stream, "IDREF", 5) > 0) {
                   1564:                                /* notify type found */
                   1565:                                decl->type = TOKENIZED_TYPE_IDREF;
                   1566: 
                   1567:                                /* flag the dtd to have a IDREF declaration */
                   1568:                                dtd->haveIdRefDecl = axl_true;
                   1569:                                
                   1570:                        } else if (axl_stream_inspect (stream, "ID", 2) > 0) {
                   1571:                                
                   1572:                                /* notify the type found */
                   1573:                                decl->type      = TOKENIZED_TYPE_ID;
                   1574: 
                   1575:                                /* flag the dtd to have a ID declaration */
                   1576:                                dtd->haveIdDecl = axl_true;
                   1577:                                
                   1578:                        } else if (axl_stream_inspect (stream, "ENTITY", 6) > 0)
                   1579:                                decl->type = TOKENIZED_TYPE_ENTITY;
                   1580:                        else if (axl_stream_inspect (stream, "ENTITIES", 8) > 0)
                   1581:                                decl->type = TOKENIZED_TYPE_ENTITIES;
                   1582:                        else if (axl_stream_inspect (stream, "NMTOKENS", 8) > 0)
                   1583:                                decl->type = TOKENIZED_TYPE_NMTOKENS;
                   1584:                        else if (axl_stream_inspect (stream, "NMTOKEN", 7) > 0)
                   1585:                                decl->type = TOKENIZED_TYPE_NMTOKEN;
                   1586:                        else {
                   1587:                                axl_error_new (-1, "Unrecognied attr type declaration found, check your <!ATTLIST declaration", stream, error);
                   1588:                                axl_stream_free (stream);
                   1589:                                return axl_false;
                   1590:                        } /* end if */
                   1591:                } /* end if */
                   1592: 
                   1593:                /* consume previous white spaces */
                   1594:                AXL_CONSUME_SPACES (stream);
                   1595: 
                   1596:                axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "checking default value declaration, stream status: '%s'",
                   1597:                         axl_stream_get_following (stream, 30));
                   1598: 
                   1599:                /* get default declaration value */
                   1600:                if (axl_stream_inspect (stream, "#REQUIRED", 9) > 0) {
                   1601:                        decl->defaults = ATT_REQUIRED;
                   1602:                } else if (axl_stream_inspect (stream, "#IMPLIED", 8) > 0) {
                   1603:                        decl->defaults = ATT_IMPLIED;
                   1604:                } else {
                   1605:                        decl->defaults = ATT_IMPLIED;
                   1606:                        if (axl_stream_inspect (stream, "#FIXED", 6) > 0) {
                   1607:                                decl->defaults = ATT_FIXED;
                   1608: 
                   1609:                                /* consume previous white spaces */
                   1610:                                AXL_CONSUME_SPACES (stream);
                   1611:                        }
                   1612: 
                   1613:                        /* check default value for this case */
                   1614:                        if (! (axl_stream_peek (stream, "\"", 1) > 0 ||
                   1615:                               axl_stream_peek (stream, "'", 1) > 0)) {
                   1616:                                err_msg = axl_strdup_printf ("Unable to find default attribute declaration (#REQUIRED, #IMPLIED, #FIXED)  for attribute %s, node <%s>",
                   1617:                                                             decl->name, attribute->name);
                   1618:                                axl_error_new (-1, err_msg, stream, error);
                   1619:                                axl_stream_free (stream);
                   1620:                                axl_free (err_msg);
                   1621:                                return axl_false;
                   1622:                        } /* end if */
                   1623:                } /* end if */
                   1624: 
                   1625:                /* check constraint for ID types */
                   1626:                if (decl->type == TOKENIZED_TYPE_ID) {
                   1627:                        /* check that the node doesn't have any unique
                   1628:                         * id declared */
                   1629: 
                   1630:                        /* check if the node have TOKENIZED_TYPE_ID */
                   1631:                        declAux = axl_list_lookup (attribute->list, __find_id_decl, NULL);
                   1632:                        if (declAux != NULL && !axl_cmp (declAux->name, decl->name)) {
                   1633:                                err_msg = axl_strdup_printf ("Found ATTLIST declaration, with several ID declarations <ATTLIST %s %s..",
                   1634:                                                             attribute->name, decl->name);
                   1635:                                axl_error_new (-1, err_msg, stream, error);
                   1636:                                axl_stream_free (stream);
                   1637:                                axl_free (err_msg);
                   1638:                                return axl_false;
                   1639:                        } /* end if */
                   1640:                        
                   1641:                        /* check required and implied */
                   1642:                        if (decl->defaults != ATT_REQUIRED && decl->defaults != ATT_IMPLIED) {
                   1643:                                err_msg = axl_strdup_printf ("Found ATTLIST declaration, with ID, that don't have configured either #IMPLICIT or #REQUIRED for attribute %s, node <%s>",
                   1644:                                                             decl->name, attribute->name);
                   1645:                                axl_error_new (-1, err_msg, stream, error);
                   1646:                                axl_stream_free (stream);
                   1647:                                axl_free (err_msg);
                   1648:                                return axl_false;
                   1649:                        } /* end if */
                   1650:                } /* end if */
                   1651: 
                   1652:                /* consume previous white spaces */
                   1653:                AXL_CONSUME_SPACES (stream);
                   1654: 
                   1655:                /* nullify to check this value later */
                   1656:                string_aux = NULL;
                   1657:                if (axl_stream_inspect (stream, "\"", 1) > 0) {
                   1658:                        /* get until */
                   1659:                        string_aux = axl_stream_get_until (stream, NULL, NULL, axl_true, 1, "\"");
                   1660:                } else if (axl_stream_inspect (stream, "'", 1) > 0) {
                   1661:                        /* get until */
                   1662:                        string_aux = axl_stream_get_until (stream, NULL, NULL, axl_true, 1, "\'");
                   1663:                } /* end if */
                   1664: 
                   1665:                /* check if default value was found */
                   1666:                if (string_aux != NULL) {
                   1667: 
                   1668:                        /* found default value, check if we have an
                   1669:                         * enumeration type, enforcing that the value
                   1670:                         * defined to be inside the enumeration */
                   1671:                        if (decl->type == ENUMERATION_TYPE) {
                   1672:                                if (axl_list_lookup (decl->enumvalues, axl_list_find_string, string_aux) == NULL) {
                   1673:                                        axl_error_new (-1, 
                   1674:                                                       "Configured a default value for an attribute list which only accepts a set of enum values that do not containt it.",
                   1675:                                                       stream, error);
                   1676:                                        axl_stream_free (stream);
                   1677:                                        return axl_false;
                   1678:                                } /* end if */
                   1679:                        } /* end if */
                   1680: 
                   1681:                        /* nullify value and make string_aux to be
                   1682:                         * owned by the axlDtdAttributeDecl
                   1683:                         * reference */
                   1684:                        axl_stream_nullify (stream, LAST_CHUNK);
                   1685:                        decl->default_value = string_aux;
                   1686:                } /* end if */
                   1687: 
                   1688:        } /* end while */
                   1689:                
                   1690:        /* properly parsed */
                   1691:        return axl_true;
                   1692: }
                   1693: 
                   1694: /** 
                   1695:  * @internal
                   1696:  * 
                   1697:  * Destroy the provided entity reference and all allocated memory.
                   1698:  * 
                   1699:  * @param entity The entity the deallocate.
                   1700:  */
                   1701: void axl_dtd_entity_free (axlDtdEntity * entity)
                   1702: {
                   1703:        /* the entity reference */
                   1704:        axl_return_if_fail (entity);
                   1705: 
                   1706:        /* free the entity name */
                   1707:        if (entity->name)
                   1708:                axl_free (entity->name);
                   1709:        
                   1710:        /* free the content */
                   1711:        if (entity->content)
                   1712:                axl_free (entity->content);
                   1713: 
                   1714:        /* free external data if defined */
                   1715:        if (entity->data) {
                   1716:                /* free system literal */
                   1717:                if (entity->data->system_literal)
                   1718:                        axl_free (entity->data->system_literal);
                   1719:                
                   1720:                /* free public literal */
                   1721:                if (entity->data->public_literal)
                   1722:                        axl_free (entity->data->public_literal);
                   1723: 
                   1724:                /* free ndata literal */
                   1725:                if (entity->data->ndata)
                   1726:                        axl_free (entity->data->ndata);
                   1727: 
                   1728:                /* free the node itself */
                   1729:                axl_free (entity->data);
                   1730:        }
                   1731: 
                   1732:        /* free the node */
                   1733:        axl_free (entity);
                   1734: 
                   1735:        return;
                   1736: }
                   1737: 
                   1738: /** 
                   1739:  * @internal
                   1740:  *
                   1741:  * Parses an entity definition from the current status of the stream
                   1742:  * provided.
                   1743:  */
                   1744: axl_bool __axl_dtd_parse_entity (axlDtd * dtd, axlStream * stream, axlError ** error)
                   1745: {
                   1746:        char         * string_aux;
                   1747:        int            matched_chunk;
                   1748:        axlDtdEntity * entity;
                   1749: 
                   1750:        /* init the dtd element list */
                   1751:        if (dtd->entities == NULL)
                   1752:                dtd->entities = axl_list_new (axl_list_always_return_1, (axlDestroyFunc) axl_dtd_entity_free);
                   1753:        
                   1754:        /* consume previous white spaces */
                   1755:        AXL_CONSUME_SPACES (stream);
                   1756: 
                   1757:        /* get for the first element declaration */
                   1758:        if (! (axl_stream_inspect (stream, "<!ENTITY", 8) > 0)) {
                   1759:                axl_error_new (-1, "Expected to receive a <!ENTITY, but it wasn't found", stream, error);
                   1760:                axl_stream_free (stream);
                   1761:                return axl_false;
                   1762:        }
                   1763: 
                   1764:        /* consume previous white spaces */
                   1765:        AXL_CONSUME_SPACES (stream);
                   1766: 
                   1767:        /* create a new entity */
                   1768:        entity = axl_new (axlDtdEntity, 1);
                   1769: 
                   1770:        /* set the entity and return axl_true */
                   1771:        axl_list_add (dtd->entities, entity);
                   1772: 
                   1773:        /* check for parameter entity definition */
                   1774:        if (axl_stream_inspect (stream, "%", 1) > 0) {
                   1775:                /* set the entity type */
                   1776:                entity->type = PARAMETER_ENTITY;
                   1777:                
                   1778:                /* consume previous white spaces */
                   1779:                AXL_CONSUME_SPACES (stream);
                   1780: 
                   1781:        } else
                   1782:                entity->type = GENERAL_ENTITY;
                   1783: 
                   1784:        /* get the element name */
                   1785:        string_aux = axl_stream_get_until (stream, NULL, &matched_chunk, axl_false, 1, " ");
                   1786:        if (string_aux == NULL) {
                   1787:                axl_error_new (-1, "Expected to receive a DTD entity name for <!ENTITY declaration, but not found", stream, error);
                   1788:                axl_stream_free (stream);
                   1789:                return axl_false;
                   1790:        }
                   1791: 
                   1792:        /* set the name */
                   1793:        axl_stream_nullify (stream, LAST_CHUNK);
                   1794:        entity->name = string_aux;
                   1795: 
                   1796:        /* consume previous white spaces */
                   1797:        AXL_CONSUME_SPACES (stream);
                   1798: 
                   1799:        /* now check if we have an external reference */
                   1800:        if (axl_stream_inspect (stream, "PUBLIC", 6) > 0) {
                   1801:                /* we have a public external resource definition */
                   1802:                
                   1803:        }else if (axl_stream_inspect (stream, "SYSTEM", 6) > 0) {
                   1804:                /* we have a system definition */
                   1805:                
                   1806:        }else {
                   1807:                /* we have a plain value get the content remove next "
                   1808:                   and ' if defined */
                   1809:                if (! ((axl_stream_inspect (stream, "\"", 1) > 0))) {
                   1810:                        if (! (axl_stream_inspect (stream, "\'", 1) > 0)) {
                   1811:                                axl_error_new (-2, "Expected to find entity value initiator (\") or ('), every entity value must start with them", 
                   1812:                                               stream, error);
                   1813:                                axl_stream_free (stream);
                   1814:                                return axl_false;
                   1815:                        }
                   1816:                        /* knowing that ' was matched, now get the attribute value */
                   1817:                        string_aux = axl_stream_get_until (stream, NULL, &matched_chunk, axl_true, 1, "'");
                   1818:                }else {
                   1819:                        /* knowhing that " was matched, now get the attribute value */
                   1820:                        string_aux = axl_stream_get_until (stream, NULL, &matched_chunk, axl_true, 1, "\"");
                   1821:                }
                   1822: 
                   1823:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "entity value found: [%s]", string_aux);
                   1824:                
                   1825:                /* nullify internal reference so we have the
                   1826:                 * only one reference to entity content value
                   1827:                 * inside string_aux */
                   1828:                axl_stream_nullify (stream, LAST_CHUNK);
                   1829: 
                   1830:                /* set the value */
                   1831:                entity->content = string_aux;
                   1832:        }
                   1833: 
                   1834:        /* consume previous white spaces */
                   1835:        AXL_CONSUME_SPACES (stream);
                   1836: 
                   1837:        /* check last item to parse */
                   1838:        if (! (axl_stream_inspect (stream, ">", 1) > 0)) {
                   1839:                axl_error_new (-2, "Expected to find entity definition terminator (>), but it wasn't found", 
                   1840:                               stream, error);
                   1841:                axl_stream_free (stream);
                   1842:                return axl_false;
                   1843:        }
                   1844: 
                   1845:        return axl_true;
                   1846: }
                   1847: 
                   1848: 
                   1849: /** 
                   1850:  * @internal
                   1851:  * 
                   1852:  * Implements DTD parsing, reading it from a direct buffer, or a file
                   1853:  * path or a file handle.
                   1854:  */
                   1855: axlDtd * __axl_dtd_parse_common (const char * entity, int entity_size, 
                   1856:                                 const char * file_path, int fd_handle, 
                   1857:                                 axlError ** error)
                   1858: {
                   1859:        axlStream * stream;
                   1860:        axlDtd    * dtd;
                   1861:        int         iterator;
                   1862:        
                   1863:        /* create the stream associated */
                   1864:        stream = axl_stream_new (entity, entity_size, file_path, fd_handle, error);
                   1865:        axl_return_val_if_fail (stream, NULL);
                   1866: 
                   1867:        dtd    = __axl_dtd_new ();
                   1868:        axl_stream_link (stream, dtd, (axlDestroyFunc) axl_dtd_free);
                   1869: 
                   1870:        iterator = 0;
                   1871:        while (axl_stream_remains (stream)) {
                   1872:                /* get rid from comments found */
                   1873:                if (! axl_doc_consume_comments (NULL, stream, error))
                   1874:                        return NULL;
                   1875:                
                   1876:                /* check for element declaration */
                   1877:                if (axl_stream_peek (stream, "<!ELEMENT", 9) > 0) {
                   1878:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found DTD element declaration");
                   1879:                        /* found element declaration */
                   1880:                        if (! __axl_dtd_parse_element (dtd, stream, error))
                   1881:                                return NULL;
                   1882:                        
                   1883:                        continue;
                   1884: 
                   1885:                }
                   1886: 
                   1887:                /* check for attribute list declarations */
                   1888:                if (axl_stream_inspect (stream, "<!ATTLIST", 9) > 0) {
                   1889:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found DTD attribute list declaration");
                   1890: 
                   1891:                        /* parse it */
                   1892:                        if (! __axl_dtd_parse_attlist (dtd, stream, error))
                   1893:                                return NULL;
                   1894:                        
                   1895:                        continue;
                   1896:                }
                   1897: 
                   1898:                /* check for the entity declaration */
                   1899:                if (axl_stream_peek (stream, "<!ENTITY", 8) > 0) {
                   1900:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found DTD entity declaration");
                   1901: 
                   1902:                        /* parse the entity definition */
                   1903:                        if (! __axl_dtd_parse_entity (dtd, stream, error))
                   1904:                                return NULL;
                   1905: 
                   1906:                        continue;
                   1907:                }
                   1908: 
                   1909:                /* stop the loop */
                   1910:                if (iterator == 3) {
                   1911:                        axl_error_new (-1, "unable to process DTD content, unable to find expected information (no <!ELEMENT, <!ATTLIST or <!ENTITY declaration)", stream, error);
                   1912:                        axl_stream_free (stream);
                   1913:                        return NULL;
                   1914:                }
                   1915:                iterator++;
                   1916:        }
                   1917: 
                   1918: 
                   1919:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "DTD elements totally loaded, building references..");
                   1920: 
                   1921:        /* update current root reference, the DTD root for the DTD
                   1922:         * document already parsed */
                   1923:        if (dtd->elements != NULL) 
                   1924:                dtd->root = __axl_dtd_get_new_root (dtd);
                   1925: 
                   1926:        /* check if the DTD has ID declarations if found IDREF
                   1927:         * declarations */
                   1928:        if (! dtd->haveIdDecl && dtd->haveIdRefDecl) {
                   1929:                axl_error_new (-1, "DTD semantic error, found IDREF attribute declaration but no attribute ID declaration was found.", stream, error);
                   1930:                axl_stream_free (stream);
                   1931:                return NULL;
                   1932:        }
                   1933:        
                   1934:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "DTD load COMPLETE");
                   1935: 
                   1936:        axl_stream_unlink (stream);
                   1937:        axl_stream_free (stream);
                   1938:        return dtd;
                   1939: }
                   1940: 
                   1941: /** 
                   1942:  * @brief Allows to parse the provided entity, which is expected to
                   1943:  * contain a DTD (Document Type Definition).
                   1944:  * 
                   1945:  * @param entity The document type definition to parse.
                   1946:  *
                   1947:  * @param entity_size The document size, or -1 to make the function to
                   1948:  * figure out current size.
                   1949:  *
                   1950:  * @param error An optional \ref axlError where errors will be reported.
                   1951:  * 
                   1952:  * @return A newly allocated \ref axlDtd that must be deallocated when
                   1953:  * no longer need with \ref axl_dtd_free. The function could return
                   1954:  * NULL on failure detected. On that case, it is requred to check \ref
                   1955:  * axlError variable, if defined.
                   1956:  */
                   1957: axlDtd   * axl_dtd_parse (const char * entity, 
                   1958:                          int          entity_size,
                   1959:                          axlError ** error)
                   1960: {
                   1961: 
                   1962:        return __axl_dtd_parse_common (entity, entity_size, NULL, -1, error);
                   1963: }
                   1964: 
                   1965: /** 
                   1966:  * @brief Allows to parse the provided DTD definition, which is found
                   1967:  * on the provided file path.
                   1968:  * 
                   1969:  * @param file_path The file path where it is expected to receive a
                   1970:  * DTD file.
                   1971:  *
                   1972:  * @param error An optional \ref axlError reference where all errors found will be reported.
                   1973:  * 
                   1974:  * @return A newly allocated \ref axlDtd instance or NULL if it fails.
                   1975:  *
                   1976:  * <b>Making a DTD to be inline loaded: </b><br>
                   1977:  * 
                   1978:  * It may be helpful to make the DTD definition available at your
                   1979:  * binary, inline compiled, to avoid distributing DTD files along with
                   1980:  * libraries, etc. This also solves installation problems like
                   1981:  * provisioning a default location to make your application to find
                   1982:  * such files.
                   1983:  *
                   1984:  * With the following command you can create an inline representation
                   1985:  * from your DTD file:
                   1986:  * \code
                   1987:  * >> axl-knife --input your-file.dtd --dtd-to-c --output your-file.dtd.h --ifnewer
                   1988:  * \endcode
                   1989:  *
                   1990:  * This will create a header with an C-macro style definition of your
                   1991:  * DTD. Now, you can include it using:
                   1992:  *
                   1993:  * \code
                   1994:  * #include <your-file.dtd.h>
                   1995:  * \endcode
                   1996:  *
                   1997:  * In the case you are developing a library, it is recommended to do
                   1998:  * such include at the body implementation (usually .c or .cpp files,
                   1999:  * to avoid requiring your API consumers to also include your DTD
                   2000:  * inline definition). 
                   2001:  *
                   2002:  * Now, to load your DTD file, use the following:
                   2003:  *
                   2004:  * \code
                   2005:  * axlError * err = NULL;
                   2006:  * axlDtd   * dtd = axl_dtd_parse (YOUR_FILE_DTD, -1, &err);
                   2007:  * if (dtd == NULL) {
                   2008:  *    // This won't happen unless axl-runtime error found, since axl-knife 
                   2009:  *    // checks your dtd file before producing the in-line definition.
                   2010:  *    // However, bug happens! check this.
                   2011:  * }
                   2012:  * \endcode
                   2013:  */
                   2014: axlDtd   * axl_dtd_parse_from_file (const char * file_path,
                   2015:                                    axlError ** error)
                   2016: {
                   2017:        return __axl_dtd_parse_common (NULL, -1, file_path, -1, error);
                   2018: }
                   2019: 
                   2020: 
                   2021: /** 
                   2022:  * @internal
                   2023:  * 
                   2024:  * Support function for axl_dtd_validate which checks if the provided
                   2025:  * parent have its childs configuration according to the values
                   2026:  * expresed on the sequenced represented by the itemList.
                   2027:  *
                   2028:  * The function return axl_true if the validation was ok, or axl_false
                   2029:  * if something have failed. It also creates an error, using the
                   2030:  * optional axlError reference received.
                   2031:  */
                   2032: axl_bool     __axl_dtd_validate_sequence (axlNode            * parent, 
                   2033:                                          int                * child_position,
                   2034:                                          axlDtdElementList  * itemList, 
                   2035:                                          axlError          ** error,
                   2036:                                          axl_bool             try_match,
                   2037:                                          axl_bool             top_level)
                   2038: {
                   2039:        int                      iterator        = 0;
                   2040:        int                      child_pos       = *child_position;
                   2041:        axlNode                * node;
                   2042:        axlDtdElementListNode  * itemNode;
                   2043:        axl_bool                 status          = axl_false;
                   2044:        axl_bool                 one_matched;
                   2045:        AxlDtdTimes              times;
                   2046:        
                   2047: 
                   2048:        axl_return_val_if_fail (parent, axl_false);
                   2049:        axl_return_val_if_fail (itemList, axl_false);
                   2050: 
                   2051: 
                   2052:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "validating a sequence list: iterator=%d, item list count=%d, at child position=%d",
                   2053:                 iterator, axl_dtd_item_list_count (itemList), child_pos);
                   2054: 
                   2055:        /* iterate over the sequence, checking its order */
                   2056:        while (iterator < axl_dtd_item_list_count (itemList)) {
                   2057:                
                   2058:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "getting next item node from the DTD item list at: %d",
                   2059:                         iterator);
                   2060:                
                   2061:                /* get the item node specification */
                   2062:                itemNode    = axl_dtd_item_list_get_node (itemList, iterator);
                   2063:                one_matched = axl_false;
                   2064:                times       = axl_dtd_item_node_get_repeat (itemNode);
                   2065: 
                   2066:                do {
                   2067: 
                   2068:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "getting node at child position: %d",
                   2069:                                   child_pos);
                   2070: 
                   2071:                        /* get the node that is located at the same position
                   2072:                         * than the sequence */
                   2073:                        if (child_pos < axl_node_get_child_num (parent)) {
                   2074:                                node     = axl_node_get_child_nth (parent, child_pos);
                   2075:                        } else
                   2076:                                node     = NULL;
                   2077: 
                   2078:                        /* the node child list have ended, check if
                   2079:                         * this situation was expected */
                   2080:                        if (node == NULL) {
                   2081:                                __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",
                   2082:                                           child_pos, axl_node_get_name (parent), times,
                   2083:                                           iterator, axl_dtd_item_list_count (itemList));
                   2084:                                /* check if we were working with a
                   2085:                                 * list, which have matched at least
                   2086:                                 * one item */
                   2087:                                if (times == ONE_OR_MANY && one_matched && status) {
                   2088:                                        if ((iterator + 1) == axl_dtd_item_list_count (itemList)) {
                   2089:                                                *child_position = child_pos;
                   2090:                                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "sequence validated with child position (III): %d", child_pos);
                   2091:                                                return axl_true;
                   2092:                                        } 
                   2093: 
                   2094:                                        /* reached this point we have
                   2095:                                           matched a one to many with
                   2096:                                           at least one match */
                   2097:                                        break;
                   2098:                                }
                   2099:                                
                   2100:                                /* check that the rest of the
                   2101:                                 * specification item is optional,
                   2102:                                 * including the one used */
                   2103:                                status = axl_true;
                   2104:                                do {
                   2105:                                        if (times != ZERO_OR_MANY &&
                   2106:                                            times != ZERO_OR_ONE) {
                   2107: 
                   2108:                                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found item, inside the DTD item list, that is not optional: %d (repeat value: %d)", 
                   2109:                                                           iterator, times);
                   2110:                                                status = axl_false;
                   2111:                                                break;
                   2112:                                        }
                   2113: 
                   2114:                                        /* update index and get the next item */
                   2115:                                        iterator++;
                   2116:                                        if (iterator < axl_dtd_item_list_count (itemList))
                   2117:                                                itemNode = axl_dtd_item_list_get_node (itemList, iterator);
                   2118:                                }while (status && (iterator < axl_dtd_item_list_count (itemList)));
                   2119: 
                   2120:                                /* check status before checking the rest of the item spec */
                   2121:                                if (status) {
                   2122:                                        *child_position = child_pos;
                   2123: 
                   2124:                                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "sequence validated with child position (II): %d", child_pos);
                   2125: 
                   2126:                                        return axl_true;
                   2127:                                }
                   2128:                                
                   2129:                                /* check if a try match is being runned */
                   2130:                                if (! try_match) {
                   2131:                                        axl_error_report (error, -1 , 
                   2132:                                                       "Found that DTD specifies more nodes to be hold by the parent (<%s>), but no more childs were found",
                   2133:                                                       axl_node_get_name (parent));
                   2134:                                }
                   2135: 
                   2136:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found that no nodes left to satisfy DTD validation operation");
                   2137:                                *child_position = child_pos;
                   2138:                                return axl_false;
                   2139:                        }
                   2140: 
                   2141:                        /* check node type */
                   2142:                        if (axl_dtd_item_node_get_type (itemNode) == AXL_ELEMENT_LIST) {
                   2143: 
                   2144:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "the item node is an item list, dtd item list position: %d, child position: %d=<%s>",
                   2145:                                         iterator, child_pos, axl_node_get_name (node));
                   2146: 
                   2147:                                /* element list found, validate its content */
                   2148:                                if (! __axl_dtd_validate_item_list (axl_dtd_item_node_get_list (itemNode),
                   2149:                                                                    parent, &child_pos, error, axl_false)) {
                   2150:                                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "sub item list validation have failed (not critical)");
                   2151:                                        /* check if we are the top
                   2152:                                         * level list and the itemNode
                   2153:                                         * checked is the last one
                   2154:                                         * item on the item list */
                   2155:                                        if (top_level && ((iterator + 1) == axl_node_get_child_num (parent))) {
                   2156:                                                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "found that the last item list wasn't matched");
                   2157:                                                
                   2158:                                        }
                   2159: 
                   2160:                                        *child_position = child_pos;
                   2161:                                        return axl_false;
                   2162:                                }
                   2163: 
                   2164:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "validated item list, child position after: %d",
                   2165:                                           child_pos);
                   2166:                                /* because child position updating and
                   2167:                                 * repeat matching is already handled
                   2168:                                 * by dtd_validate_item_list function
                   2169:                                 * we just continue with the next
                   2170:                                 * iteration */
                   2171:                                break;
                   2172: 
                   2173:                        } else if (axl_dtd_item_node_get_type (itemNode) == AXL_ELEMENT_NODE) {
                   2174:                                /* check the name against the spec */
                   2175: 
                   2176:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, 
                   2177:                                           "the item node is a final content particule definition: %s",
                   2178:                                           axl_dtd_item_node_get_value (itemNode));
                   2179: 
                   2180:                                status = NODE_CMP_NAME (node, axl_dtd_item_node_get_value (itemNode));
                   2181:                        }
                   2182: 
                   2183:                        /* check previous status */
                   2184:                        if ((times == ONE_AND_ONLY_ONE) || 
                   2185:                            (times == ONE_OR_MANY && one_matched == axl_false)) {
                   2186:                                if (! status) {
                   2187:                                        /* only report an upper level
                   2188:                                         * error if we are not running
                   2189:                                         * a try match */
                   2190:                                        if (! try_match) {
                   2191: 
                   2192:                                                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, 
                   2193:                                                           "Found different node (<%s>) for a sequence expected (<%s>), at child position: %d, item list pos: %d",
                   2194:                                                           axl_node_get_name (node), 
                   2195:                                                           axl_dtd_item_node_get_value (itemNode),
                   2196:                                                           child_pos, iterator);
                   2197:                                                axl_error_report (error, -1, 
                   2198:                                                                  "Found different node (<%s>) for a sequence expected (<%s>), at child position: %d, item list pos: %d",
                   2199:                                                                  axl_node_get_name (node), 
                   2200:                                                                  axl_dtd_item_node_get_value (itemNode),
                   2201:                                                                  child_pos, iterator);
                   2202:                                        }
                   2203:                                        /* return that a match wasn't possible */
                   2204:                                        *child_position = child_pos;
                   2205:                                        return axl_false;                       
                   2206:                                }
                   2207:                        }
                   2208: 
                   2209:                        /* according to the repetition pattern, update loop indexes */
                   2210:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "updating child nodes references: %d, repeat type: %d, status=%d",
                   2211:                                   child_pos, times, status);
                   2212: 
                   2213: 
                   2214:                        /* one only item to match and exactly one */
                   2215:                        if (times == ONE_AND_ONLY_ONE) {
                   2216:                                child_pos++;
                   2217:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "updated child position to: %d, repeat type: %d, status=%d",
                   2218:                                           child_pos, times, status);
                   2219:                                break;
                   2220:                        }
                   2221: 
                   2222:                        /* one or many items to match */
                   2223:                        if (times == ONE_OR_MANY) { 
                   2224: 
                   2225:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "matched one to many item node: status=%d one_matched=%d",
                   2226:                                           status, one_matched);
                   2227: 
                   2228:                                /* if the match have failed and
                   2229:                                 * previous matches was ok, it seems
                   2230:                                 * we have reached the next
                   2231:                                 * items. Just break the loop */
                   2232:                                if (status == axl_false && one_matched == axl_true) 
                   2233:                                        break;
                   2234: 
                   2235:                                child_pos++;
                   2236:                                one_matched = axl_true;
                   2237:                                continue; /* don't break the loop */
                   2238:                        }
                   2239: 
                   2240:                        /* zero or optionally one item to match */                      
                   2241:                        if (times == ZERO_OR_ONE) {
                   2242:                                /* if previous status was ok, it seems
                   2243:                                 * that we have matched the optional
                   2244:                                 * character. In that case, move the
                   2245:                                 * index to the following value. If
                   2246:                                 * not, just break the loop. */
                   2247:                                if (status == axl_true)
                   2248:                                        child_pos++;
                   2249:                                break;
                   2250:                        }
                   2251: 
                   2252:                        /* zero or many items to match */
                   2253:                        if (times == ZERO_OR_MANY) {
                   2254:                                if (status == axl_true) {
                   2255:                                        one_matched = axl_true;
                   2256:                                        child_pos++;
                   2257:                                        continue;
                   2258:                                }
                   2259:                                break;
                   2260:                        }
                   2261: 
                   2262: 
                   2263:                        /* until break the loop */
                   2264:                }while (axl_true);
                   2265: 
                   2266:                /* update iterator index */
                   2267:                iterator++;
                   2268:        }
                   2269: 
                   2270:        /* check if more nodes where specified than the DTD spec */
                   2271:        times = axl_dtd_item_list_repeat (itemList);
                   2272:        if ((times == ONE_OR_MANY || times == ONE_AND_ONLY_ONE) && 
                   2273:            top_level && (child_pos  < axl_node_get_child_num (parent))) {
                   2274: 
                   2275:                /* drop a log */
                   2276:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "parent node <%s> have more childs=%d than the childs iterated=%d, top_level=%d",
                   2277:                           axl_node_get_name (parent),
                   2278:                           axl_node_get_child_num (parent),
                   2279:                           child_pos, top_level);
                   2280: 
                   2281:                /* do not report an error found if a try match is
                   2282:                 * being run */
                   2283:                if (! try_match) {
                   2284:                        axl_error_new (-1, "More childs, than the ones especified in the DTD, were found",
                   2285:                                       NULL, error);
                   2286:                }
                   2287:                /* return that the match wasn't possible */
                   2288:                *child_position = child_pos;
                   2289:                return axl_false;
                   2290:        }
                   2291: 
                   2292:        /* return that the sequence has been validated */
                   2293:        *child_position = child_pos;
                   2294: 
                   2295:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "sequence validated with child position (I): %d", child_pos);
                   2296: 
                   2297:        return axl_true;
                   2298: }
                   2299: 
                   2300: /** 
                   2301:  * @internal
                   2302:  * 
                   2303:  * Internal support function to validate the choice list.
                   2304:  */
                   2305: axl_bool     __axl_dtd_validate_choice (axlNode             * parent, 
                   2306:                                        int                 * child_position, 
                   2307:                                        axlDtdElementList   * itemList, 
                   2308:                                        axlError           ** error,
                   2309:                                        axl_bool              try_match, 
                   2310:                                        axl_bool              top_level)
                   2311: {
                   2312:        axlNode               * node;
                   2313:        axlDtdElementListNode * itemNode;
                   2314:        int                     iterator;
                   2315:        axl_bool                status;
                   2316:        AxlDtdTimes             times;
                   2317:        axl_bool                one_match;
                   2318: 
                   2319:        
                   2320:        if (*child_position < axl_node_get_child_num (parent)) {
                   2321:                /* get a reference to be matched by the choice list */
                   2322:                node = axl_node_get_child_nth (parent, *child_position);
                   2323:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "validated choice list at position: %d=<%s>", *child_position, axl_node_get_name (node));
                   2324:        } else {
                   2325:                /* tried to match a choice list with a child index
                   2326:                 * outside the maximum number of childs */
                   2327:                if (! try_match) {
                   2328:                        axl_error_new (-1, "Unable to match choice list, it seems that the are not enough childs to validate the choice list",
                   2329:                                       NULL, error);
                   2330:                }
                   2331:                return axl_false;
                   2332:        }
                   2333: 
                   2334:        iterator = 0; 
                   2335:        while (iterator < axl_dtd_item_list_count (itemList)) {
                   2336:                /* get the DTD item list to match */
                   2337:                itemNode = axl_dtd_item_list_get_node   (itemList, iterator);
                   2338:                times    = axl_dtd_item_node_get_repeat (itemNode);
                   2339: 
                   2340:                if (axl_dtd_item_node_get_type (itemNode) == AXL_ELEMENT_NODE) {
                   2341:                        /* reset match configuration */
                   2342:                        one_match = axl_false;
                   2343:                repeat_for_node:
                   2344:                        /* a node was found */
                   2345:                        status    = NODE_CMP_NAME (node, axl_dtd_item_node_get_value (itemNode));
                   2346: 
                   2347:                        /* know, if the node was matched check it
                   2348:                         * repetition configuration */
                   2349:                        if (status) {
                   2350:                                /* update child position */
                   2351:                                (*child_position)++;
                   2352: 
                   2353:                                if (times == ONE_AND_ONLY_ONE || times == ZERO_OR_ONE) {
                   2354:                                        /* the node was matched and
                   2355:                                         * the itemNode has a one and
                   2356:                                         * only one configuration,
                   2357:                                         * just return that the choice
                   2358:                                         * list was matched */
                   2359:                                        return axl_true;
                   2360:                                }
                   2361:                                if (times == ONE_OR_MANY || times == ZERO_OR_MANY) {
                   2362:                                        /* because the node was matched, but the repetition
                   2363:                                         * pattern allows to match more nodes we have to
                   2364:                                         * iterate a bit more */
                   2365:                                        node = axl_node_get_child_nth (parent, *child_position);
                   2366:                                        if (node == NULL) {
                   2367:                                                /* because we already matched at least one item, 
                   2368:                                                 * we can assume that the itemNode was successfully 
                   2369:                                                 * matched for both cases (*) and (+). */
                   2370:                                                return axl_true;
                   2371:                                        }
                   2372:                                        /* flag the one match */
                   2373:                                        one_match = axl_true;
                   2374:                                        
                   2375:                                        /* if the node reference is
                   2376:                                         * not NULL, try to match the
                   2377:                                         * next item */
                   2378:                                        goto repeat_for_node;
                   2379:                                }
                   2380:                        } /* end if */
                   2381:                        
                   2382:                        /* before returning, that that we have matched
                   2383:                         * previously, at least, one node for
                   2384:                         * one-to-many and zero-to-many pattern */
                   2385:                        if ((times == ONE_OR_MANY || times == ZERO_OR_MANY) && one_match) {
                   2386:                                return axl_true;
                   2387:                        }
                   2388: 
                   2389:                } else if (axl_dtd_item_node_get_type (itemNode) == AXL_ELEMENT_LIST) {
                   2390:                        /* an element list was found, call to validate it */
                   2391:                        /* element list found, validate its content */
                   2392:                        if (__axl_dtd_validate_item_list (axl_dtd_item_node_get_list (itemNode),
                   2393:                                                          parent, child_position, error, axl_false)) {
                   2394:                                /* item list matched */
                   2395:                                return axl_true;
                   2396:                        }
                   2397:                }
                   2398: 
                   2399:                /* no item was matched, update iterator indexes */
                   2400:                iterator++;
                   2401:        }
                   2402: 
                   2403:        /* seems that the choice list wasn't matched */
                   2404:        if (! try_match) {
                   2405:                axl_error_new (-1, "Unable to match choice list, after checking all posibilities, choice list wasn't validated", 
                   2406:                               NULL, error);
                   2407:        }
                   2408:        return axl_false;
                   2409: }
                   2410: 
                   2411: /** 
                   2412:  * @internal 
                   2413:  *
                   2414:  * Tries to perform a validation, based on the item list received and
                   2415:  * the repetition configuration.
                   2416:  * 
                   2417:  * @param itemList The item list containing DTD content spec
                   2418:  * information used to validate.
                   2419:  *
                   2420:  * @param parent The parent node where the validation process is being
                   2421:  * applied. The content spec refers to the childs the parent has.
                   2422:  *
                   2423:  * @param stack An stack used by the overall process to store the
                   2424:  * subsequent parents to be validated. This stack must be released if
                   2425:  * a error is found.
                   2426:  *
                   2427:  * @param error An optional axlError reference containing the error
                   2428:  * textual diagnostic if found.
                   2429:  * 
                   2430:  * @return axl_true if the validation was ok, otherwise axl_false is
                   2431:  * returned.
                   2432:  */
                   2433: axl_bool     __axl_dtd_validate_item_list (axlDtdElementList  * itemList,
                   2434:                                           axlNode            * parent, 
                   2435:                                           int                * child_position,
                   2436:                                           axlError          ** error,
                   2437:                                           axl_bool             top_level)
                   2438: {
                   2439:        int          temp_child_pos;
                   2440:        axl_bool     status;
                   2441:        axl_bool     already_matched;
                   2442: 
                   2443: 
                   2444:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "validating an item list with repeat pattern: %d, at %d, top level=%d",
                   2445:                   axl_dtd_item_list_repeat (itemList), *child_position, top_level);
                   2446: 
                   2447:        /* now check repetition type */
                   2448:        switch (axl_dtd_item_list_repeat (itemList)) {
                   2449:        case ONE_AND_ONLY_ONE:
                   2450:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a (one and only one) spec..");
                   2451:                if (axl_dtd_item_list_type (itemList) == SEQUENCE) {
                   2452: 
                   2453:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "using a SEQUENCE form");
                   2454:                        /* it is a choice, so the item list specifies
                   2455:                         * the nodes that could appear */
                   2456:                        if (!__axl_dtd_validate_sequence (parent, child_position, itemList, error, 
                   2457:                                                          axl_false, top_level)) {
                   2458:                                return axl_false;
                   2459:                        }
                   2460:                }else {
                   2461:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "using a CHOICE form");
                   2462:                        /* it is a sequence, so, item list
                   2463:                         * specification represents the nodes, in the
                   2464:                         * order they must appear */
                   2465:                        if (!__axl_dtd_validate_choice (parent, child_position, itemList, error,
                   2466:                                                        axl_false, top_level)) {
                   2467:                                return axl_false;
                   2468:                        }
                   2469:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "choice list was properly validated");
                   2470:                }
                   2471:                break;
                   2472:        case ZERO_OR_ONE:
                   2473: 
                   2474:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a (zero or one) spec..");
                   2475:                if (axl_dtd_item_list_type (itemList) == SEQUENCE) {
                   2476: 
                   2477:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "using a SEQUENCE form, parent: <%s>",
                   2478:                                   axl_node_get_name (parent));
                   2479:                        /* because we are running a zero or one item
                   2480:                         * list matching, we don't care if it doesn't
                   2481:                         * match. In the case it match, the child
                   2482:                         * position is updated and next calls will be
                   2483:                         * properly aligned. In the match doesn't
                   2484:                         * happens, it also don't matter because the
                   2485:                         * pattern allow to not match */
                   2486:                        temp_child_pos = *child_position;
                   2487:                        if (!__axl_dtd_validate_sequence (parent, child_position, itemList, error, 
                   2488:                                                          axl_true, top_level)) {
                   2489:                                /* check that the match wasn't
                   2490:                                 * produced, at any level */
                   2491:                                if (temp_child_pos != *child_position) {
                   2492:                                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "item list mismatch (%d != %d)", 
                   2493:                                                   temp_child_pos, *child_position);
                   2494:                                        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",
                   2495:                                                       NULL, error);
                   2496:                                        return axl_false;
                   2497:                                }
                   2498: 
                   2499:                                return axl_false;
                   2500:                        }
                   2501:                        
                   2502:                }else {
                   2503:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "    using a CHOICE form");
                   2504: 
                   2505:                        /* it is a sequence, so, item list
                   2506:                         * specification represents the nodes, in the
                   2507:                         * order they must appear */
                   2508:                        __axl_dtd_validate_choice (parent, child_position, itemList, error,
                   2509:                                                   axl_true, top_level);
                   2510:                }
                   2511:                break;
                   2512:        case ZERO_OR_MANY:
                   2513: 
                   2514:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a (zero or many) spec..");
                   2515:                if (axl_dtd_item_list_type (itemList) == SEQUENCE) {
                   2516: 
                   2517:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "    using a SEQUENCE (size: %d) form ",
                   2518:                                   axl_dtd_item_list_count (itemList));
                   2519:                        /* one this case, several matches must be
                   2520:                         * tried, until the validation fails */
                   2521:                        do {
                   2522:                                temp_child_pos = *child_position;
                   2523:                                status         = __axl_dtd_validate_sequence (parent, child_position, itemList, error, 
                   2524:                                                                              axl_true, top_level);
                   2525: 
                   2526:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "sequence match status=%d", status);
                   2527:                                if (! status) {
                   2528:                                        /* check that the match wasn't
                   2529:                                         * produced, at any level */
                   2530:                                        if ((temp_child_pos != *child_position)) {
                   2531: 
                   2532:                                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "item list mismatch (%d != %d)", 
                   2533:                                                           temp_child_pos, *child_position);
                   2534:                                                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",
                   2535:                                                               NULL, error);
                   2536:                                                return axl_false;
                   2537:                                        }
                   2538:                                }
                   2539:                        }while (status);
                   2540:                }else {
                   2541: 
                   2542:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "    using a CHOICE form");
                   2543:                        /* it is a sequence, so, item list
                   2544:                         * specification represents the nodes, in the
                   2545:                         * order they must appear */
                   2546:                        do {
                   2547:                                status = __axl_dtd_validate_choice (parent, child_position, itemList, error,
                   2548:                                                                    axl_true, top_level);
                   2549:                        }while (status);
                   2550:                }
                   2551:                break;
                   2552:        case ONE_OR_MANY:
                   2553:                /* one or many sequence spec (+) */
                   2554:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a (zero or many) spec..");
                   2555:                if (axl_dtd_item_list_type (itemList) == SEQUENCE) {
                   2556: 
                   2557:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "    using a SEQUENCE (size: %d) form ",
                   2558:                                   axl_dtd_item_list_count (itemList));
                   2559: 
                   2560:                        /* one this case, several matches must be
                   2561:                         * tried, until the validation fails */
                   2562:                        already_matched = axl_false;
                   2563:                        do {
                   2564:                                temp_child_pos = *child_position;
                   2565:                                /* try to match the one or many
                   2566:                                   sequence according to the value
                   2567:                                   stored inside already matched */
                   2568:                                status         = __axl_dtd_validate_sequence (parent, child_position, itemList, error, 
                   2569:                                                                              already_matched, top_level);
                   2570: 
                   2571:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "sequence match status=%d", status);
                   2572:                                if (! status) {
                   2573:                                        /* check that the match wasn't
                   2574:                                         * produced, at any level */
                   2575:                                        if ((temp_child_pos != *child_position)) {
                   2576: 
                   2577:                                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "item list mismatch, matched partially (%d != %d)", 
                   2578:                                                           temp_child_pos, *child_position);
                   2579:                                                axl_error_new (-1, 
                   2580:                                                               "Found an DTD item list definition, that should be matched entirely or not, one or many times, but it was matched partially",
                   2581:                                                               NULL, error);
                   2582:                                                return axl_false;
                   2583:                                        }
                   2584:                                }else {
                   2585:                                        /* set that we have matched, at least, one item */
                   2586:                                        already_matched = axl_true;
                   2587:                                }
                   2588: 
                   2589:                                
                   2590: 
                   2591:                        }while (status);
                   2592:                }else {
                   2593: 
                   2594:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "    using a CHOICE form");
                   2595:                        /* it is a sequence, so, item list
                   2596:                         * specification represents the nodes, in the
                   2597:                         * order they must appear */
                   2598:                        already_matched = axl_false;
                   2599:                        do {
                   2600:                                /* the next choice matching is done
                   2601:                                 * according to the value stored in
                   2602:                                 * already matched */
                   2603:                                status = __axl_dtd_validate_choice (parent, child_position, itemList, error,
                   2604:                                                                    already_matched, top_level);
                   2605:                                /* if the validation successed, set
                   2606:                                 * that next matched are not required
                   2607:                                 * to be successful ones */
                   2608:                                if (status)
                   2609:                                        already_matched = axl_true;
                   2610:                        }while (status);
                   2611:                }
                   2612:                break;
                   2613:        default:
                   2614:                /* this case will never be reached */
                   2615: #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."
                   2616:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, INTERNAL_ERROR_01);
                   2617:                axl_error_new (-1, INTERNAL_ERROR_01, NULL, error);
                   2618:                return axl_false;
                   2619:        }
                   2620: 
                   2621: 
                   2622:        __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",
                   2623:                   top_level, axl_dtd_item_list_type (itemList), *child_position, axl_node_get_child_num (parent));
                   2624: 
                   2625:        /* check that, in the case that the choice item list is being
                   2626:         * validated, ensure it has validated all nodes, especially if
                   2627:         * we are the top level definition */
                   2628:        if (top_level && (axl_dtd_item_list_type (itemList) == CHOICE)) {
                   2629:                if (((*child_position) + 1) < axl_node_get_child_num (parent)) {
                   2630:                    
                   2631: 
                   2632:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "found that the choice list didn't cover all childs (%d), while parent=<%s> has: (%d)",
                   2633:                                   (*child_position), axl_node_get_name (parent), axl_node_get_child_num (parent));
                   2634:                        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",
                   2635:                                       NULL, error);
                   2636:                        return axl_false;
                   2637:                }
                   2638:        }
                   2639:        
                   2640:        /* element type children validated */
                   2641:        return axl_true;       
                   2642: }
                   2643: 
                   2644: /** 
                   2645:  * @internal
                   2646:  *
                   2647:  * Support function validate parent nodes which are element type
                   2648:  * children ones.
                   2649:  */
                   2650: axl_bool     __axl_dtd_validate_element_type_children (axlDtdElement  * element, 
                   2651:                                                       axlNode        * parent, 
                   2652:                                                       axl_bool         top_level,
                   2653:                                                       axlError      ** error)
                   2654: {
                   2655:        axlDtdElementList * itemList;
                   2656:        int                 child_pos = 0;
                   2657:        char              * err_msg;
                   2658: 
                   2659:        /* get a reference to the item list */
                   2660:        itemList = axl_dtd_get_item_list (element);
                   2661: 
                   2662:        /* check for xml nodes with fewer content than the initially
                   2663:         * expected. */
                   2664:        if (axl_node_get_child_num (parent) < element->minimum_match) {
                   2665:                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.",
                   2666:                                             axl_node_get_name (parent), 
                   2667:                                             axl_node_get_child_num (parent), 
                   2668:                                             element->minimum_match);
                   2669:                axl_error_new (-1, err_msg, NULL, error);
                   2670:                axl_free (err_msg);
                   2671:                return axl_false;
                   2672:        }
                   2673: 
                   2674:        /* validate the item list, starting from the child 0 */
                   2675:        if (__axl_dtd_validate_item_list (itemList, parent, &child_pos, error, top_level)) {
                   2676:                /* check if, at least, all minimum elements was
                   2677:                 * matched */
                   2678:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "checking minimum node match: (%d < min: %d) (%d < childs: %d) node=<%s>", 
                   2679:                           child_pos, element->minimum_match,
                   2680:                           child_pos, axl_node_get_child_num (parent),
                   2681:                           axl_node_get_name (parent));
                   2682:                        
                   2683:                if (child_pos < axl_node_get_child_num (parent)) {
                   2684:                        axl_error_report (error, -1,
                   2685:                                          "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.",
                   2686:                                          child_pos, element->minimum_match, child_pos, axl_node_get_child_num (parent), 
                   2687:                                          axl_node_get_name (parent));
                   2688:                        return axl_false;
                   2689:                }
                   2690:                /* seems that the minimum match */
                   2691:                return axl_true;
                   2692:        }
                   2693: 
                   2694:        return axl_false;
                   2695: }
                   2696: 
                   2697: /** 
                   2698:  * @internal
                   2699:  * Internal support function to validate #PCDATA nodes.
                   2700:  */
                   2701: axl_bool     __axl_dtd_validate_element_type_pcdata (axlDtdElement  * element, 
                   2702:                                                     axlNode        * parent, 
                   2703:                                                     axlStack       * stack, 
                   2704:                                                     axlError      ** error)
                   2705: {
                   2706:        /* check for childs */
                   2707:        if (axl_node_have_childs (parent)) {
                   2708:                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "node <%s> should be #PCDATA and it contains childs",
                   2709:                           axl_node_get_name (parent));
                   2710:                axl_error_new (-1, 
                   2711:                               "Found a node for which its espeficiation makes it to be a node with only data and no childs, and it currently contains childs",
                   2712:                               NULL, error);
                   2713:                return axl_false;
                   2714:        }
                   2715:        
                   2716:        /* return that the validation was ok */
                   2717:        return axl_true;
                   2718: }
                   2719: 
                   2720: /** 
                   2721:  * @internal
                   2722:  * 
                   2723:  * Support function to validate empty nodes.
                   2724:  */
                   2725: axl_bool     __axl_dtd_validate_element_type_empty (axlDtdElement  * element,
                   2726:                                                    axlNode        * parent,
                   2727:                                                    axlStack       * stack,
                   2728:                                                    axlError      ** error)
                   2729: {
                   2730:        char * err_msg;
                   2731: 
                   2732:        /* check the node is indeed, empty */
                   2733:        if (! axl_node_is_empty (parent)) {
                   2734:                err_msg = axl_strdup_printf (
                   2735:                        "Found a node <%s> that it is especified that must be empty, but it isn't",
                   2736:                        axl_node_get_name (parent));
                   2737:                axl_error_new (-1, err_msg, NULL, error);
                   2738:                axl_free (err_msg);
                   2739:                return axl_false;
                   2740:        }
                   2741: 
                   2742:        /* check the node doesn't have childs */
                   2743:        if (axl_node_have_childs (parent)) {
                   2744:                err_msg = axl_strdup_printf (
                   2745:                        "Found a node <%s> that it is especified that must be empty, but it has childs",
                   2746:                        axl_node_get_name (parent));
                   2747:                axl_error_new (-1, err_msg, NULL, error);
                   2748:                axl_free (err_msg);
                   2749:                return axl_false;
                   2750:        }
                   2751:        
                   2752:        /* return that the validation was ok */
                   2753:        return axl_true;
                   2754: }
                   2755: 
                   2756: axl_bool __axl_dtd_attr_validate_foreach (const char * key, const char * value, axlPointer data, axlPointer data2)
                   2757: {
                   2758:        axlDtdAttribute     * attribute = data;
                   2759:        axlError           ** error     = data2;
                   2760:        axlDtdAttributeDecl * decl;
                   2761:        char                * err_msg;
                   2762: 
                   2763:        /* get declaration associated */
                   2764:        decl = axl_list_lookup (attribute->list, __find_attr_decl, (axlPointer) key);
                   2765:        
                   2766:        if (decl == NULL) {
                   2767:                /* found an error */
                   2768:                err_msg = axl_strdup_printf ("Found an attribute (%s) which is not specified by the attribute declaration for <%s>",
                   2769:                                             key, attribute->name);
                   2770:                axl_error_new (-1, err_msg, NULL, error);
                   2771:                
                   2772:                /* free the cursor and the error message */
                   2773:                axl_free (err_msg);
                   2774: 
                   2775:                /* return axl_true here because we want to stop the process */
                   2776:                return axl_true;
                   2777:                
                   2778:        } /* end if */
                   2779: 
                   2780:        /* if the declaration is found, now check its
                   2781:         * contraints */
                   2782:        axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "checking contraint for attribute: %s=%s", decl->name, value);
                   2783:        if (decl->type == CDATA_ATTRIBUTE) {
                   2784:                /* found free attribute declaration, go ahed */
                   2785:        } else if (decl->type == ENUMERATION_TYPE) {
                   2786:                /* found an enumeration type, check and return */
                   2787:                if (axl_list_lookup (decl->enumvalues, axl_list_find_string, (char *) value) == NULL) {
                   2788:                        /* found an error */
                   2789:                        err_msg = axl_strdup_printf ("Found an attribute (%s) with a value not allowed by the enum declaration (%s) for the node <%s>",
                   2790:                                                     key, value, attribute->name);
                   2791:                        axl_error_new (-1, err_msg, NULL, error);
                   2792:                        
                   2793:                        /* free the cursor and the error message */
                   2794:                        axl_free (err_msg);
                   2795:                        return axl_true;
                   2796:                }
                   2797:        } else {
                   2798:                /* not supported yet */
                   2799:        }
                   2800: 
                   2801:        /* return axl_false to continue with the process */
                   2802:        return axl_false;
                   2803: }
                   2804: 
                   2805: axl_bool __axl_dtd_attr_validate_required (axlPointer element, axlPointer data)
                   2806: {
                   2807:        axlNode             * node = data;
                   2808:        axlDtdAttributeDecl * decl = element;
                   2809: 
                   2810:        switch (decl->defaults) {
                   2811:        case ATT_REQUIRED:
                   2812:                /* attribute required */
                   2813:                return !HAS_ATTR (node, decl->name);
                   2814:        case ATT_FIXED:
                   2815:                return !HAS_ATTR_VALUE (node, decl->name, decl->default_value);
                   2816:        default:
                   2817:                break;
                   2818:        } /* end switch */
                   2819: 
                   2820:        /* return axl_false for this because it is not obligatory
                   2821:         * to have the attribute defined. */
                   2822:        return axl_false;
                   2823: }
                   2824: 
                   2825: /** 
                   2826:  * @internal Functions which validates the attribute declaration for
                   2827:  * the node provided, using attribute declarations found.
                   2828:  * 
                   2829:  * @param node The node to check for its attributes.
                   2830:  *
                   2831:  * @param dtd The dtd used to validate the node provided.
                   2832:  *
                   2833:  * @param error A reference to the axlError where the textual
                   2834:  * diagnostic error will be reported.
                   2835:  * 
                   2836:  * @return axl_true if the node is validated, axl_false if not.
                   2837:  */
                   2838: axl_bool axl_dtd_attr_validate (axlNode * node, axlDtd * dtd, axlError ** error, axlHash * id_validation, axlList * idref_validation)
                   2839: {
                   2840:        axlDtdAttribute     * attribute;
                   2841:        axlDtdAttributeDecl * decl;
                   2842:        char                * err_msg;
                   2843:        int                   iterator;
                   2844:        axlError            * _error = NULL;
                   2845: 
                   2846:        /* find attribute contraints for the node */
                   2847:        attribute = axl_dtd_get_attr (dtd, axl_node_get_name (node));
                   2848:        if (attribute == NULL)
                   2849:                return axl_true;
                   2850: 
                   2851:        /* we have an especification, run it */
                   2852: 
                   2853:        /* for each attribute found, check against the spec */
                   2854:        axl_node_attr_foreach (node, __axl_dtd_attr_validate_foreach, attribute, &_error);
                   2855: 
                   2856:        /* check the error */
                   2857:        if (! axl_error_was_ok (_error)) {
                   2858:                /* reconfigure error returned */
                   2859:                if (error != NULL)
                   2860:                        *error = _error;
                   2861:                return axl_false;
                   2862:        } /* end if */
                   2863:                
                   2864:        
                   2865:        /* now, for each contraint, check that all required nodes
                   2866:         * exists */
                   2867:        decl = axl_list_lookup (attribute->list, __axl_dtd_attr_validate_required, node);
                   2868:        if (decl != NULL) {
                   2869:                if (decl->defaults == ATT_FIXED)
                   2870:                        err_msg = axl_strdup_printf ("attribute required '%s' (or its value), due to #FIXED declaration, not found for node <%s>", 
                   2871:                                                     decl->name, attribute->name);
                   2872:                else 
                   2873:                        err_msg = axl_strdup_printf ("attribute required '%s', due to #REQUIRED declaration, not found for node <%s>", 
                   2874:                                                     decl->name, attribute->name);
                   2875:                axl_error_new (-1, err_msg, NULL, error);
                   2876:                axl_free (err_msg);
                   2877:                return axl_false;
                   2878:        } /* end if */
                   2879: 
                   2880:        /* check declarations */
                   2881:        if (dtd->haveIdDecl) {
                   2882: 
                   2883:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found DTD has ID unique attribute declaration..");
                   2884:                
                   2885:                /* check if the node have TOKENIZED_TYPE_ID */
                   2886:                decl = axl_list_lookup (attribute->list, __find_id_decl, NULL);
                   2887:                
                   2888:                /* if we have a tokenized */
                   2889:                if (decl != NULL) {
                   2890: 
                   2891:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found ID unique attribute declaration %s=\"%s\"..",
                   2892:                                   decl->name, ATTR_VALUE (node, decl->name));
                   2893: 
                   2894:                        /* check if the attribute value for the decl that is
                   2895:                         * flagged as ID is already found at the
                   2896:                         * id_validation */
                   2897:                        if (axl_hash_exists (id_validation, (axlPointer) ATTR_VALUE (node, decl->name))) {
                   2898:                                err_msg = axl_strdup_printf ("DTD declared the attribute '%s' as unique (ID) for the node %s, but was found used several times",
                   2899:                                                             decl->name, attribute->name);
                   2900:                                axl_error_new (-1, err_msg, NULL, error);
                   2901:                                axl_free (err_msg);
                   2902:                                return axl_false;
                   2903:                        } /* end if */
                   2904:                        
                   2905:                        /* seems the attribute was not used, nice!, store it */
                   2906:                        axl_hash_insert (id_validation, (axlPointer) ATTR_VALUE (node, decl->name), (axlPointer) ATTR_VALUE (node, decl->name));
                   2907:                } /* end if */
                   2908:        } /* end if */
                   2909: 
                   2910:        if (dtd->haveIdRefDecl) {
                   2911:                /* find the id ref declaration */
                   2912:                
                   2913:                iterator = 0;
                   2914:                while (iterator < axl_list_length (attribute->list)) {
                   2915:                        
                   2916:                        /* get the attribute declaration at the
                   2917:                         * particular position */
                   2918:                        decl = axl_list_get_nth (attribute->list, iterator);
                   2919:                        if (decl->type == TOKENIZED_TYPE_IDREF) {
                   2920:                                /* found a reference, but do not check
                   2921:                                 * it at this place becase the
                   2922:                                 * reference could be placed at any
                   2923:                                 * part in the document event after
                   2924:                                 * the reference pointed is
                   2925:                                 * defined. store and check later */
                   2926:                                if (ATTR_VALUE (node, decl->name)) {
                   2927:                                        /* store the id ref reference
                   2928:                                         * if defined */
                   2929:                                        axl_list_add (idref_validation, (axlPointer) ATTR_VALUE (node, decl->name));
                   2930:                                }
                   2931:                        } /* end if */
                   2932: 
                   2933:                        /* get the next */
                   2934:                        iterator++;
                   2935:                        
                   2936:                } /* end if */
                   2937:                
                   2938:        } /* end if */
                   2939: 
                   2940:        axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "attributes validated for node=<%s>", attribute->name);
                   2941:        
                   2942:        return axl_true;
                   2943: }
                   2944: 
                   2945: /** 
                   2946:  * @internal Function used by axl_dtd_validate_references to ensure
                   2947:  * that all references found point to a valid reference defined.
                   2948:  */
                   2949: axl_bool __axl_dtd_reference_check (axlPointer _element, axlPointer data)
                   2950: {
                   2951: #if defined(SHOW_DEBUG_LOG)
                   2952:        const char * value = _element;
                   2953: 
                   2954:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "checking id ref: %s", value);
                   2955: #endif
                   2956: 
                   2957:        return ! axl_hash_exists ((axlHash *) data, _element);
                   2958: }
                   2959: 
                   2960: /** 
                   2961:  * @internal Function that validates all references found (from IDREF
                   2962:  * attribute) to unique references (defined by ID attributes).
                   2963:  *
                   2964:  */
                   2965: axl_bool axl_dtd_validate_references (axlHash * id_validation, axlList * idref_validation, axlError ** error)
                   2966: {
                   2967:        char * reference;
                   2968:        char * err_msg;
                   2969:        
                   2970:        /* if no empty at the valiadtion reference list, means not
                   2971:         * reference was done, so there is no room for errors */
                   2972:        if (idref_validation == NULL) 
                   2973:                return axl_true;
                   2974:        
                   2975:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "id_validation reference: 0x%x", id_validation);
                   2976: 
                   2977:        /* find first reference not found */
                   2978:        reference = axl_list_lookup (idref_validation, __axl_dtd_reference_check, id_validation);
                   2979:        
                   2980:        if (reference != NULL) {
                   2981:                /* found a reference not defined, report it to the
                   2982:                 * application level */
                   2983:                err_msg = axl_strdup_printf ("Found a reference defined ('%s') which is not found in any ID attribute in the document",
                   2984:                                             reference);
                   2985:                axl_error_new (-1, err_msg, NULL, error);
                   2986:                axl_free (err_msg);
                   2987: 
                   2988:                return axl_false;
                   2989:        } /* end if */
                   2990:        
                   2991:        /* validation ok */
                   2992:        return axl_true;
                   2993: }
                   2994: 
                   2995: /** 
                   2996:  * @brief Allows to validate the given XML document (\ref axlDoc)
                   2997:  * against the given document type definition (DTD, \ref axlDtd).
                   2998:  *
                   2999:  * This function allows to validate your XML documents providing the
                   3000:  * document type definition, that was read using \ref axl_dtd_parse or
                   3001:  * \ref axl_dtd_parse_from_file.
                   3002:  *
                   3003:  * Keep in mind that a document could be well-formed and valid. The
                   3004:  * only difference is that valid XML document are those that, meet all
                   3005:  * XML rules, but also are clasified and recognized as XML documents
                   3006:  * with some particular structure, that is represented (or
                   3007:  * constrained) with providing a DTD definition.
                   3008:  *
                   3009:  * @param doc The \ref axlDoc containing the XML document to be
                   3010:  * validated.
                   3011:  *
                   3012:  * @param dtd The \ref axlDtd containing the DTD definition used to
                   3013:  * validate the document.
                   3014:  *
                   3015:  * @param error An optional reference to a \ref axlError object where
                   3016:  * validation errors are reported.
                   3017:  *
                   3018:  * @return axl_true if the document is valid, axl_false if not.
                   3019:  */
                   3020: axl_bool           axl_dtd_validate        (axlDoc * doc, axlDtd * dtd,
                   3021:                                            axlError ** error)
                   3022: {
                   3023:        axlNode            * parent;
                   3024:        axlStack           * stack;
                   3025:        axlHash            * id_validation = NULL;
                   3026:        axlList            * idref_validation = NULL;
                   3027:        
                   3028:        axlDtdElement      * element;
                   3029:        axl_bool             top_level;
                   3030:        char               * err_msg;
                   3031:        axl_bool             result;
                   3032:        
                   3033:        /* perform some checkings */
                   3034:        axl_return_val_if_fail (doc, axl_false);
                   3035:        axl_return_val_if_fail (dtd, axl_false);
                   3036: 
                   3037:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "starting DTD validation");
                   3038: 
                   3039:        /* validate the very first root node */
                   3040:        parent  = axl_doc_get_root (doc);
                   3041:        element = axl_dtd_get_root (dtd);
                   3042:        if ((element != NULL) && ! NODE_CMP_NAME (parent, axl_dtd_get_element_name (element))) {
                   3043: 
                   3044:                /* because a DTD document could have several top level
                   3045:                 * elements, ensure this is not the case */
                   3046:                element = axl_dtd_get_element (dtd, axl_node_get_name (parent));
                   3047:                if (element == NULL) { /*  || ! axl_dtd_element_is_toplevel (dtd, element)) { */
                   3048:                        /* root node doesn't match */
                   3049:                        err_msg = axl_strdup_printf ("Found that root node doesn't match (%s != %s!",
                   3050:                                                     axl_node_get_name (parent), 
                   3051:                                                     axl_dtd_get_element_name (element));
                   3052:                        axl_error_new (-1, err_msg, NULL, error);
                   3053:                        axl_free (err_msg);
                   3054:                        return axl_false;
                   3055: 
                   3056:                } /* end if */
                   3057:        } /* end if */
                   3058: 
                   3059:        /* check if the node has DTD element declaration */
                   3060:        if (element == NULL) {
                   3061:                err_msg = axl_strdup_printf ("There is not DTD element declaration to validate the node <%s>", 
                   3062:                                             axl_node_get_name (parent));
                   3063:                axl_error_new (-1, err_msg, NULL, error);
                   3064:                axl_free (err_msg);
                   3065:                return axl_false;
                   3066:        } /* end if */
                   3067: 
                   3068:        /* check if the dtd contains a Id declaration */
                   3069:        if (dtd->haveIdDecl) {
                   3070:                /* seems the user have declarted ID attributes init the hash */
                   3071:                id_validation = axl_hash_new (axl_hash_string, axl_hash_equal_string);
                   3072:        } /* end if */
                   3073: 
                   3074:        /* check if the dtd contains Id ref declarations */
                   3075:        if (dtd->haveIdRefDecl) {
                   3076:                /* create a list that could contain all references done */
                   3077:                idref_validation = axl_list_new (axl_list_always_return_1, NULL);
                   3078:        } /* end if */
                   3079: 
                   3080:        /* check empty content spec */
                   3081:        if (axl_dtd_get_element_type (element) == ELEMENT_TYPE_EMPTY) {
                   3082:                /* check if the document provided have only one node */
                   3083:                result = axl_node_is_empty (parent) && !axl_node_have_childs (parent) && axl_dtd_attr_validate (parent, dtd, error, id_validation, idref_validation);
                   3084: 
                   3085:                /* check references */
                   3086:                if (result)
                   3087:                        result = axl_dtd_validate_references (id_validation, idref_validation, error);
                   3088:                
                   3089:                /* free and return */
                   3090:                axl_hash_free (id_validation);
                   3091: 
                   3092:                /* free the list */
                   3093:                axl_list_free (idref_validation);
                   3094:                return result;
                   3095:        } /* end if */
                   3096: 
                   3097:        /* queue initial nodes to validate */
                   3098:        stack     = axl_stack_new (NULL);
                   3099:        
                   3100: 
                   3101:        /* set that the only top level node is the first one */
                   3102:        top_level = axl_true;
                   3103: 
                   3104:        do {
                   3105:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "doing a DTD iteration: <%s>...",
                   3106:                           axl_node_get_name (parent));
                   3107: 
                   3108:                /* validate attributes */
                   3109:                if (! axl_dtd_attr_validate (parent, dtd, error, id_validation, idref_validation)) {
                   3110:                        /* free the stack */
                   3111:                        axl_stack_free (stack);
                   3112: 
                   3113:                        /* free id_validation */
                   3114:                        axl_hash_free (id_validation);
                   3115: 
                   3116:                        /* free the list */
                   3117:                        axl_list_free (idref_validation);
                   3118:                        return axl_false;
                   3119:                }
                   3120: 
                   3121:                /* reach this position, the <parent> reference contains
                   3122:                 * a reference to the parent node, which will be used
                   3123:                 * to validate current child content against current
                   3124:                 * configuration for dtd element constraining it.
                   3125:                 * 
                   3126:                 * equally, the <element> reference contains a dtd
                   3127:                 * reference to the already checked DTD element which
                   3128:                 * configure this parent node. */
                   3129:                switch (axl_dtd_get_element_type (element)) {
                   3130:                case ELEMENT_TYPE_PCDATA:
                   3131:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "  find  PCDATA dtd element=%s: parent=<%s>, ",
                   3132:                                   axl_dtd_get_element_name (element), 
                   3133:                                   axl_node_get_name (parent));
                   3134: 
                   3135:                        /* ok, a leaf node was found, know it is
                   3136:                         * required to check that the node doesn't
                   3137:                         * have more childs and only have content,
                   3138:                         * that is, it is not empty  */
                   3139:                        if (!__axl_dtd_validate_element_type_pcdata (element, parent, stack, error)) {
                   3140:                                /* free id_validation */
                   3141:                                axl_hash_free (id_validation);
                   3142: 
                   3143:                                /* free the stack */
                   3144:                                axl_stack_free (stack);
                   3145:                                
                   3146:                                /* free the list */
                   3147:                                axl_list_free (idref_validation);
                   3148:                                return axl_false;
                   3149:                        }
                   3150:                        break;
                   3151:                case ELEMENT_TYPE_CHILDREN:
                   3152: 
                   3153:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "  find  CHILDREN dtd element");
                   3154:                        /* ok, a parent node that have childs */
                   3155:                        if (!__axl_dtd_validate_element_type_children (element, parent, top_level, error)) {
                   3156:                                /* free id_validation */
                   3157:                                axl_hash_free (id_validation);
                   3158: 
                   3159:                                /* free the stack */
                   3160:                                axl_stack_free (stack);
                   3161: 
                   3162:                                /* free the list */
                   3163:                                axl_list_free (idref_validation);
                   3164:                                
                   3165:                                return axl_false;
                   3166:                        }
                   3167:                        break;
                   3168:                case ELEMENT_TYPE_EMPTY:
                   3169:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "  find  EMPTY dtd element");
                   3170:                        /* the element especification is empty, the
                   3171:                         * node being validated must also be the
                   3172:                         * same */
                   3173:                        if (!__axl_dtd_validate_element_type_empty (element, parent, stack, error)) {
                   3174:                                /* free id_validation */
                   3175:                                axl_hash_free (id_validation);
                   3176: 
                   3177:                                /* free the stack */
                   3178:                                axl_stack_free (stack);
                   3179: 
                   3180:                                /* free the list */
                   3181:                                axl_list_free (idref_validation);
                   3182: 
                   3183:                                return axl_false;
                   3184:                        }
                   3185:                        break;
                   3186:                case ELEMENT_TYPE_ANY:
                   3187:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "  find  ANY dtd element");
                   3188:                        /* the anything is allowed cased from this
                   3189:                         * parent node. */
                   3190:                        goto continue_with_validation;
                   3191:                case ELEMENT_TYPE_MIXED:
                   3192:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "  find  MIXED dtd element");
                   3193: 
                   3194:                        /* the mixed case, where nodes and PC data
                   3195:                         * could be mixed */
                   3196:                        break;
                   3197:                default:
                   3198:                        /* do not do any thing on this case */
                   3199:                        break;
                   3200:                }
                   3201:                        
                   3202:                /* queue more childs, as future parents to be
                   3203:                 * validated on the provided queue, only in the case
                   3204:                 * the parent node have childs */
                   3205:                if (axl_node_have_childs (parent)) {
                   3206: 
                   3207:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "parent node <%s> have childs, adding its childs (stack size: %d)",
                   3208:                                   axl_node_get_name (parent),
                   3209:                                   axl_stack_size (stack));
                   3210: 
                   3211:                        /* queue childs to be processed */
                   3212:                        __axl_dtd_queue_childs (stack, parent);
                   3213: 
                   3214:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "parent node <%s> childs: %d, (stack size: %d)",
                   3215:                                   axl_node_get_name (parent), axl_node_get_child_num (parent),
                   3216:                                   axl_stack_size (stack));
                   3217:                }
                   3218:                
                   3219:                /* set the parent reference to NULL */
                   3220:                parent = NULL;
                   3221:                        
                   3222:                /* update the reference to the new parent node, only
                   3223:                 * if there are new parents on the stack */
                   3224:        continue_with_validation:
                   3225:                if (! axl_stack_is_empty (stack)) {
                   3226: 
                   3227: 
                   3228:                        /* get a new reference */
                   3229:                        parent  = axl_stack_pop (stack);
                   3230:                        
                   3231:                        /* get a reference to the DTD element to used */
                   3232:                        element = axl_dtd_get_element (dtd, axl_node_get_name (parent));
                   3233:                        if (element == NULL) {
                   3234:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "found that the node <%s> doesn't have DTD especification", 
                   3235:                                           axl_node_get_name (parent));
                   3236:                                /* prepare the error message */
                   3237:                                err_msg = axl_strdup_printf ("Found a node <%s> that doesn't have a DTD element espefication to validate it, DTD validation failed",
                   3238:                                                             axl_node_get_name (parent));
                   3239:                                axl_error_new (-1, err_msg, NULL, error);
                   3240:                                axl_free (err_msg);
                   3241: 
                   3242:                                /* free id_validation */
                   3243:                                axl_hash_free (id_validation);
                   3244: 
                   3245:                                /* free the list */
                   3246:                                axl_list_free (idref_validation);
                   3247: 
                   3248:                                /* free the stack */
                   3249:                                axl_stack_free (stack);
                   3250:                                return axl_false;
                   3251:                        } /* end if */
                   3252:                } /* end if */
                   3253: 
                   3254:                /* set the top level status */
                   3255:                top_level = axl_false;
                   3256:                
                   3257:                /* until the stack is empty */
                   3258:        }while (parent != NULL);
                   3259: 
                   3260:        /* check references */
                   3261:        result = axl_dtd_validate_references (id_validation, idref_validation, error);
                   3262: 
                   3263:        /* deallocate stack used */
                   3264:        axl_stack_free (stack);
                   3265: 
                   3266:        /* free id_validation */
                   3267:        axl_hash_free (id_validation);
                   3268: 
                   3269:        /* free the list */
                   3270:        axl_list_free (idref_validation);
                   3271: 
                   3272:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "DTD validation, %s", result ? "ok" : "failed");
                   3273: 
                   3274:        /* the document is valid */
                   3275:        return result;
                   3276: }
                   3277: 
                   3278: /** 
                   3279:  * @brief Allows to check if the provided two references represents
                   3280:  * DTD documents with the same rules. 
                   3281:  * 
                   3282:  * @param dtd First reference to compare.
                   3283:  * @param dtd2 Second reference to compare.
                   3284:  *
                   3285:  * @return axl_true if both references represent the same document. If
                   3286:  * some of the references received are NULL the function returns
                   3287:  * axl_false.
                   3288:  *
                   3289:  * NOTE: The function does not have the ability to perform a smart
                   3290:  * equal operation like detecting DTD that are semantically
                   3291:  * equivalent. It only checks internal structure. 
                   3292:  */
                   3293: axl_bool                 axl_dtd_are_equal        (axlDtd * dtd,
                   3294:                                                   axlDtd * dtd2)
                   3295: {
                   3296:        int iterator;
                   3297:        int iterator2;
                   3298:        int iterator3;
                   3299:        axlDtdEntity          * entity,      * entity2;
                   3300:        axlDtdElement         * element,     * element2;
                   3301:        axlDtdElementListNode * node,        * node2;
                   3302:        axlDtdAttribute       * attribute,   * attribute2;
                   3303:        axlDtdAttributeDecl   * attr_decl,   * attr_decl2;
                   3304: 
                   3305:        /* check references received */
                   3306:        if (dtd == NULL)
                   3307:                return axl_false;
                   3308:        if (dtd2 == NULL)
                   3309:                return axl_false;
                   3310: 
                   3311:        /* check each rule inside both documents */
                   3312:        if (axl_list_length (dtd->entities) != axl_list_length (dtd2->entities))
                   3313:                return axl_false;
                   3314:        if (axl_list_length (dtd->elements) != axl_list_length (dtd2->elements))
                   3315:                return axl_false;
                   3316:        if (axl_list_length (dtd->attributes) != axl_list_length (dtd2->attributes))
                   3317:                return axl_false;
                   3318:        if (dtd->haveIdRefDecl != dtd2->haveIdRefDecl)
                   3319:                return axl_false;
                   3320:        if (dtd->haveIdDecl != dtd2->haveIdDecl)
                   3321:                return axl_false;
                   3322: 
                   3323:        /* now check inner elements (ENTITIES) */
                   3324:        iterator = 0;
                   3325:        while (iterator < axl_list_length (dtd->entities)) {
                   3326:                /* get referneces */
                   3327:                entity  = axl_list_get_nth (dtd->entities, iterator);
                   3328:                entity2 = axl_list_get_nth (dtd2->entities, iterator);
                   3329: 
                   3330:                /* check types */
                   3331:                if (entity->type != entity2->type)
                   3332:                        return axl_false;
                   3333: 
                   3334:                /* check names */
                   3335:                if (! axl_cmp (entity->name, entity2->name)) 
                   3336:                        return axl_false;
                   3337: 
                   3338:                /* check content */
                   3339:                if (! axl_cmp (entity->content, entity2->content))
                   3340:                        return axl_false;
                   3341: 
                   3342:                /* check external data */
                   3343:                if (entity->data == NULL && entity2->data != NULL)
                   3344:                        return axl_false;
                   3345:                if (entity->data != NULL && entity2->data == NULL)
                   3346:                        return axl_false;
                   3347:                if (entity->data != NULL && entity2->data != NULL) {
                   3348:                        if (! axl_cmp (entity->data->system_literal, entity2->data->system_literal))
                   3349:                                return axl_false;
                   3350:                        if (! axl_cmp (entity->data->public_literal, entity2->data->public_literal))
                   3351:                                return axl_false;
                   3352:                        if (! axl_cmp (entity->data->ndata, entity2->data->ndata))
                   3353:                                return axl_false;
                   3354:                } /* end if */
                   3355: 
                   3356:                /* next iterator */
                   3357:                iterator++;
                   3358:        } /* end while */
                   3359: 
                   3360:        /* now check inner elements (ELEMENTS) */
                   3361:        iterator = 0;
                   3362:        while (iterator < axl_list_length (dtd->elements)) {
                   3363:                /* get referneces */
                   3364:                element  = axl_list_get_nth (dtd->elements, iterator);
                   3365:                element2 = axl_list_get_nth (dtd2->elements, iterator);
                   3366: 
                   3367:                /* check types */
                   3368:                if (element->type != element2->type)
                   3369:                        return axl_false;
                   3370: 
                   3371:                /* minimum match */
                   3372:                if (element->minimum_match != element2->minimum_match)
                   3373:                        return axl_false;
                   3374: 
                   3375:                /* check names */
                   3376:                if (! axl_cmp (element->name, element2->name)) 
                   3377:                        return axl_false;
                   3378: 
                   3379:                /* check element list */
                   3380:                if (element->list == NULL && element2->list != NULL)
                   3381:                        return axl_false;
                   3382:                if (element->list != NULL && element2->list == NULL)
                   3383:                        return axl_false;
                   3384:                if (element->list != NULL && element2->list != NULL) {
                   3385: 
                   3386:                        /* check internal values */
                   3387:                        if (element->list->type != element2->list->type)
                   3388:                                return axl_false;
                   3389:                        if (element->list->times != element2->list->times)
                   3390:                                return axl_false;
                   3391: 
                   3392:                        iterator2 = 0;
                   3393:                        while (iterator2 < axl_list_length (element->list->itemList)) {
                   3394:                                
                   3395:                                /* get references */
                   3396:                                node  = axl_list_get_nth (element->list->itemList, iterator2);
                   3397:                                node2 = axl_list_get_nth (element2->list->itemList, iterator2);
                   3398: 
                   3399:                                if (node->type != node->type)
                   3400:                                        return axl_false;
                   3401:                                if (node->times != node2->times)
                   3402:                                        return axl_false;
                   3403:                                
                   3404:                                /* next value */
                   3405:                                iterator2++;
                   3406: 
                   3407:                        } /* end while */
                   3408:                        
                   3409:                } /* end if */
                   3410: 
                   3411:                /* next iterator */
                   3412:                iterator++;
                   3413:        } /* end while */
                   3414: 
                   3415:        /* now check inner elements (ATTRIBUTES) */
                   3416:        iterator = 0;
                   3417:        while (iterator < axl_list_length (dtd->attributes)) {
                   3418:                /* get referneces */
                   3419:                attribute  = axl_list_get_nth (dtd->attributes, iterator);
                   3420:                attribute2 = axl_list_get_nth (dtd2->attributes, iterator);
                   3421: 
                   3422:                /* check names */
                   3423:                if (! axl_cmp (attribute->name, attribute2->name)) 
                   3424:                        return axl_false;
                   3425: 
                   3426:                /* check values */
                   3427:                if (attribute->list == NULL && attribute2->list != NULL)
                   3428:                        return axl_false;
                   3429:                if (attribute->list != NULL && attribute2->list == NULL)
                   3430:                        return axl_false;
                   3431:                if (attribute->list != NULL && attribute2->list != NULL) {
                   3432: 
                   3433:                        /* check list length */
                   3434:                        if (axl_list_length (attribute->list) != axl_list_length (attribute2->list))
                   3435:                                return axl_false;
                   3436: 
                   3437:                        /* check internal values */
                   3438:                        iterator2 = 0;
                   3439:                        while (iterator2 < axl_list_length (attribute->list)) {
                   3440:                                
                   3441:                                /* get references */
                   3442:                                attr_decl   = axl_list_get_nth (attribute->list,  iterator2);
                   3443:                                attr_decl2  = axl_list_get_nth (attribute2->list, iterator2);
                   3444: 
                   3445:                                if (attr_decl->type != attr_decl2->type)
                   3446:                                        return axl_false;
                   3447:                                if (attr_decl->defaults != attr_decl2->defaults)
                   3448:                                        return axl_false;
                   3449:                                if (! axl_cmp (attr_decl->name, attr_decl2->name))
                   3450:                                        return axl_false;
                   3451:                                
                   3452:                                if (attr_decl->enumvalues == NULL && attr_decl2->enumvalues != NULL)
                   3453:                                        return axl_false;
                   3454:                                if (attr_decl->enumvalues != NULL && attr_decl2->enumvalues == NULL)
                   3455:                                        return axl_false;
                   3456:                                if (attr_decl->enumvalues != NULL && attr_decl2->enumvalues != NULL) {
                   3457:                                        if (axl_list_length (attr_decl->enumvalues) != axl_list_length (attr_decl2->enumvalues))
                   3458:                                                return axl_false;
                   3459:                                        iterator3 = 0;
                   3460:                                        while (iterator3 < axl_list_length (attr_decl->enumvalues)) {
                   3461:                                                /* check values */
                   3462:                                                if (! axl_cmp (axl_list_get_nth (attr_decl->enumvalues, iterator3),
                   3463:                                                               axl_list_get_nth (attr_decl2->enumvalues, iterator3)))
                   3464:                                                        return axl_false;
                   3465: 
                   3466:                                                /* next value */
                   3467:                                                iterator3++;
                   3468:                                        } /* end while */
                   3469:                                } /* end if */
                   3470:                                
                   3471:                                /* next value */
                   3472:                                iterator2++;
                   3473: 
                   3474:                        } /* end while */
                   3475:                        
                   3476:                } /* end if */
                   3477: 
                   3478:                /* next iterator */
                   3479:                iterator++;
                   3480:        } /* end while */
                   3481: 
                   3482:        return axl_true;
                   3483:        
                   3484: }
                   3485: 
                   3486: /** 
                   3487:  * @brief Allows to get the root node for the provided DTD.
                   3488:  *
                   3489:  * Every DTD have a root node defined, which is the root node accepted
                   3490:  * for the set of XML document considered to be valid under the
                   3491:  * definition of the DTD provided.
                   3492:  *
                   3493:  * The value returned is the name of the root node that must have the
                   3494:  * XML document being validated.
                   3495:  * 
                   3496:  * @param dtd The \ref axlDtd where the root node name will be
                   3497:  * returned.
                   3498:  * 
                   3499:  * @return A reference to the internal representation of the root node
                   3500:  * Value must not be deallocated.
                   3501:  */
                   3502: axlDtdElement  * axl_dtd_get_root        (axlDtd * dtd)
                   3503: {
                   3504:        axl_return_val_if_fail (dtd, NULL);
                   3505:        
                   3506:        /* return current status for the root node */
                   3507:        if (dtd->root == NULL) {
                   3508:                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "dtd root element not defined");
                   3509:                return NULL;
                   3510:        }
                   3511:        return dtd->root;
                   3512: }
                   3513: 
                   3514: /** 
                   3515:  * @internal function used by \ref axl_dtd_get_element to perform node
                   3516:  * lookups.
                   3517:  */
                   3518: axl_bool __find_dtd_element (axlPointer _element, axlPointer data)
                   3519: {
                   3520:        axlDtdElement * element = _element;
                   3521:        char          * name    = data;
                   3522: 
                   3523:        /* check the name */
                   3524:        if (axl_cmp (element->name, name))
                   3525:                return axl_true;
                   3526: 
                   3527:        /* it is not the element */
                   3528:        return axl_false;
                   3529: }
                   3530: 
                   3531: /** 
                   3532:  * @brief Allows to get the DTD element (\ref axlDtdElement), inside
                   3533:  * the provided DTD (\ref axlDtd), that represent the spefication for
                   3534:  * the node called by the provided name.
                   3535:  * 
                   3536:  * @param dtd The DTD (\ref axlDtd) where the lookup will be
                   3537:  * performed.
                   3538:  *
                   3539:  * @param name The element name to lookup.
                   3540:  * 
                   3541:  * @return A reference to the \ref axlDtdElement searched or NULL if
                   3542:  * fails. The function also returns NULL if values received are NULL.
                   3543:  */
                   3544: axlDtdElement      * axl_dtd_get_element      (axlDtd * dtd, const char * name)
                   3545: {
                   3546: 
                   3547:        axl_return_val_if_fail (dtd, NULL);
                   3548:        axl_return_val_if_fail (name, NULL);
                   3549: 
                   3550:        /* perform the lookup */
                   3551:        return axl_list_lookup (dtd->elements, __find_dtd_element, (axlPointer) name);
                   3552: }
                   3553: 
                   3554: /** 
                   3555:  * @internal function used by \ref axl_dtd_get_attr to perform node
                   3556:  * lookups.
                   3557:  */
                   3558: axl_bool __find_dtd_attr (axlPointer _element, axlPointer data)
                   3559: {
                   3560:        axlDtdAttribute * attr = _element;
                   3561:        char            * name = data;
                   3562: 
                   3563:        /* check the name */
                   3564:        if (axl_cmp (attr->name, name))
                   3565:                return axl_true;
                   3566: 
                   3567:        /* it is not the element */
                   3568:        return axl_false;
                   3569: }
                   3570: 
                   3571: /** 
                   3572:  * @brief Allows to get the set of attribute declerations for a
                   3573:  * particular node. 
                   3574:  *
                   3575:  * The \ref axlDtdAttribute declaration contains all constraints
                   3576:  * configured for attributes found for the particular xml node
                   3577:  * (identified by <b>name</b>).
                   3578:  * 
                   3579:  * @param dtd A reference to the DTD document.
                   3580:  *
                   3581:  * @param nodeName The xml node that is requested to return all attribute
                   3582:  * declarations.
                   3583:  * 
                   3584:  * @return A reference to the \ref axlDtdAttribute or NULL if it
                   3585:  * fails.
                   3586:  */
                   3587: axlDtdAttribute    * axl_dtd_get_attr         (axlDtd * dtd,
                   3588:                                               const char * nodeName)
                   3589: {
                   3590:        axl_return_val_if_fail (dtd, NULL);
                   3591:        axl_return_val_if_fail (nodeName, NULL);
                   3592: 
                   3593:        /* perform the lookup */
                   3594:        return axl_list_lookup (dtd->attributes, __find_dtd_attr, (axlPointer) nodeName);
                   3595: }
                   3596: 
                   3597: /** 
                   3598:  * @brief Allows to get the number of constraints that have been
                   3599:  * configured for the particular node.
                   3600:  * 
                   3601:  * @param dtd The reference to the DTD document.
                   3602:  *
                   3603:  * @param nodeName The name of the node that is being asked for its
                   3604:  * constraints.
                   3605:  * 
                   3606:  * @return 0 or the number of contraints. The function return -1 if
                   3607:  * any of the parameter received is null.
                   3608:  */
                   3609: int                  axl_dtd_get_attr_contraints (axlDtd * dtd,
                   3610:                                                  const char * nodeName)
                   3611: {
                   3612:        axlDtdAttribute * attr;
                   3613: 
                   3614:        axl_return_val_if_fail (dtd, -1);
                   3615:        axl_return_val_if_fail (nodeName, -1);
                   3616: 
                   3617:        /* get the attribute specification for the node */
                   3618:        attr = axl_dtd_get_attr (dtd, nodeName);
                   3619: 
                   3620:        /* return the number of items */
                   3621:        return axl_list_length (attr->list);
                   3622: }
                   3623: 
                   3624: /** 
                   3625:  * @brief Returns the name of the provided \ref axlDtdElement.
                   3626:  * 
                   3627:  * @param element A reference to a \ref axlDtdElement where the name
                   3628:  * will be returned.
                   3629:  * 
                   3630:  * @return A reference to the internal DTD element name. Returned
                   3631:  * value mustn't be deallocated.
                   3632:  */
                   3633: char           * axl_dtd_get_element_name (axlDtdElement * element)
                   3634: {
                   3635:        axl_return_val_if_fail (element,  NULL);
                   3636: 
                   3637:        return element->name;
                   3638: }
                   3639: 
                   3640: /** 
                   3641:  * @brief Returns current element type for the provided \ref axlDtdElement.
                   3642:  * 
                   3643:  * @param element The axlDtdElement where its type will be returned.
                   3644:  * 
                   3645:  * @return Current element type for the provided node.
                   3646:  */
                   3647: AxlDtdElementType    axl_dtd_get_element_type (axlDtdElement * element)
                   3648: {
                   3649:        axl_return_val_if_fail (element, ELEMENT_TYPE_UNKNOWN);
                   3650:        
                   3651:        return element->type;
                   3652: }
                   3653: 
                   3654: /** 
                   3655:  * @brief Returns current DTD content specification, represented by the Item list.
                   3656:  * 
                   3657:  * @param element The DTD element (\ref axlDtdElement) which is being
                   3658:  * requested to return its \ref axlDtdElementList.
                   3659:  * 
                   3660:  * @return The \ref axlDtdElementList reference. The value returned
                   3661:  * must not be deallocated. The function returns NULL if the reference received is NULL.
                   3662:  */
                   3663: axlDtdElementList  * axl_dtd_get_item_list    (axlDtdElement * element)
                   3664: {
                   3665:        axl_return_val_if_fail (element, NULL);
                   3666: 
                   3667:        return element->list; 
                   3668: }
                   3669: 
                   3670: /** 
                   3671:  * @brief Allows to check if the provided DTD ELEMENT representation
                   3672:  * is a top level definition.
                   3673:  * 
                   3674:  * @param dtd The DTD document where the operation will be performed.
                   3675:  * @param element The \ref axlDtdElement to check.
                   3676:  * 
                   3677:  * @return \ref axl_true if the dtd element is a top level element or
                   3678:  * \ref axl_false if not. The function returns \ref axl_false if the
                   3679:  * provided reference is NULL.
                   3680:  */
                   3681: axl_bool                    axl_dtd_element_is_toplevel (axlDtd * dtd, axlDtdElement * element)
                   3682: {
                   3683:        /* support several top level definitions */
                   3684:        int             iterator;
                   3685:        axlDtdElement * dtd_element_aux;
                   3686: 
                   3687:        axl_return_val_if_fail (dtd,     axl_false);
                   3688:        axl_return_val_if_fail (element, axl_false);
                   3689: 
                   3690:        /* check which is the top */
                   3691:        iterator        = 0;
                   3692:        while (iterator < axl_list_length (dtd->elements)) {
                   3693:                        
                   3694:                /* get the next reference */
                   3695:                dtd_element_aux = axl_list_get_nth (dtd->elements, iterator);
                   3696:                        
                   3697:                /* check which is the top */
                   3698:                if (__axl_dtd_get_is_parent (dtd_element_aux, element)) {
                   3699:                        /* the element provided have a parent */
                   3700:                        return axl_false;
                   3701:                }
                   3702:                        
                   3703:                /* update inner loop iterator */
                   3704:                iterator ++;
                   3705:        } /* while end */
                   3706: 
                   3707:        /* return that the provided node doesn't have a parent node */
                   3708:        return axl_true;
                   3709: }
                   3710: 
                   3711: /** 
                   3712:  * @brief Returns the number of item nodes (\ref
                   3713:  * axlDtdElementListNode) inside the item list received (\ref axlDtdElementList).
                   3714:  * 
                   3715:  * @param itemList The \ref axlDtdElementList where the count
                   3716:  * operation is being requested.
                   3717:  * 
                   3718:  * @return The number of item list the provided \ref axlDtdElementList
                   3719:  * reference has. The function return -1 if the provided reference is
                   3720:  * NULL.
                   3721:  */
                   3722: int                  axl_dtd_item_list_count  (axlDtdElementList * itemList)
                   3723: {
                   3724:        axl_return_val_if_fail (itemList, -1);
                   3725: 
                   3726:        if (itemList->itemList == NULL)
                   3727:                return 0;
                   3728: 
                   3729:        return axl_list_length (itemList->itemList);
                   3730: }
                   3731: 
                   3732: /** 
                   3733:  * @brief Allows to get current configuration for the provided item
                   3734:  * list, which is the content specification for a DTD element.
                   3735:  * 
                   3736:  * @param itemList The item list where the operation will be
                   3737:  * performed.
                   3738:  * 
                   3739:  * @return Current configuration (\ref SEQUENCE or a \ref CHOICE).
                   3740:  */
                   3741: AxlDtdNestedType     axl_dtd_item_list_type   (axlDtdElementList * itemList)
                   3742: {
                   3743:        axl_return_val_if_fail (itemList, -1);
                   3744: 
                   3745:        return itemList->type;
                   3746: }
                   3747: 
                   3748: /** 
                   3749:  * @brief Allows to get current configuration for DTD content spec
                   3750:  * repetition.
                   3751:  * 
                   3752:  * @param itemList The content spec where the query will be performed.
                   3753:  * 
                   3754:  * @return Current configuration for times to be repeated DTD element
                   3755:  * content specification.
                   3756:  */
                   3757: AxlDtdTimes          axl_dtd_item_list_repeat (axlDtdElementList * itemList)
                   3758: {
                   3759:        axl_return_val_if_fail (itemList, DTD_TIMES_UNKNOWN);
                   3760: 
                   3761:        /* returns current times configuration */
                   3762:        return itemList->times;
                   3763: }
                   3764: 
                   3765: /** 
                   3766:  * @brief Allows to get the provided item node reference (\ref
                   3767:  * axlDtdElementListNode) from the provided item list (\ref
                   3768:  * axlDtdElementList).
                   3769:  *
                   3770:  * Provided position ranges from 0 up to \ref axl_dtd_item_list_count.
                   3771:  * 
                   3772:  * @param itemList The itemList where the operation will be performed.
                   3773:  * @param position The position where the item node will be looked up.
                   3774:  * 
                   3775:  * @return A reference to the \ref axlDtdElementListNode, or NULL if
                   3776:  * there is no item node at the selected index.  The function return
                   3777:  * NULL if the provided position is a non positive value or it is
                   3778:  * greater than the current item list count (\ref
                   3779:  * axl_dtd_item_list_count) or the provided item list reference is
                   3780:  * NULL.
                   3781:  */
                   3782: axlDtdElementListNode * axl_dtd_item_list_get_node (axlDtdElementList * itemList, 
                   3783:                                                    int position)
                   3784: {
                   3785:        axl_return_val_if_fail (itemList, NULL);
                   3786:        axl_return_val_if_fail (position >= 0, NULL);
                   3787:        axl_return_val_if_fail (position < axl_dtd_item_list_count (itemList), NULL);
                   3788:        
                   3789:        return axl_list_get_nth (itemList->itemList, position);
                   3790: }
                   3791: 
                   3792: /** 
                   3793:  * @brief Allows to get current node type for the provided DTD element
                   3794:  * type content particule or item node (\ref axlDtdElementListNode).
                   3795:  *
                   3796:  * @param node The node where the type is being requested.
                   3797:  * 
                   3798:  * @return It returns if the item node contains a final leaf node,
                   3799:  * making a reference to an explicit node naming that is allowed to be
                   3800:  * used in the context where is found the provided \ref
                   3801:  * axlDtdElementListNode or a \ref axlDtdElementList containing more
                   3802:  * nodes or lists. 
                   3803:  */
                   3804: NodeType             axl_dtd_item_node_get_type (axlDtdElementListNode * node)
                   3805: {
                   3806:        axl_return_val_if_fail (node, AXL_ELEMENT_NOT_DEFINED);
                   3807:        return node->type;
                   3808: }
                   3809: 
                   3810: /** 
                   3811:  * @brief Returns the item list inside the provided node.
                   3812:  *
                   3813:  * The node is supported to contain an item list reference or NULL
                   3814:  * will be returned. Check \ref axl_dtd_item_node_get_type.
                   3815:  * 
                   3816:  * @param node The node where the operation will be performed.
                   3817:  * 
                   3818:  * @return The item list inside the node or NULL if fails.
                   3819:  */
                   3820: axlDtdElementList   * axl_dtd_item_node_get_list (axlDtdElementListNode * node)
                   3821: {
                   3822:        axl_return_val_if_fail (node, NULL);
                   3823:        axl_return_val_if_fail (node->type == AXL_ELEMENT_LIST, NULL);
                   3824: 
                   3825:        return node->data;
                   3826: }
                   3827: 
                   3828: /** 
                   3829:  * @brief Allows to get the dtd item list value, which represents the
                   3830:  * node name that is being constrained/represented.
                   3831:  * 
                   3832:  * @param node The item node where the value is being requested.
                   3833:  * 
                   3834:  * @return The value inside the item node, supposing it contains an
                   3835:  * leaf item node or NULL if fails. The value returned must not be
                   3836:  * deallocated.
                   3837:  */
                   3838: char               * axl_dtd_item_node_get_value (axlDtdElementListNode * node)
                   3839: {
                   3840:        axl_return_val_if_fail (node, NULL);
                   3841:        if (node->type != AXL_ELEMENT_NODE) 
                   3842:                return "requested-value-on-a-list";
                   3843: 
                   3844:        return node->data;
                   3845: }
                   3846: 
                   3847: /** 
                   3848:  * @brief Allows to get current configuration for the provided content
                   3849:  * particule for the times to be repeated.
                   3850:  * 
                   3851:  * @param node The content particule where the query will be
                   3852:  * performed.
                   3853:  * 
                   3854:  * @return Return current repetition configuration. 
                   3855:  */
                   3856: AxlDtdTimes          axl_dtd_item_node_get_repeat (axlDtdElementListNode * node)
                   3857: {
                   3858:        axlDtdElementList * list;
                   3859: 
                   3860:        axl_return_val_if_fail (node, DTD_TIMES_UNKNOWN);
                   3861: 
                   3862: 
                   3863:        if (node->type == AXL_ELEMENT_NODE) {
                   3864:                /* return value requested */
                   3865:                return node->times;
                   3866:        }
                   3867: 
                   3868:        if (node->type == AXL_ELEMENT_LIST) {
                   3869:                /* return the requested value for an item list */
                   3870:                list = node->data;
                   3871:                return list->times;
                   3872:        }
                   3873:        
                   3874:        /* return that we don't know man */
                   3875:        return DTD_TIMES_UNKNOWN;
                   3876: }
                   3877: 
                   3878: 
                   3879: /** 
                   3880:  * @internal
                   3881:  *
                   3882:  * Internal function which allows to lookup the DTD entity reference
                   3883:  * provided the name and the type.
                   3884:  */
                   3885: axlDtdEntity * __axl_dtd_entity_lookup (axlDtd            * dtd, 
                   3886:                                        const char        * name,
                   3887:                                        axlDtdEntityType    type)
                   3888: {
                   3889:        axlDtdEntity  * entity;
                   3890:        int             iterator;
                   3891:        int             length;
                   3892: 
                   3893:        /* check values received */
                   3894:        axl_return_val_if_fail (dtd,  NULL);
                   3895:        axl_return_val_if_fail (name, NULL);
                   3896: 
                   3897:        /* lookup for the item */
                   3898:        iterator = 0;
                   3899:        length   = axl_list_length (dtd->entities);
                   3900:        while (iterator < length) {
                   3901: 
                   3902:                /* get the entity at the provided position */
                   3903:                entity = axl_list_get_nth (dtd->entities, iterator);
                   3904: 
                   3905:                /* check the type and the name */
                   3906:                if ((entity->type == type) && axl_cmp (entity->name, name))
                   3907:                        return entity;
                   3908:                
                   3909:                /* update iterator */
                   3910:                iterator++;
                   3911:        } /* end while */
                   3912: 
                   3913:        return NULL;
                   3914: }
                   3915: 
                   3916: /** 
                   3917:  * @brief Allows to check if the provided entity name, with the
                   3918:  * provided type is defined on the given DTD object.
                   3919:  * 
                   3920:  * @param dtd The \ref axlDtd instance where the entity lookup will be
                   3921:  * performed.
                   3922:  *
                   3923:  * @param name The entity name to lookup.
                   3924:  *
                   3925:  * @param type The entity type to lookup.
                   3926:  * 
                   3927:  * @return axl_true if an entity is found named as provided with the type
                   3928:  * provided. Othewise, axl_false is returned.
                   3929:  */
                   3930: axl_bool                 axl_dtd_entity_exists    (axlDtd            * dtd, 
                   3931:                                                   const char        * name,
                   3932:                                                   axlDtdEntityType    type)
                   3933: {
                   3934:        /* return if the entity exists */
                   3935:        return (__axl_dtd_entity_lookup (dtd, name, type) != NULL);
                   3936: }
                   3937: 
                   3938: /** 
                   3939:  * @brief Allows to get the content configured inside the entity that
                   3940:  * is identified by the provided name and the provided type.
                   3941:  * 
                   3942:  * @param dtd The DTD where the lookup will be performed.
                   3943:  *
                   3944:  * @param name The entity name to lookup for its content.
                   3945:  *
                   3946:  * @param type The entity type to match.
                   3947:  * 
                   3948:  * @return An internal reference to the content associated to the
                   3949:  * entity found or NULL. In case the content is defined (as return
                   3950:  * value) it must not be deallocated.
                   3951:  */
                   3952: char               * axl_dtd_entity_value     (axlDtd            * dtd, 
                   3953:                                               const char        * name,
                   3954:                                               axlDtdEntityType    type)
                   3955: {
                   3956:        axlDtdEntity * entity;
                   3957: 
                   3958:        /* get the entity reference */
                   3959:        entity = __axl_dtd_entity_lookup (dtd, name, type);
                   3960:        
                   3961:        /* check the entity reference */
                   3962:        axl_return_val_if_fail (entity, NULL);
                   3963: 
                   3964:        /* return the content */
                   3965:        return entity->content;
                   3966: }
                   3967: 
                   3968: /** 
                   3969:  * @brief Allows to destroy the provided \ref axlDtd  document.
                   3970:  * 
                   3971:  * @param dtd The \ref axlDtd document to destroy.
                   3972:  */
                   3973: void       axl_dtd_free  (axlDtd * dtd)
                   3974: {
                   3975:        if (dtd == NULL) {
                   3976:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "received a null DTD reference, doing nothing");
                   3977:                return;
                   3978:        }
                   3979:        
                   3980:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "releasing the DTD reference");
                   3981:        /* free dtd elements */
                   3982:        if (dtd->elements)
                   3983:                axl_list_free (dtd->elements);
                   3984: 
                   3985:        /* free entities */
                   3986:        if (dtd->entities)
                   3987:                axl_list_free (dtd->entities);
                   3988: 
                   3989:        /* free attributes */
                   3990:        if (dtd->attributes)
                   3991:                axl_list_free (dtd->attributes);
                   3992: 
                   3993:        /* free the node itself */
                   3994:        axl_free (dtd);
                   3995: 
                   3996:        return;
                   3997: }
                   3998: 
                   3999: 
                   4000: /** 
                   4001:  * @internal
                   4002:  *
                   4003:  * @brief Allows to release the memory hold by the given
                   4004:  * axlDtdElement.
                   4005:  * 
                   4006:  * @param element The axlDtdElement to release.
                   4007:  */
                   4008: void       axl_dtd_element_free (axlDtdElement * element)
                   4009: {
                   4010:        if (element == NULL)
                   4011:                return;
                   4012: 
                   4013:        /* free element name */
                   4014:        if (element->name != NULL)
                   4015:                axl_free (element->name);
                   4016: 
                   4017:        /* free element list definitions */
                   4018:        axl_dtd_item_list_free (element->list);
                   4019:        
                   4020:        /* free element itself */
                   4021:        axl_free (element);
                   4022: 
                   4023:        return;
                   4024: }
                   4025: 
                   4026: /** 
                   4027:  * @internal 
                   4028:  *
                   4029:  * @brief Deallocates memory used by the \ref axlDtdElementList
                   4030:  * reference.
                   4031:  * 
                   4032:  * @param list The reference to deallocate.
                   4033:  */
                   4034: void axl_dtd_item_list_free (axlDtdElementList * list)
                   4035: {
                   4036:        if (list == NULL)
                   4037:                return;
                   4038:        
                   4039:        /* check and deallocate the list provided */
                   4040:        if (list->itemList != NULL)
                   4041:                axl_list_free (list->itemList);
                   4042:        
                   4043:        /* deallocates the node itself */
                   4044:        axl_free (list);
                   4045:        return;
                   4046: }
                   4047: 
                   4048: /* @} */
                   4049: 

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