Annotation of gpl/axl/src/axl_node.c, revision 1.1.1.1

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: 
                     40: #include <axl.h>
                     41: #define LOG_DOMAIN "axl-node"
                     42: 
                     43: /**
                     44:  * \defgroup axl_node_module Axl Node: Xml node interface functions to use and manipulate xml nodes inside documents.
                     45:  */
                     46: 
                     47: /** 
                     48:  * \addtogroup axl_node_module
                     49:  * @{
                     50:  */
                     51: 
                     52: struct _axlAttrCursor {
                     53:        axlPointer     data;
                     54:        int            count;
                     55:        axlNode      * node;
                     56: };
                     57: 
                     58: /** 
                     59:  * @internal Axl content representation used to store comments, xml
                     60:  * content, CDATA content and entity references.
                     61:  */
                     62: typedef struct _axlNodeContent axlNodeContent;
                     63: 
                     64: struct _axlNodeContent {
                     65:        /** 
                     66:         * @internal
                     67:         *
                     68:         * @brief Pointer which holds current content inside the xml
                     69:         * node.
                     70:         */
                     71:        char          * content;
                     72:        /** 
                     73:         * @internal
                     74:         *
                     75:         * @brief Current content size stored on the given axlNode.
                     76:         */
                     77:        int             content_size;
                     78:        
                     79: };
                     80: 
                     81: /** 
                     82:  * @internal Type representation to hold node attributes while they
                     83:  * are fewer.
                     84:  */
                     85: typedef struct _axlNodeAttr axlNodeAttr;
                     86: 
                     87: struct _axlNodeAttr {
                     88:        /** 
                     89:         * @internal Node attribute name.
                     90:         */
                     91:        char        * attribute;
                     92: 
                     93:        /** 
                     94:         * @internal Node attribute value.
                     95:         */
                     96:        char        * value;
                     97: 
                     98:        /** 
                     99:         * @internal Flags the attribute pair to be considered from a
                    100:         * factory.
                    101:         */
                    102:        axl_bool          from_factory;
                    103: 
                    104:        /** 
                    105:         * @internal Next attribute.
                    106:         */
                    107:        axlNodeAttr * next;
                    108: };
                    109: 
                    110: /** 
                    111:  * @internal Function that allows to copy all attributes found on the
                    112:  * list received.
                    113:  * 
                    114:  * @param list The attribute list to copy.
                    115:  * 
                    116:  * @return A newly allocated attribute list.
                    117:  */
                    118: axlNodeAttr * __axl_node_copy_attr_list (axlNodeAttr * list)
                    119: {
                    120:        axlNodeAttr * result   = NULL;
                    121: 
                    122:        /* if the list isn't defined, return NULL */
                    123:        if (list == NULL)
                    124:                return NULL;
                    125: 
                    126:        /* alloc memory to hold attribute name and value, and
                    127:         * copy it from the list */
                    128:        result             = axl_new (axlNodeAttr, 1);
                    129:        result->attribute  = axl_strdup (list->attribute);
                    130:        result->value      = axl_strdup (list->value);
                    131: 
                    132:        /* call to copy the rest of the list */
                    133:        result->next = __axl_node_copy_attr_list (list->next);
                    134: 
                    135:        /* return result created */
                    136:        return result;
                    137: }
                    138: 
                    139: /** 
                    140:  * @internal Deallocs the attribute list received.
                    141:  * 
                    142:  * @param list The attribute list to copy.
                    143:  * 
                    144:  * @return A newly allocated attribute list.
                    145:  */
                    146: void __axl_node_free_attr_list (axlNodeAttr * attr)
                    147: {
                    148:        axlNodeAttr * next;
                    149: 
                    150:        /* if the list isn't defined, return NULL */
                    151:        if (attr == NULL)
                    152:                return;
                    153: 
                    154:        /* copy all nodes */
                    155:        while (attr != NULL) {
                    156:                /* get the next attribute */
                    157:                next = attr->next;
                    158: 
                    159:                /* free attribute description */
                    160:                if (! attr->from_factory) {
                    161:                        axl_free (attr->attribute);
                    162:                        axl_free (attr->value);
                    163:                        axl_free (attr);
                    164:                } /* end if */
                    165: 
                    166:                /* get the next */
                    167:                attr = next;
                    168:                
                    169:        } /* end while */
                    170: 
                    171:        /* return result created */
                    172:        return;
                    173: }
                    174: 
                    175: /** 
                    176:  * @internal Function that allows to now if both lists represents the
                    177:  * same set of attributes, even if they aren't ordered using the same.
                    178:  * 
                    179:  * @param attr The first attribute pointing to the rest of the
                    180:  * attribute list.
                    181:  *
                    182:  * @param attr2 The second attribute pointing to the rest of the
                    183:  * attribute list.
                    184:  * 
                    185:  * @return \ref axl_true if both lists are equal, otherwise \ref axl_false is
                    186:  * returned.
                    187:  */
                    188: axl_bool __axl_node_attr_list_is_equal (axlNodeAttr * attr, axlNodeAttr * attr2)
                    189: {
                    190:        axlNodeAttr * attrAux;
                    191:        axl_bool      found;
                    192: 
                    193:        /* for each attribute found in the attribute list, check it on
                    194:         * the second list */
                    195:        while (attr != NULL) {
                    196:                
                    197:                attrAux = attr2;
                    198:                found   = axl_false;
                    199:                while (attrAux != NULL) {
                    200:                        
                    201:                        /* check attribute */
                    202:                        if (axl_cmp (attrAux->attribute, attr->attribute) &&
                    203:                            axl_cmp (attrAux->value, attr->value)) {
                    204:                                /* attribute found, break the loop */
                    205:                                found = axl_true;
                    206:                                break;
                    207:                        }
                    208: 
                    209:                        /* next attribute */
                    210:                        attrAux = attrAux->next;
                    211:                        
                    212:                } /* end while */
                    213:                
                    214:                /* check if the attribute was found */
                    215:                if (! found )
                    216:                        return axl_false;
                    217: 
                    218:                /* get the next */
                    219:                attr = attr->next;
                    220:                
                    221:        } /* end while */
                    222: 
                    223:        /* all attributes was found, including its values, so, the
                    224:         * list is equal */
                    225:        return axl_true;
                    226: }
                    227: 
                    228: typedef enum {
                    229:        /** 
                    230:         * @internal Signal axl library that the node was allocated by
                    231:         * a factory not by the system alloc.
                    232:         */
                    233:        NODE_FROM_FACTORY      = 1,
                    234: 
                    235:        /** 
                    236:         * @internal Signal axl library that the node node was
                    237:         * allocated by a factory not by the system alloc.
                    238:         */
                    239:        NODE_NAME_FROM_FACTORY = 1 << 2
                    240: } axlNodeConf;
                    241: 
                    242: struct _axlNode {
                    243:        /** 
                    244:         * @internal
                    245:         *
                    246:         * Node name that is the value found at the very begining of
                    247:         * the node definition <name.../>
                    248:         */
                    249:        char          * name;
                    250: 
                    251:        /** 
                    252:         * @internal Number of attributes stored. This value is used
                    253:         * to now if the attributes are stored using a hash or a
                    254:         * linked list. In the case it is equal or greater than 11, a
                    255:         * hash is used to store attribute. Otherwise, a linked list
                    256:         * (using axlAttrNode) is used.
                    257:         */
                    258:        int             attr_num;
                    259: 
                    260:        /** 
                    261:         * @internal
                    262:         * @brief The attributes this node has.
                    263:         */
                    264:        axlPointer    * attributes;
                    265: 
                    266:        /** 
                    267:         * @internal A reference to the first child.
                    268:         */
                    269:        axlItem      * first;
                    270: 
                    271:        /** 
                    272:         * @internal A reference to the last child.
                    273:         */
                    274:        axlItem      * last;
                    275: 
                    276:        /** 
                    277:         * @internal A hash used to store arbitrary data associated to
                    278:         * the node.
                    279:         */
                    280:        axlHash       * annotate_data; 
                    281: 
                    282:        /** 
                    283:         * @internal Internal reference to the holder axlItem
                    284:         * containing the axl node reference.
                    285:         */
                    286:        axlItem       * holder;
                    287:        
                    288:        /** 
                    289:         * @internal Value that contains flags for configuration.
                    290:         */
                    291:        int             conf;
                    292: };
                    293: 
                    294: struct _axlItem {
                    295:        /** 
                    296:         * @internal A reference to the type that is being hold by the
                    297:         * encapsulation reference.
                    298:         */
                    299:        AxlItemType     type;
                    300:        
                    301:        /** 
                    302:         * @internal The reference to the pointer that is actually
                    303:         * stored.
                    304:         */
                    305:        axlPointer      data;
                    306: 
                    307:        /** 
                    308:         * @internal
                    309:         * A pointer to the parent node.
                    310:         */
                    311:        axlNode       * parent;
                    312: 
                    313:        /** 
                    314:         * @internal
                    315:         *
                    316:         * A pointer to the brother node, the node that is found on
                    317:         * the next position.
                    318:         */
                    319:        axlItem       * next;
                    320: 
                    321:        /** 
                    322:         * @internal Stores a reference to the previous node inside
                    323:         * the same level.
                    324:         */
                    325:        axlItem       * previous;
                    326: 
                    327:        /** 
                    328:         * @internal
                    329:         *
                    330:         * Internal reference to the whole xml document where the node
                    331:         * is contained.
                    332:         */
                    333:        axlDoc        * doc;
                    334: };
                    335: 
                    336: /** 
                    337:  * @internal
                    338:  *
                    339:  * @brief Internal position function which ensures that nodes added
                    340:  * will be added at the end of the list.
                    341:  */
                    342: int __axl_node_equal (axlPointer a, axlPointer b)
                    343: {
                    344:        return 1;
                    345: }
                    346: 
                    347: /** 
                    348:  * @internal
                    349:  *
                    350:  * Internal function which allocates the enough memory to copy
                    351:  * received content changing all escape sequences.
                    352:  */
                    353: char * __axl_node_content_copy_and_escape (const char * content, 
                    354:                                           int          content_size, 
                    355:                                           int          additional_size,
                    356:                                           axl_bool     cdata)
                    357: {
                    358:        int    iterator  = 0;
                    359:        int    iterator2 = 0;
                    360:        char * result;
                    361:        axl_return_val_if_fail (content, NULL);
                    362: 
                    363:        /* allocate the memory to be returned */
                    364:        result = axl_new (char, content_size + additional_size + 1);
                    365: 
                    366:        /* iterate over all content defined */
                    367:        while (iterator2 < content_size) {
                    368:                /* check for &apos; */
                    369:                if (content [iterator2] == '\'') {
                    370:                        memcpy (result + iterator, "&apos;", 6);
                    371:                        iterator += 6;
                    372:                        iterator2++;
                    373:                        continue;
                    374:                }
                    375: 
                    376:                /* check for &quot; */
                    377:                if (content [iterator2] == '"') {
                    378:                        memcpy (result + iterator, "&quot;", 6);
                    379:                        iterator += 6;
                    380:                        iterator2++;
                    381:                        continue;
                    382:                }
                    383: 
                    384:                /* check for &amp; */
                    385:                if (content [iterator2] == '&') {
                    386:                        memcpy (result + iterator, "&amp;", 5);
                    387:                        iterator += 5;
                    388:                        iterator2++;
                    389:                        continue;
                    390:                }
                    391: 
                    392:                /* check for &gt; */
                    393:                if (content [iterator2] == '>') {
                    394:                        memcpy (result + iterator, "&gt;", 4);
                    395:                        iterator += 4;
                    396:                        iterator2++;
                    397:                        continue;
                    398:                }
                    399: 
                    400:                /* check for &lt; */
                    401:                if (content [iterator2] == '<') {
                    402:                        memcpy (result + iterator, "&lt;", 4);
                    403:                        iterator += 4;
                    404:                        iterator2++;
                    405:                        continue;
                    406:                }
                    407: 
                    408:                /* check for ]]> declaration */
                    409:                if (content [iterator2] == ']' && content [iterator2 + 1] == ']' && content [iterator2 + 2] == '>') {
                    410:                        if (cdata) {
                    411:                                memcpy (result + iterator, "]]>]]&gt;<![CDATA[", 18);
                    412:                                iterator  += 18;
                    413:                                iterator2 +=3;
                    414:                        } else {
                    415:                                memcpy (result + iterator, "]]&gt;", 6);
                    416:                                iterator  += 6;
                    417:                                iterator2 += 3;
                    418:                        }
                    419:                        continue;
                    420:                }
                    421: 
                    422:                /* copy value received because it is not an escape
                    423:                 * sequence */
                    424:                memcpy (result + iterator, content + iterator2, 1);
                    425: 
                    426:                /* update the iterator */
                    427:                iterator++;
                    428:                iterator2++;
                    429:        }
                    430: 
                    431:        /* return results */
                    432:        return result;
                    433: }
                    434: 
                    435: /** 
                    436:  * @brief Replaces all entity references to its corresponding
                    437:  * values. This function only implements translation for default
                    438:  * recognized entities (&, <, >, ' and ").
                    439:  *
                    440:  * @param content The string content having escaped XML declarations
                    441:  * such \&gt; or \&lt; which should be
                    442:  * translated into its corresponding utf-8 symbol (for example > and
                    443:  * <).
                    444:  *
                    445:  * @param content_size A non-optional reference to an integer variable
                    446:  * which will hold the new size of the string returned. You can pass a
                    447:  * variable initialized to 0 or -1 to let the function to calculate
                    448:  * the initial string length (by using strlen).
                    449:  *
                    450:  * Because the substitution pattern applied on this operation makes
                    451:  * not necessary to allocate memory, the function return the same
                    452:  * string received, but with all values replaced. If you want to avoid
                    453:  * this behaviour, use \ref axl_strdup before calling to this
                    454:  * function.
                    455:  *
                    456:  * @return Returns the string modified or NULL if it fails.
                    457:  */
                    458: char * axl_node_content_translate_defaults (char * content, 
                    459:                                            int  * content_size)
                    460: {
                    461:        int     iterator  = 0;
                    462:        int     iterator2 = 0;
                    463:        
                    464:        axl_return_val_if_fail (content, NULL);
                    465:        axl_return_val_if_fail (content_size, NULL);
                    466: 
                    467:        /* update string length if no data was provided */
                    468:        if (*content_size == 0 || *content_size == -1)
                    469:                *content_size = strlen (content);
                    470: 
                    471:        /* iterate over all content defined */
                    472:        while (iterator < (*content_size)) {
                    473:                
                    474:                /* check for &apos; */
                    475:                if (axl_stream_cmp (content + iterator, "&apos;", 6)) {
                    476:                        content [iterator2] = '\'';
                    477:                        iterator2++;
                    478:                        
                    479:                        iterator += 6;
                    480:                        continue;
                    481:                }
                    482:                
                    483:                /* check for &quot; */
                    484:                if (axl_stream_cmp (content + iterator, "&quot;", 6)) {
                    485:                        content [iterator2] = '"';
                    486:                        iterator2++;
                    487:                        
                    488:                        iterator += 6;
                    489:                        continue;
                    490:                }
                    491: 
                    492:                /* check for &amp; */
                    493:                if (axl_stream_cmp (content + iterator, "&amp;", 5)) {
                    494:                        content [iterator2] = '&';
                    495:                        iterator2++;
                    496:                        
                    497:                        iterator += 5;
                    498:                        continue;
                    499:                }
                    500: 
                    501:                /* check for &gt; */
                    502:                if (axl_stream_cmp (content + iterator, "&gt;", 4)) {
                    503:                        content [iterator2] = '>';
                    504:                        iterator2++;
                    505:                        
                    506:                        iterator += 4;
                    507:                        continue;
                    508:                }
                    509: 
                    510:                /* check for &lt; */
                    511:                if (axl_stream_cmp (content + iterator, "&lt;", 4)) {
                    512:                        content [iterator2] = '<';
                    513:                        iterator2++;
                    514:                        
                    515:                        iterator += 4;
                    516:                        continue;
                    517:                }
                    518: 
                    519:                /* copy move the content */
                    520:                if (iterator2 != iterator)
                    521:                        content [iterator2] = content [iterator];
                    522: 
                    523:                /* update the iterator */
                    524:                iterator++;
                    525:                iterator2++;
                    526:        }
                    527: 
                    528:        /* return results, setting the new content size */
                    529:        *content_size       = iterator2;
                    530:        content [iterator2] = 0;
                    531:        return content;
                    532: }
                    533: 
                    534: 
                    535: 
                    536: /** 
                    537:  * @brief Creates a new \ref axlNode with the provided name.
                    538:  *
                    539:  * The function will perform a new local copy from the name reference
                    540:  * received. See also \ref axl_node_create_ref for an explanation
                    541:  * about how to save memory.
                    542:  *
                    543:  * @param name The name to be used for the node be created. The
                    544:  * function doesn't check if the paramater received is null.
                    545:  * 
                    546:  * @return A newly allocated \ref axlNode reference, that must be
                    547:  * deallocated by \ref axl_node_free.
                    548:  */
                    549: axlNode * axl_node_create (const char * name)
                    550: {
                    551: 
                    552:        axlNode * node;
                    553: 
                    554:        /* init the node */
                    555:        node        = axl_new (axlNode, 1);
                    556:        node->name  = axl_strdup (name);
                    557:        
                    558:        return node;
                    559: }
                    560: 
                    561: /** 
                    562:  * @brief This function allows to create a xml node from the provided
                    563:  * xml content (bootstraping XML content).
                    564:  *
                    565:  * This function is useful if it is required to create a node with a
                    566:  * particular complex content, without going into the detail of
                    567:  * creating all childs, attributes and content.
                    568:  *
                    569:  * Here is an example:
                    570:  * \code
                    571:  * axlError * error = NULL;
                    572:  * axlNode  * node  = NULL;
                    573:  * 
                    574:  * // parse document 
                    575:  * root = axl_node_parse_strings (error, 
                    576:  *                                "<child>",
                    577:  *                                "  <widget class=\"GtkLabel\" id=\"label4\">",
                    578:  *                                "    <property name=\"visible\">True</property>",
                    579:  *                                "    <property name=\"label\" translatable=\"yes\">&lt;b&gt;1. Seleccione el sistema:&lt;/b&gt;</property>",
                    580:  *                                "    <property name=\"use_underline\">False</property>",
                    581:  *                                "    <property name=\"use_markup\">True</property>",
                    582:  *                                "    <property name=\"justify\">GTK_JUSTIFY_LEFT</property>",
                    583:  *                                "    <property name=\"wrap\">False</property>",
                    584:  *                                "    <property name=\"selectable\">False</property>",
                    585:  *                                "    <property name=\"xalign\">0</property>",
                    586:  *                                "    <property name=\"yalign\">0.5</property>",
                    587:  *                                "    <property name=\"xpad\">0</property>",
                    588:  *                                "    <property name=\"ypad\">0</property>",
                    589:  *                                "    <property name=\"ellipsize\">PANGO_ELLIPSIZE_NONE</property>",
                    590:  *                                "    <property name=\"width_chars\">-1</property>",
                    591:  *                                "    <property name=\"single_line_mode\">False</property>",
                    592:  *                                "    <property name=\"angle\">0</property>",
                    593:  *                                "  </widget>",
                    594:  *                                "  <packing>",
                    595:  *                                "     <property name=\"padding\">0</property>",
                    596:  *                                "     <property name=\"expand\">False</property>",
                    597:  *                                "     <property name=\"fill\">False</property>",
                    598:  *                                "  </packing>",
                    599:  *                                "</child>",
                    600:  *                                NULL);
                    601:  * if (root == NULL) {
                    602:  *     printf ("Error: unable to parse content, error: %s\n", axl_error_get (error));
                    603:  *              axl_error_free (error);
                    604:  *     return;
                    605:  * }
                    606:  *
                    607:  * // once finished, free the node 
                    608:  * axl_node_free (root);
                    609:  * \endcode
                    610:  * 
                    611:  * @param error Optional error reference to report parsing error
                    612:  * problems that can be found.
                    613:  * 
                    614:  * The function receives a set of strings, separate by comma, ended by
                    615:  * NULL.
                    616:  * 
                    617:  * @return A newly allocated reference to the \ref axlNode or NULL if
                    618:  * it fails. In such case, the error variable is filled with the error
                    619:  * found.
                    620:  */
                    621: axlNode * axl_node_parse_strings      (axlError ** error, ...)
                    622: {
                    623:        axlDoc   * doc;
                    624:        axlNode  * root;
                    625:        va_list    args;
                    626:        char     * string     = NULL;
                    627:        char     * stream     = NULL;
                    628:        char     * stream_aux = NULL;
                    629:        
                    630:        /* check incoming data */
                    631:        axl_return_val_if_fail (error, NULL);
                    632:        
                    633:        /* open the stdargs */
                    634:        va_start (args, error);
                    635:        
                    636:        while ((string = va_arg (args, char *)) != NULL) {
                    637:                stream_aux = stream;
                    638:                stream = axl_stream_concat (stream, string);
                    639:                if (stream_aux != NULL) {
                    640:                        axl_free (stream_aux);
                    641:                        stream_aux = NULL;
                    642:                }
                    643:        }
                    644: 
                    645:        /* close the stdargs */
                    646:        va_end (args);
                    647: 
                    648:        /* check that we have received, at least, an string
                    649:         * parseable */
                    650:        if (stream == NULL)
                    651:                return NULL;
                    652: 
                    653:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "string to parse: %s", stream);
                    654: 
                    655:        /* parse the string */
                    656:        doc = axl_doc_parse (stream, -1, error);
                    657:        if (doc == NULL) {
                    658:                /* free document */
                    659:                axl_free (stream);
                    660:                return NULL;
                    661:        }
                    662: 
                    663:        /* free the stream */
                    664:        axl_free (stream);
                    665: 
                    666:        /* deattach the root node */
                    667:        root = axl_doc_get_root (doc);
                    668:        axl_node_deattach (root);
                    669: 
                    670:        /* do not free the document, rather, store it to be
                    671:         * deallocated by the node just after it is deallocated. */
                    672:        axl_node_annotate_data_full (root, "__root_document", NULL, doc, (axlDestroyFunc) axl_doc_free);
                    673: 
                    674:        /* return the node created */
                    675:        return root;
                    676: }
                    677: 
                    678: /** 
                    679:  * @brief Allows to create a complete node configuring not only the
                    680:  * node but its content, using a printf-like format.
                    681:  *
                    682:  * This handy function, like \ref axl_node_parse_strings, allows to
                    683:  * create complex xml structures providing inline content.
                    684:  *
                    685:  * Here is an example:
                    686:  * \code
                    687:  * axlNode * node = axl_node_parse (NULL, "<content attr='value' attr2='value'>This is content</content>");
                    688:  * \endcode
                    689:  *
                    690:  * The previous call will create a node called <b>content</b> with the
                    691:  * provided attributes and content, in one step.
                    692:  *
                    693:  * The node returned can be integrated into a xml document using usual
                    694:  * API, for example: \ref axl_node_set_child or \ref axl_doc_set_root.
                    695:  * 
                    696:  * @param error The optional error reference holding the returned
                    697:  * result.
                    698:  *
                    699:  * @param content The content to be used to create the node.
                    700:  * 
                    701:  * @return A reference to a newly allocated \ref axlNode or NULL if it
                    702:  * fails. The \ref axlError is filled with the error found if provided
                    703:  * by the caller.
                    704:  */
                    705: axlNode * axl_node_parse                    (axlError ** error, const char * content, ...)
                    706: {
                    707:        char    * _content;
                    708:        va_list   args;
                    709:        axlDoc  * doc;
                    710:        axlNode * root;
                    711: 
                    712:        /* open the stdargs */
                    713:        va_start (args, content);
                    714:        
                    715:        /* create the content */
                    716:        _content = axl_strdup_printfv (content, args);
                    717: 
                    718:        /* close the stdargs */
                    719:        va_end (args);
                    720: 
                    721:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "parsing document:\n %s", _content);
                    722: 
                    723:        /* parse the string */
                    724:        doc = axl_doc_parse (_content, -1, error);
                    725:        if (doc == NULL) {
                    726:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "failed to parse document:\n %s", _content);
                    727: 
                    728:                /* free document */
                    729:                axl_free (_content);
                    730: 
                    731:                return NULL;
                    732:        }
                    733: 
                    734:        /* free the content */
                    735:        axl_free (_content);
                    736: 
                    737:        /* deattach the root node */
                    738:        root = axl_doc_get_root (doc);
                    739:        axl_node_deattach (root);
                    740: 
                    741:        /* do not free the document, rather, store it to be
                    742:         * deallocated by the node just after it is deallocated. */
                    743:        axl_node_annotate_data_full (root, "__root_document", NULL, doc, (axlDestroyFunc) axl_doc_free);
                    744: 
                    745:        /* return the node created */
                    746:        return root;
                    747: }
                    748: 
                    749: 
                    750: /** 
                    751:  * @brief Creates a new \ref axlNode but reusing the memory passed in
                    752:  * by the name reference.
                    753:  *
                    754:  * This function works the same way like \ref axl_node_create, but
                    755:  * previous one makes a local copy from the name provided. This means
                    756:  * that, if you have allocated the reference being passed, the
                    757:  * previous function will allocate again memory for the name
                    758:  * reference.
                    759:  *
                    760:  * Obviously, for a few xml nodes this have none or little effect but,
                    761:  * if your xml document have 100.000 nodes you save 100.000 extra
                    762:  * memory allocations and deallocations. This may improve your
                    763:  * application performace because memory
                    764:  * fragmentation/allocations/deallocations are reduced.
                    765:  *
                    766:  * Keep in mind that this function should not be used with static strings. Example:
                    767:  * \code
                    768:  *    // propery node creation 
                    769:  *    axlNode * node = axl_node_create ("test");
                    770:  *  
                    771:  *    // NOT PROPER node creation
                    772:  *    axlNode * node = axl_node_create_ref ("test");
                    773:  * \endcode
                    774:  *
                    775:  * @param name A user-space allocated memory representing the node
                    776:  * name. The function doesn't check if the parameter received is null.
                    777:  * 
                    778:  * @return A newly created \ref axlNode reference that must be
                    779:  * deallocated by \ref axl_node_free.
                    780:  */
                    781: axlNode * axl_node_create_ref         (char * name)
                    782: {
                    783:        axlNode * node;
                    784: 
                    785:        /* init the node */
                    786:        node        = axl_new (axlNode, 1);
                    787:        node->name  = name;
                    788:        
                    789:        /* return a reference to a new axlNode */
                    790:        return node;
                    791: }
                    792: 
                    793: /** 
                    794:  * @brief Allows to configure the node name, using the value provided. 
                    795:  * 
                    796:  * The function will dealloc the previous name stored, if found.
                    797:  *
                    798:  * @param node The node to be configured with a new name.
                    799:  * 
                    800:  * @param name The new name to configure on the node. Function will
                    801:  * create a local copy from the new name provided. The function won't
                    802:  * check the name parameter received to be a non-null pointer.
                    803:  */
                    804: void      axl_node_set_name                 (axlNode * node, const char * name)
                    805: {
                    806:        /* check the name to be already configured and dealloc it */
                    807:        if (node->name != NULL && ! (node->conf & NODE_NAME_FROM_FACTORY))
                    808:                axl_free (node->name);
                    809:        
                    810:        /* alloc the new name */
                    811:        node->name = axl_strdup (name);
                    812:        node->conf &= ~NODE_NAME_FROM_FACTORY;
                    813:        
                    814:        return;
                    815: }
                    816: 
                    817: /** 
                    818:  * @brief Allows to configure the node name, using the value provided
                    819:  * as a reference allocated and to be owned by the node.
                    820:  * 
                    821:  * The function will dealloc the previous name stored, if found.
                    822:  *
                    823:  * @param node The node to be configured with a new name.
                    824:  * 
                    825:  * @param name The new name to configure on the node. The value
                    826:  * provided will be owned by the node. The function won't check the
                    827:  * name parameter received to be a non-null pointer.
                    828:  */
                    829: void      axl_node_set_name_ref             (axlNode * node, char * name)
                    830: {
                    831:        /* check the name to be already configured and dealloc it */
                    832:        if (node->name != NULL && ! (node->conf & NODE_NAME_FROM_FACTORY))
                    833:                axl_free (node->name);
                    834: 
                    835:        /* alloc the new name */
                    836:        node->name = name;
                    837:        
                    838:        return;
                    839: }
                    840: 
                    841: /** 
                    842:  * @internal Allows to configure the xml node, flaging the string
                    843:  * received to be owned by a factory. Do not use this API from your
                    844:  * application. This is only useful for Axl Library internals.
                    845:  * 
                    846:  * @param node The xml node that is going to be configured.
                    847:  *
                    848:  * @param name The xml node name to be configured. Previous
                    849:  * configuration won't be deallocated as it is supposed that this
                    850:  * function is only used from inside axl library.
                    851:  */
                    852: void axl_node_set_name_from_factory (axlNode * node, char * name)
                    853: {
                    854:        /* set node name */
                    855:        node->name = name;
                    856: 
                    857:        /* update configuration */
                    858:        node->conf |= NODE_NAME_FROM_FACTORY;
                    859:        
                    860:        return;
                    861: }
                    862: 
                    863: axlPointer __axl_node_copy_key (axlPointer key, axlDestroyFunc key_destroy, 
                    864:                                axlPointer data, axlDestroyFunc data_destroy)
                    865: {
                    866:        /* copy the key */
                    867:        return axl_strdup (key);
                    868: }
                    869: 
                    870: axlPointer __axl_node_copy_value (axlPointer key, axlDestroyFunc key_destroy,
                    871:                                  axlPointer data, axlDestroyFunc data_destroy)
                    872: {
                    873:        /* copy data */
                    874:        return axl_strdup (data);
                    875: }
                    876: 
                    877: /** 
                    878:  * @brief Allows to perform a copy operation for the provided node.
                    879:  *
                    880:  * @param node The source node to copy.
                    881:  *
                    882:  * @param copy_attributes Signals the function to also copy node
                    883:  * attributes into the newly created node.
                    884:  *
                    885:  * @param copy_childs Signals the function to also copy childs for the
                    886:  * source node.
                    887:  * 
                    888:  * @return A newly created node copy or null if it fails. The function
                    889:  * will fail if the node reference provided is null.
                    890:  */
                    891: axlNode * axl_node_copy                     (axlNode   * node,
                    892:                                             axl_bool    copy_attributes,
                    893:                                             axl_bool    copy_childs)
                    894: {
                    895:        axlNode * result;
                    896:        axlItem * child;
                    897:        axlItem * copy;
                    898:        
                    899: 
                    900:        axl_return_val_if_fail (node, NULL);
                    901: 
                    902:        /* create the copy */
                    903:        result = axl_node_create (axl_node_get_name (node));
                    904: 
                    905:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "node=<%s> (copy operation)",
                    906:                   result->name);
                    907: 
                    908:        /* check for attributes */
                    909:        if (node->attributes != NULL && copy_attributes) {
                    910:                
                    911:                /* copy attribute configuration and attributes */
                    912:                result->attr_num = node->attr_num;
                    913:                if (node->attr_num >= 11) {
                    914:                        /* copy attribute list supposing it is a
                    915:                         * hash */
                    916:                        result->attributes = (axlPointer) axl_hash_copy ((axlHash *) node->attributes, 
                    917:                                                                         /* key copy function */
                    918:                                                                         __axl_node_copy_key,
                    919:                                                                         /* value copy function */
                    920:                                                                         __axl_node_copy_value);
                    921:                } else {
                    922:                        /* copy attribute list */
                    923:                        result->attributes = (axlPointer) __axl_node_copy_attr_list ((axlNodeAttr *) node->attributes);
                    924:                }
                    925:        }
                    926: 
                    927:        /* check if child nodes must be also copied */
                    928:        if (copy_childs && (node->first != NULL)) {
                    929: 
                    930:                /* copy all content inside */
                    931:                child = node->first;
                    932:                while (child != NULL) {
                    933:                        
                    934:                        /* copy the child found */
                    935:                        copy       = axl_item_copy (child, result);
                    936:                        
                    937:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "  new item created (copy operation) with parent=<%s> and type=%d",
                    938:                                   copy->parent->name,
                    939:                                   axl_item_get_type (copy));
                    940: 
                    941:                        /* set the content */
                    942:                        axl_item_set_child_ref (result, copy);
                    943: 
                    944:                        /* get the next element */
                    945:                        child = child->next;
                    946: 
                    947:                } /* end while */
                    948:        } /* end if */
                    949:        
                    950:        
                    951:        /* return the node created */
                    952:        return result;
                    953: }
                    954: 
                    955: /** 
                    956:  * @brief Allows to get the xml document (\ref axlDoc) where the
                    957:  * provided xml node is stored.
                    958:  * 
                    959:  * @param node The node that is being requested to return is xml
                    960:  * document reference.
                    961:  * 
                    962:  * @return The xml document reference or NULL if it is not already
                    963:  * set. 
                    964:  */
                    965: axlDoc  * axl_node_get_doc                  (axlNode * node)
                    966: {
                    967:        axl_return_val_if_fail (node, NULL);
                    968:        
                    969:        /* return the internal reference */
                    970:        return axl_item_get_doc (node->holder);
                    971: }
                    972: 
                    973: /** 
                    974:  * @internal
                    975:  *
                    976:  * This function is not provided to the public API because it is used
                    977:  * by the Axl internals to set the root node for a provided xml node,
                    978:  * that is usually the root document xml node.
                    979:  * 
                    980:  * @param node The node that is being configured to have, or being contained in, the provided xml document.
                    981:  *
                    982:  * @param doc The xml document that holds the node.
                    983:  */
                    984: void      axl_node_set_doc                  (axlNode * node, axlDoc * doc)
                    985: {
                    986:        axlItem * item;
                    987: 
                    988:        axl_return_if_fail (node);
                    989:        axl_return_if_fail (doc);
                    990: 
                    991:        /* get the item reference */
                    992:        item = node->holder;
                    993: 
                    994:        if (item == NULL) {
                    995: 
                    996:                /* create an empty reference */
                    997:                item         = axl_item_factory_get (axl_doc_get_item_factory (doc)); 
                    998:                item->type   = ITEM_NODE | ITEM_FROM_FACTORY;
                    999:                item->data   = node;
                   1000:                node->holder = item;
                   1001:                
                   1002:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "node received doesn't have a holder reference, creating ref=0x%x, node=0x%x, type=%d",
                   1003:                           item, node, item->type);
                   1004:        } /* end if */
                   1005: 
                   1006:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "setting doc to the item node");
                   1007: 
                   1008:        /* call to set item at the document */
                   1009:        item->doc = doc;
                   1010: 
                   1011:        return;
                   1012: }
                   1013: 
                   1014: 
                   1015: /** 
                   1016:  * @internal
                   1017:  * 
                   1018:  * Support function to install attribute information provided into the
                   1019:  * \ref axlNode provided.
                   1020:  *
                   1021:  * @return axl_true if the attribute was added, otherwise axl_false is
                   1022:  * returned.
                   1023:  */
                   1024: axl_bool      __axl_node_set_attribute      (axlFactory * factory, 
                   1025:                                             axlNode    * node, 
                   1026:                                             char       * attribute, 
                   1027:                                             char       * value, 
                   1028:                                             axl_bool     from_factory)
                   1029: {
                   1030:        axlNodeAttr * attr;
                   1031:        axlNodeAttr * next;
                   1032: 
                   1033:        /* init attribute list */
                   1034:        /* do not init attribute list twice */
                   1035:        if (node->attributes == NULL) {
                   1036:                /* configure default axl attribute list */
                   1037:                node->attr_num   = 1;
                   1038:                
                   1039:                /* create the node */
                   1040:                if (from_factory)
                   1041:                        attr = axl_factory_get (factory);
                   1042:                else
                   1043:                        attr = axl_new (axlNodeAttr, 1);
                   1044:                attr->from_factory = from_factory;
                   1045:                attr->attribute    = attribute;
                   1046:                attr->value        = value;
                   1047:                
                   1048:                /* store the node */
                   1049:                node->attributes = (axlPointer) attr;
                   1050: 
                   1051:                return axl_true;
                   1052:        }
                   1053: 
                   1054:        /* store the attribute using the general case */
                   1055:        if (node->attr_num < 10) {
                   1056: 
                   1057:                /* check if the attribute exists */
                   1058:                if (axl_node_has_attribute (node, attribute))
                   1059:                        return axl_false;
                   1060: 
                   1061:                /* create the node */
                   1062:                if (from_factory)
                   1063:                        attr = axl_factory_get (factory);
                   1064:                else
                   1065:                        attr = axl_new (axlNodeAttr, 1);
                   1066:                attr->from_factory = from_factory;
                   1067:                attr->attribute    = attribute;
                   1068:                attr->value        = value;
                   1069: 
                   1070:                /* set the next to the new item to be the current first */
                   1071:                attr->next       = (axlNodeAttr *) node->attributes;
                   1072: 
                   1073:                /* set the new first */
                   1074:                node->attributes = (axlPointer) attr;
                   1075:                
                   1076:        } else if (node->attr_num >= 10) {
                   1077: 
                   1078:                /* check if the attribute exists */
                   1079:                if (axl_node_has_attribute (node, attribute))
                   1080:                        return axl_false;
                   1081:                
                   1082:                /* check if we have to translate current attributes */
                   1083:                if (node->attr_num == 10) {
                   1084:                        /* get a reference to current attribute list */
                   1085:                        attr = (axlNodeAttr *) node->attributes;
                   1086: 
                   1087:                        /* create the hash */
                   1088:                        node->attributes = (axlPointer) axl_hash_new_full (axl_hash_string, axl_hash_equal_string, 1);
                   1089:                        
                   1090:                        while (attr != NULL) {
                   1091:                                /* add the attribute */ 
                   1092:                                axl_hash_insert_full ((axlHash *) node->attributes, 
                   1093:                                                      /* attribute name */
                   1094:                                                      attr->attribute, attr->from_factory ?  NULL : axl_free, 
                   1095:                                                      /* attribute value */
                   1096:                                                      attr->value, attr->from_factory ? NULL : axl_free);
                   1097:                                /* free current node */
                   1098:                                next = attr->next;
                   1099:                                if (! attr->from_factory)
                   1100:                                        axl_free (attr);
                   1101: 
                   1102:                                /* get the next item to store */
                   1103:                                attr = next;
                   1104:                        } /* end while */
                   1105: 
                   1106:                } /* end if */
                   1107: 
                   1108:                /* add the attribute */ 
                   1109:                axl_hash_insert_full ((axlHash *) node->attributes, 
                   1110:                                      attribute, from_factory ? NULL : axl_free, 
                   1111:                                      value, from_factory ? NULL : axl_free);                           
                   1112:                
                   1113:        } /* end if */
                   1114: 
                   1115:        /* update attribute count */
                   1116:        node->attr_num++;
                   1117: 
                   1118:        return axl_true;
                   1119: }
                   1120: 
                   1121: /** 
                   1122:  * @brief Allows to configure an xml attribute on the given node.
                   1123:  *
                   1124:  * \code
                   1125:  * <complex attr1='value'>
                   1126:  *   ..
                   1127:  * </complex>
                   1128:  * \endcode
                   1129:  *
                   1130:  * It is not allowed to store the same attribute twice inside the same
                   1131:  * node. If the function detects that a node is being set to have the
                   1132:  * same attribute name several times, the attribute will be silently
                   1133:  * not added.
                   1134:  *
                   1135:  * Values for the attribute name (<b>attribute</b>) and its associated
                   1136:  * value can be deallocated once the function finish. This function
                   1137:  * will perform a local copy.
                   1138:  * 
                   1139:  * @param node The \ref axlNode where the attribute will be installed.
                   1140:  *
                   1141:  * @param attribute The attribute name to configure. This value can't
                   1142:  * be NULL.
                   1143:  *
                   1144:  * @param value The value associated to the attribute to be
                   1145:  * configured. This value can't be NULL.
                   1146:  */
                   1147: void      axl_node_set_attribute      (axlNode    * node, 
                   1148:                                       const char * attribute, 
                   1149:                                       const char * value)
                   1150: {
                   1151:        int    additional_size = 0;
                   1152:        char * _attr;
                   1153:        char * _value;
                   1154: 
                   1155:        axl_return_if_fail (node);
                   1156:        axl_return_if_fail (attribute);
                   1157:        axl_return_if_fail (value);
                   1158: 
                   1159:        /* check for empty attribute names */
                   1160:        if (attribute[0] == 0) {
                   1161:                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "skipping setting attribute with no name!");
                   1162:                return;
                   1163:        }
                   1164: 
                   1165:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "setting attribute: %s='%s'", attribute, value);
                   1166: 
                   1167:        /* check attribute name */
                   1168:        if (axl_node_has_invalid_chars (attribute, strlen (attribute),
                   1169:                                        &additional_size)) {
                   1170: 
                   1171:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found attribute content with escapable, non-valid content");
                   1172:                _attr = __axl_node_content_copy_and_escape (attribute, 
                   1173:                                                            strlen (attribute),
                   1174:                                                            additional_size,
                   1175:                                                            axl_false);
                   1176:        }else {
                   1177: 
                   1178:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "'%s' is a valid string..", attribute);
                   1179:                _attr = axl_strdup (attribute);
                   1180:        }
                   1181: 
                   1182:        /* check attribute value */
                   1183:        additional_size = 0;
                   1184:        if (axl_node_has_invalid_chars (value, strlen (value),
                   1185:                                        &additional_size)) {
                   1186: 
                   1187:                _value = __axl_node_content_copy_and_escape (value, 
                   1188:                                                             strlen (value),
                   1189:                                                             additional_size,
                   1190:                                                             axl_false);
                   1191:        }else {
                   1192:                
                   1193:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "'%s' is a valid string..", value);
                   1194:                _value = axl_strdup (value);
                   1195:        }
                   1196: 
                   1197:        /* insert the attribute */
                   1198:        if (! __axl_node_set_attribute (NULL, node, _attr, _value, axl_false)) {
                   1199:                axl_free (_attr);
                   1200:                axl_free (_value);
                   1201:        } /* end if */
                   1202:        
                   1203:        return;
                   1204: }
                   1205: 
                   1206: /** 
                   1207:  * @brief Allows to install a new attribute pair, based on the
                   1208:  * attribute name and the attribute value, without allocating memory
                   1209:  * for them.
                   1210:  * 
                   1211:  * This function works the same way like \ref axl_node_set_attribute
                   1212:  * but reusing memory allocated by the user space.
                   1213:  * 
                   1214:  * @param node The \ref axlNode where the attributes will be
                   1215:  * installed.
                   1216:  *
                   1217:  * @param attribute The attribute name to be installed.
                   1218:  *
                   1219:  * @param value The attribute value to be installed.
                   1220:  */
                   1221: void      axl_node_set_attribute_ref  (axlNode * node, char * attribute, char * value)
                   1222: {
                   1223: 
                   1224:        axl_return_if_fail (node);
                   1225:        axl_return_if_fail (attribute);
                   1226:        axl_return_if_fail (value);
                   1227: 
                   1228:        /* insert the attribute */
                   1229:        if (! __axl_node_set_attribute (NULL, node, attribute, value, axl_false)) {
                   1230:                axl_free (attribute);
                   1231:                axl_free (value);
                   1232:                return;
                   1233:        } /* end if */
                   1234: 
                   1235:        return;
                   1236: }
                   1237: 
                   1238: /** 
                   1239:  * @internal Function that allows configuring attributes to the
                   1240:  * selected node, notifying that they come from a factory and
                   1241:  * shouldn't be deallocated in the usual way. This function shouldn't
                   1242:  * be used by API consumers. This is only useful for Axl Library
                   1243:  * internals.
                   1244:  * 
                   1245:  * @param node The node to be configured with the attribute values.
                   1246:  *
                   1247:  * @param attribute The attribute to configure.
                   1248:  * @param value The attribute value to configure.
                   1249:  */
                   1250: void      axl_node_set_attribute_from_factory  (axlFactory * factory, 
                   1251:                                                axlNode    * node, 
                   1252:                                                char       * attribute, 
                   1253:                                                char       * value)
                   1254: {
                   1255:        /* insert the attribute */
                   1256:        __axl_node_set_attribute (factory, node, attribute, value, axl_true);
                   1257: 
                   1258:        return;
                   1259: }
                   1260: 
                   1261: /** 
                   1262:  * @brief Allows to check if a particular attribute is installed on
                   1263:  * the given node.
                   1264:  *
                   1265:  * @param node The node where the attribute will be checked to be
                   1266:  * configured.
                   1267:  *
                   1268:  * @param attribute The attribute to check.
                   1269:  * 
                   1270:  * @return A \ref axl_true if the attribute value is set, otherwise
                   1271:  * \ref axl_false is returned.
                   1272:  *
                   1273:  * See also \ref HAS_ATTR.
                   1274:  */
                   1275: axl_bool          axl_node_has_attribute      (axlNode * node, const char * attribute)
                   1276: {
                   1277:        axlNodeAttr * attr;
                   1278: 
                   1279:        axl_return_val_if_fail (node,      axl_false);
                   1280:        axl_return_val_if_fail (attribute, axl_false);
                   1281: 
                   1282:        /* check for empty hash */
                   1283:        if (node->attributes == NULL)
                   1284:                return axl_false;
                   1285: 
                   1286:        if (node->attr_num <= 10) {
                   1287:                /* linked configuration */
                   1288:                attr = (axlNodeAttr *) node->attributes;
                   1289:                while (attr != NULL) {
                   1290:                        /* check that the attribute is equal */
                   1291:                        if (axl_cmp (attr->attribute, attribute))
                   1292:                                return axl_true;
                   1293: 
                   1294:                        /* get the next attribute */
                   1295:                        attr = attr->next;
                   1296:                } /* end while */
                   1297: 
                   1298:                /* attribute not found */
                   1299:                return axl_false;
                   1300:        } /* end if */
                   1301: 
                   1302:        /* hashed configuration */
                   1303:        return axl_hash_exists ((axlHash *) node->attributes, (axlPointer) attribute);
                   1304: }
                   1305: 
                   1306: /** 
                   1307:  * @brief Allows to remove the provided attribute, from the node
                   1308:  * provided.
                   1309:  * 
                   1310:  * @param node The node to be updated by removing the attribute
                   1311:  * provided.
                   1312:  *
                   1313:  * @param attribute The attribute to locate and remove.
                   1314:  */
                   1315: void      axl_node_remove_attribute         (axlNode    * node,
                   1316:                                             const char * attribute)
                   1317: {
                   1318:        axlNodeAttr * attr;
                   1319:        axlNodeAttr * previous;
                   1320: 
                   1321:        axl_return_if_fail (node);
                   1322:        axl_return_if_fail (attribute);
                   1323: 
                   1324:        /* check for empty hash */
                   1325:        if (node->attributes == NULL)
                   1326:                return;
                   1327: 
                   1328:        if (node->attr_num <= 10) {
                   1329:                /* linked configuration */
                   1330:                attr     = (axlNodeAttr *) node->attributes;
                   1331:                previous = NULL;
                   1332:                while (attr != NULL) {
                   1333:                        /* check that the attribute is equal */
                   1334:                        if (axl_cmp (attr->attribute, attribute)) {
                   1335:                                /* attribute found */
                   1336:                                if (previous == NULL)
                   1337:                                        node->attributes = (axlPointer) attr->next;
                   1338:                                else
                   1339:                                        previous->next = attr->next;
                   1340: 
                   1341:                                /* do not decrease attribute number
                   1342:                                 * since it is used to know the kind
                   1343:                                 * of store used. */
                   1344: 
                   1345:                                /* now dealloc the attribute */
                   1346:                                if (! attr->from_factory) {
                   1347:                                        axl_free (attr->attribute);
                   1348:                                        axl_free (attr->value);
                   1349:                                        axl_free (attr);
                   1350:                                } /* end if */
                   1351:                                
                   1352:                                return;
                   1353:                        }
                   1354: 
                   1355:                        /* get the next attribute */
                   1356:                        previous = attr;
                   1357:                        attr     = attr->next;
                   1358:                } /* end while */
                   1359: 
                   1360:                /* attribute not found */
                   1361:                return;
                   1362:        } /* end if */
                   1363: 
                   1364:        /* hashed configuration */
                   1365:        axl_hash_remove ((axlHash *) node->attributes, (axlPointer) attribute);
                   1366: 
                   1367:        /* do not decrease attribute number
                   1368:         * since it is used to know the kind
                   1369:         * of store used. */
                   1370:        
                   1371:        return;
                   1372: }
                   1373: 
                   1374: /** 
                   1375:  * @brief Allows to get the number of attributes installed on the
                   1376:  * provided node.
                   1377:  * 
                   1378:  * @param node The node that is requested to return the number of
                   1379:  * attributes installed.
                   1380:  * 
                   1381:  * @return Number of attributes installed, or -1 if it fails.
                   1382:  */
                   1383: int       axl_node_num_attributes           (axlNode    * node)
                   1384: {
                   1385:        int           result = 0;
                   1386:        axlNodeAttr * attr;
                   1387: 
                   1388:        axl_return_val_if_fail (node, -1);
                   1389: 
                   1390:        if (node->attr_num <= 10) {
                   1391:                /* linked configuration */
                   1392:                attr     = (axlNodeAttr *) node->attributes;
                   1393:                while (attr != NULL) {
                   1394:                        /* update sum */
                   1395:                        result++;
                   1396: 
                   1397:                        /* get the next attribute */
                   1398:                        attr     = attr->next;
                   1399:                } /* end while */
                   1400: 
                   1401:                /* attribute not found */
                   1402:                return result;
                   1403:        } /* end if */
                   1404: 
                   1405:        /* hashed configuration */
                   1406:        return axl_hash_items ((axlHash *) node->attributes);
                   1407: }
                   1408: 
                   1409: /** 
                   1410:  * @brief Allows to check if the provided node has attributes
                   1411:  * installed.
                   1412:  * 
                   1413:  * @param node The node to be checked for attributes.
                   1414:  * 
                   1415:  * @return \ref axl_true if the node has attributes, otherwise \ref axl_false
                   1416:  * is returned. The function also returns \ref axl_false if a null
                   1417:  * reference for the node is provided.
                   1418:  */
                   1419: axl_bool      axl_node_has_attributes (axlNode * node)
                   1420: {
                   1421:        axl_return_val_if_fail (node, axl_false);
                   1422: 
                   1423:        /* return if the attributes reference is configured */
                   1424:        return (node->attributes != NULL);
                   1425: }
                   1426: 
                   1427: /** 
                   1428:  * @brief Allows to get current content of the provided attribute
                   1429:  * inside the given node.
                   1430:  *
                   1431:  * It is recomended to call first to \ref axl_node_has_attribute to
                   1432:  * ensure that the attribute to be reported its value already
                   1433:  * exists. See also \ref ATTR_VALUE.
                   1434:  *
                   1435:  * @param node The \ref axlNode where the attribute value associated
                   1436:  * will be returned.
                   1437:  *
                   1438:  * @param attribute The attribute that is being required for its
                   1439:  * value.
                   1440:  * 
                   1441:  * @return A string containing the attribute value or NULL if
                   1442:  * fails. Returned value must not be deallocated, it is a reference to
                   1443:  * a local copy. Use \ref axl_strdup function to get a persistent
                   1444:  * copy.
                   1445:  */
                   1446: const char    * axl_node_get_attribute_value (axlNode * node, const char * attribute)
                   1447: {
                   1448:        axlNodeAttr * attr;
                   1449: 
                   1450:        /* check values received */
                   1451:        axl_return_val_if_fail (node, NULL);
                   1452:        axl_return_val_if_fail (attribute, NULL);
                   1453: 
                   1454:        /* check for empty hash */
                   1455:        if (node->attributes == NULL)
                   1456:                return NULL;
                   1457: 
                   1458:        if (node->attr_num <= 10) {
                   1459:                /* linked configuration */
                   1460:                attr = (axlNodeAttr *) node->attributes;
                   1461:                while (attr != NULL) {
                   1462:                        /* check that the attribute is equal */
                   1463:                        if (axl_cmp (attr->attribute, attribute))
                   1464:                                return attr->value;
                   1465: 
                   1466:                        /* get the next attribute */
                   1467:                        attr = attr->next;
                   1468:                } /* end while */
                   1469:                
                   1470:                /* attribute not found */
                   1471:                return NULL;
                   1472:        } /* end if */
                   1473: 
                   1474:        /* return value stored for the provided key */
                   1475:        return axl_hash_get ((axlHash *) node->attributes, (axlPointer) attribute);
                   1476: }
                   1477: 
                   1478: /** 
                   1479:  * @brief Gets an allocated copy for the value associated to the given
                   1480:  * attribute.
                   1481:  *
                   1482:  * See \ref axl_node_get_attribute_value for more information. This
                   1483:  * function works the same way but returning an already allocated
                   1484:  * attribute value.
                   1485:  * 
                   1486:  * @param node The node where the attribute value is requested.
                   1487:  *
                   1488:  * @param attribute The attribute that is being requested.
                   1489:  * 
                   1490:  * @return A newly allocated reference that must be deallocated when
                   1491:  * no longer needed calling to \ref axl_free.
                   1492:  */
                   1493: char    * axl_node_get_attribute_value_copy (axlNode    * node, 
                   1494:                                             const char * attribute)
                   1495: {
                   1496:        const char * _value;
                   1497: 
                   1498:        /* get the attribute */
                   1499:        _value = axl_node_get_attribute_value (node, attribute);
                   1500:        axl_return_val_if_fail (_value, NULL);
                   1501:        
                   1502:        /* return a copy */
                   1503:        return axl_strdup (_value);
                   1504: }
                   1505: 
                   1506: /** 
                   1507:  * @brief Gets the attribute content for the provided attribute name,
                   1508:  * at the provided node, but translating entity references found.
                   1509:  *
                   1510:  * This function works the same way like \ref
                   1511:  * axl_node_get_attribute_value_copy, in the sense it returns a
                   1512:  * dinamically allocated copy for the attribute value requested but,
                   1513:  * at the same time, it returns the content with all entity references
                   1514:  * already translated.
                   1515:  *
                   1516:  * @param node The \ref axlNode instance where the attribute content
                   1517:  * will be returned.
                   1518:  *
                   1519:  * @param attribute The attribute name that is being requested.
                   1520:  * 
                   1521:  * @return The attribute content, already translated, for those
                   1522:  * entities found. The function returns a dinamilly allocated string
                   1523:  * so \ref axl_free must be used.
                   1524:  */
                   1525: char    * axl_node_get_attribute_value_trans (axlNode    * node, 
                   1526:                                              const char * attribute)
                   1527: {
                   1528:        char * _value;
                   1529:        int    size;
                   1530: 
                   1531:        /* get the attribute */
                   1532:        _value = (char *) axl_node_get_attribute_value (node, attribute);
                   1533:        axl_return_val_if_fail (_value, NULL);
                   1534: 
                   1535:        /* perform a local copy */
                   1536:        _value = axl_strdup (_value);
                   1537:        
                   1538:        /* return a copy */
                   1539:        size   = strlen (_value);
                   1540:        return axl_node_content_translate_defaults (_value, &size);
                   1541: }
                   1542: 
                   1543: /** 
                   1544:  * @brief Allows to get the value associated to the attribute
                   1545:  * provided, inside the node selected, removing trailing and ending
                   1546:  * white spaces (in the W3C sence: \\n, \\t, \\r, ' ').
                   1547:  *
                   1548:  * See \ref ATTR_VALUE_TRIMMED for a convenience macro.
                   1549:  * 
                   1550:  * @param node The node that is requested to return the associated 
                   1551:  * value to the attribute.
                   1552:  *
                   1553:  * @param attribute The attribute that is being requested.
                   1554:  * 
                   1555:  * @return A reference to the attribute value or NULL if it fails. The
                   1556:  * function doesn't return a copy, it returns a reference to the
                   1557:  * internal value.
                   1558:  */
                   1559: const char    * axl_node_get_attribute_value_trimmed (axlNode    * node,
                   1560:                                                      const char * attribute)
                   1561: {
                   1562:        char * _value;
                   1563: 
                   1564:        /* get the attribute */
                   1565:        _value = (char *) axl_node_get_attribute_value (node, attribute);
                   1566:        axl_return_val_if_fail (_value, NULL);
                   1567: 
                   1568:        /* trim the value */
                   1569:        axl_stream_trim (_value);
                   1570: 
                   1571:        /* return value */
                   1572:        return _value;
                   1573: }
                   1574: 
                   1575: /** 
                   1576:  * @brief Convenience function that allows to check if a particular
                   1577:  * attribute with a particular value is found at the provided node.
                   1578:  *
                   1579:  * This function will check if the attribute provided in the node is
                   1580:  * found and in such case, if the value that is contained inside the
                   1581:  * node is actually the same as the one provide to this function.
                   1582:  *
                   1583:  * You can also use hits macro associated: \ref HAS_ATTR_VALUE.
                   1584:  * 
                   1585:  * @param node The node that will be checked.
                   1586:  * @param attribute The attribute to be checked.
                   1587:  * @param value The value to checked if the attribute is found.
                   1588:  * 
                   1589:  * @return \ref axl_true if the node has the attribute with the
                   1590:  * provided value.
                   1591:  */
                   1592: axl_bool axl_node_has_attribute_value       (axlNode    * node, 
                   1593:                                             const char * attribute, 
                   1594:                                             const char * value)
                   1595: {
                   1596:        axl_return_val_if_fail (node,      axl_false);
                   1597:        axl_return_val_if_fail (attribute, axl_false);
                   1598:        axl_return_val_if_fail (value,     axl_false);
                   1599: 
                   1600:        /* return if the attribute value found is the same */
                   1601:        return axl_cmp (axl_node_get_attribute_value (node, attribute), value);
                   1602: }
                   1603: 
                   1604: /**
                   1605:  * @}
                   1606:  */
                   1607: 
                   1608: /**
                   1609:  * \defgroup axl_node_annotate Axl Node Annotate: An interface that allows associate arbitrary data to a particular node, indexed as a hash.
                   1610:  */
                   1611: 
                   1612: /** 
                   1613:  * \addtogroup axl_node_annotate
                   1614:  * @{
                   1615:  */
                   1616: 
                   1617: /** 
                   1618:  * @internal function which checks and initializes the hash used for
                   1619:  * annotated data.
                   1620:  */
                   1621: void __init_node_annotation (axlNode * node)
                   1622: {
                   1623:        if (node->annotate_data == NULL)
                   1624:                node->annotate_data =  axl_hash_new (axl_hash_string, axl_hash_equal_string);
                   1625:        return;
                   1626: }
                   1627: 
                   1628: /** 
                   1629:  * @brief Allows to store user defined data associated to the node
                   1630:  * that is not visible from an XML perspective.
                   1631:  *
                   1632:  * This function allows to store data associated to the node and to
                   1633:  * retrieve it later in an inherited fashion. This allows to store
                   1634:  * semantic/metadata information while parsing xml documents.
                   1635:  *
                   1636:  * This function stores the given key using a hash,
                   1637:  * associating the data provided on the given node. You can also check
                   1638:  * the \ref axl_node_annotate_data_full which performs the same task
                   1639:  * but allowing to provide key and data destroy functions.
                   1640:  *
                   1641:  * Once data is stored, it could be inherited by child nodes because
                   1642:  * the access to it is done using \ref axl_node_annotate_get which can
                   1643:  * configure the data lookup to into the particular node or its
                   1644:  * parents.
                   1645:  *
                   1646:  * Additionally, you can also perform annotation using native types:
                   1647:  * int, string and double. Check the following functions to do so.
                   1648:  *
                   1649:  * - \ref axl_node_annotate_int
                   1650:  * - \ref axl_node_annotate_double
                   1651:  * - \ref axl_node_annotate_string
                   1652:  *
                   1653:  * @param node The node where the annotated data will be stored.
                   1654:  *
                   1655:  * @param key The key under which the annotated data will be stored
                   1656:  * (and indexed).
                   1657:  *
                   1658:  * @param data The data to be stored associated to the key provided.
                   1659:  */
                   1660: void      axl_node_annotate_data                 (axlNode     * node, 
                   1661:                                                 const char    * key,
                   1662:                                                 axlPointer    data)
                   1663: {
                   1664:        axl_return_if_fail (node);
                   1665: 
                   1666:        /* check and init node annotation */
                   1667:        __init_node_annotation (node);
                   1668:        
                   1669:        /* insert data */
                   1670:        axl_hash_insert (node->annotate_data, (axlPointer) key, data);
                   1671: 
                   1672:        /* nothing more to do */
                   1673:        return;
                   1674: }
                   1675: 
                   1676: /** 
                   1677:  * @brief Allows to store user defined data associated to the node
                   1678:  * that is not visible from an XML perspective.
                   1679:  *
                   1680:  * See \ref axl_node_annotate_data for a long explanation. This
                   1681:  * function performs the same task as \ref axl_node_annotate_data but
                   1682:  * allowing to set a key destroy and data destroy functions. They are
                   1683:  * later used to deallocate key and data references.
                   1684:  *
                   1685:  * @param node The node where the annotated data will be stored.
                   1686:  *
                   1687:  * @param key The key under which the annotated data will be stored.
                   1688:  *
                   1689:  * @param key_destroy The destroy function to be called to deallocate
                   1690:  * the key stored.
                   1691:  *
                   1692:  * @param data The data to be stored associated to the key provided.
                   1693:  *
                   1694:  * @param data_destroy The destroy function to be called to deallocate
                   1695:  * the data provided.
                   1696:  */
                   1697: void      axl_node_annotate_data_full            (axlNode       * node,
                   1698:                                                 const char    * key,
                   1699:                                                 axlDestroyFunc  key_destroy,
                   1700:                                                 axlPointer      data,
                   1701:                                                 axlDestroyFunc  data_destroy)
                   1702: {
                   1703:        axl_return_if_fail (node);
                   1704: 
                   1705:        /* check and init node annotation */
                   1706:        __init_node_annotation (node);
                   1707: 
                   1708:        /* insert data */
                   1709:        axl_hash_insert_full (node->annotate_data, (axlPointer) key, key_destroy, data, data_destroy);
                   1710: 
                   1711:        /* nothing more to do */
                   1712:        return;
                   1713: }
                   1714: 
                   1715: /** 
                   1716:  * @brief Allows to perform a lookup for annotated data stored on the
                   1717:  * provided node.
                   1718:  * 
                   1719:  * @param node The node where the lookup will be performed.
                   1720:  *
                   1721:  * @param key The key to lookup in the \ref axlNode reference.
                   1722:  *
                   1723:  * @param lookup_in_parent Once the lookup fails in the current node,
                   1724:  * this variable allows to signal the function to also lookup the
                   1725:  * value in the parent nodes recursively. This mechanism allows to
                   1726:  * store data on parent nodes that are shared among all child nodes.
                   1727:  *
                   1728:  * @return The data associated to the key according to the lookup
                   1729:  * configuration (lookup_in_parent and lookup_in_doc).
                   1730:  */
                   1731: axlPointer axl_node_annotate_get                 (axlNode     * node,
                   1732:                                                  const char  * key,
                   1733:                                                  axl_bool      lookup_in_parent)
                   1734: {
                   1735:        axlPointer   result = NULL;
                   1736:        axlNode    * parent;
                   1737:        
                   1738:        /* check node received before nothing */
                   1739:        axl_return_val_if_fail (node, NULL);
                   1740:        axl_return_val_if_fail (key, NULL);
                   1741:        
                   1742:        /* lookup the data in the current node */
                   1743:        if (node->annotate_data != NULL) {
                   1744:                /* lookup the data */
                   1745:                result = axl_hash_get (node->annotate_data, (axlPointer) key);
                   1746: 
                   1747:                /* check result returned */
                   1748:                if (result != NULL)
                   1749:                        return result;
                   1750:        } /* end if */
                   1751: 
                   1752:        /* check if we have to lookup the data in parent nodes */
                   1753:        if (lookup_in_parent) {
                   1754:                /* get the first parent reference */
                   1755:                parent = axl_item_get_parent (node->holder);
                   1756:                
                   1757:                /* for each parent, try to lookup the data */
                   1758:                while (parent != NULL) {
                   1759:                        /* lookup the data */
                   1760:                        if (parent->annotate_data)
                   1761:                                result = axl_hash_get (parent->annotate_data, (axlPointer) key);
                   1762: 
                   1763:                        /* check result returned */
                   1764:                        if (result != NULL)
                   1765:                                return result;
                   1766: 
                   1767:                        /* get the next parent */
                   1768:                        parent = axl_item_get_parent (parent->holder);
                   1769:                }
                   1770:        }
                   1771: 
                   1772:        /* no node was found */
                   1773:        return result;
                   1774: }
                   1775: 
                   1776: /** 
                   1777:  * @internal definition to clasify node annotation.
                   1778:  */
                   1779: typedef enum {
                   1780:        /** 
                   1781:         * @internal definition to clasify int elements.
                   1782:         */
                   1783:        ANNOTATE_INT     = 0, 
                   1784:        /** 
                   1785:         * @internal definition to clasify string elements.
                   1786:         */
                   1787:        ANNOTATE_STRING  = 1, 
                   1788:        /** 
                   1789:         * @internal definition to clasify int elements.
                   1790:         */
                   1791:        ANNOTATE_DOUBLE  = 2
                   1792: } AnnotateType;
                   1793: 
                   1794: typedef struct _AnnotateNodeData {
                   1795:        /** 
                   1796:         * @internal type annotated.
                   1797:         */
                   1798:        AnnotateType type;
                   1799: 
                   1800:        /** 
                   1801:         * @internal Value annotated: int, string or double.
                   1802:         */
                   1803:        union {
                   1804:                int    int_value;
                   1805:                char * string_value;
                   1806:                double double_value;
                   1807:        } value;
                   1808: } AnnotateNodeData;
                   1809: 
                   1810: void __axl_annotate_data_free (AnnotateNodeData * data)
                   1811: {
                   1812:        if (data == NULL)
                   1813:                return;
                   1814: 
                   1815:        /* free the string */
                   1816:        if (data->type == ANNOTATE_STRING)
                   1817:                axl_free (data->value.string_value);
                   1818: 
                   1819:        /* free the data */
                   1820:        axl_free (data);
                   1821: 
                   1822:        return;
                   1823: }
                   1824: 
                   1825: /** 
                   1826:  * @brief Allows to perform an annotation to the node at runtime,
                   1827:  * storing a integer value.
                   1828:  *
                   1829:  * While using xml documents loaded into memory, each node could be
                   1830:  * processed and annotated with particular information, indexed with a
                   1831:  * key, that could be retrieved later for faster process.
                   1832:  * 
                   1833:  * This data annotation doesn't perform any modification to the xml
                   1834:  * document in any form. It is just a programming support that allows
                   1835:  * developers to avoid creating complex and independent structures to
                   1836:  * the xml document while developing XML based solutions.
                   1837:  * 
                   1838:  * While using annotation support, you can use low level functions
                   1839:  * that provide a simple way to store pointers associated to
                   1840:  * particular nodes and retrieve them using:
                   1841:  * 
                   1842:  * - \ref axl_node_annotate_data_full
                   1843:  * - \ref axl_node_annotate_data
                   1844:  * - \ref axl_node_annotate_get
                   1845:  *
                   1846:  * However, additional functions are provided to store and retreive
                   1847:  * easily integers, strings and double data annotated. See the
                   1848:  * following:
                   1849:  * 
                   1850:  *  - \ref axl_node_annotate_int
                   1851:  *  - \ref axl_node_annotate_string
                   1852:  *  - \ref axl_node_annotate_double
                   1853:  *
                   1854:  * If you use this function to store an integer data you must use \ref
                   1855:  * axl_node_annotate_get_int to retreive data stored. You can't use
                   1856:  * \ref axl_node_annotate_get.
                   1857:  * 
                   1858:  * @param node The node where the annotation will be aplied.
                   1859:  *
                   1860:  * @param key The key to index the data annotated to the node.
                   1861:  *
                   1862:  * @param int_value An integer value that will be annotated to the
                   1863:  * node received under the key provided.
                   1864:  */
                   1865: void       axl_node_annotate_int                 (axlNode    * node,
                   1866:                                                 const char * key,
                   1867:                                                 int          int_value)
                   1868: {
                   1869:        AnnotateNodeData * data;
                   1870:        
                   1871:        /* check received values */
                   1872:        axl_return_if_fail (node);
                   1873:        axl_return_if_fail (key);
                   1874: 
                   1875:        /* allocate the node */
                   1876:        data                  = axl_new (AnnotateNodeData, 1);
                   1877:        data->type            = ANNOTATE_INT;
                   1878:        data->value.int_value = int_value;
                   1879: 
                   1880:        /* annotate the value */
                   1881:        axl_node_annotate_data_full (node, key, NULL, data, (axlDestroyFunc) __axl_annotate_data_free);
                   1882:        
                   1883:        return;
                   1884: }
                   1885: 
                   1886: /** 
                   1887:  * @brief Allows to perform an annotation to the node at runtime,
                   1888:  * storing a string value.
                   1889:  *
                   1890:  * While using xml documents loaded into memory, each node could be
                   1891:  * processed and annotated with particular information, indexed with a
                   1892:  * key, that could be retrieved later for faster process.
                   1893:  * 
                   1894:  * This data annotation doesn't perform any modification to the xml
                   1895:  * document in any form. It is just a programming support that allows
                   1896:  * developers to avoid creating complex and independent structures to
                   1897:  * the xml document while developing XML based solutions.
                   1898:  * 
                   1899:  * While using annotation support, you can use low level functions
                   1900:  * that provide a simple way to store pointers associated to
                   1901:  * particular nodes and retrieve them using:
                   1902:  * 
                   1903:  * - \ref axl_node_annotate_data_full
                   1904:  * - \ref axl_node_annotate_data
                   1905:  * - \ref axl_node_annotate_get
                   1906:  *
                   1907:  * However, additional functions are provided to store and retreive
                   1908:  * easily integers, strings and double data annotated. See the
                   1909:  * following:
                   1910:  * 
                   1911:  *  - \ref axl_node_annotate_int
                   1912:  *  - \ref axl_node_annotate_string
                   1913:  *  - \ref axl_node_annotate_double
                   1914:  *
                   1915:  * If you use this function to store a string data you must use \ref
                   1916:  * axl_node_annotate_get_string to retreive data stored. You can't use \ref axl_node_annotate_get.
                   1917:  *
                   1918:  * @param node The node where the annotation will be aplied.
                   1919:  *
                   1920:  * @param key The key to index the data annotated to the node.
                   1921:  *
                   1922:  * @param string_value A string value that will be annotated to the
                   1923:  * node received under the key provided. This value will be copied and
                   1924:  * released once the node is deallocated.
                   1925:  */
                   1926: void       axl_node_annotate_string              (axlNode       * node,
                   1927:                                                 const char    * key,
                   1928:                                                 const char    * string_value)
                   1929: {
                   1930:        AnnotateNodeData * data;
                   1931:        
                   1932:        /* check received values */
                   1933:        axl_return_if_fail (node);
                   1934:        axl_return_if_fail (key);
                   1935:        axl_return_if_fail (string_value);
                   1936: 
                   1937:        /* allocate the node */
                   1938:        data                     = axl_new (AnnotateNodeData, 1);
                   1939:        data->type               = ANNOTATE_STRING;
                   1940:        data->value.string_value = axl_strdup (string_value);
                   1941: 
                   1942:        /* annotate the value */
                   1943:        axl_node_annotate_data_full (node, key, NULL, data, (axlDestroyFunc) __axl_annotate_data_free);
                   1944:        
                   1945:        return;
                   1946: }
                   1947: 
                   1948: /** 
                   1949:  * @brief Allows to perform an annotation to the node at runtime,
                   1950:  * storing a double value.
                   1951:  *
                   1952:  * While using xml documents loaded into memory, each node could be
                   1953:  * processed and annotated with particular information, indexed with a
                   1954:  * key, that could be retrieved later for faster process.
                   1955:  * 
                   1956:  * This data annotation doesn't perform any modification to the xml
                   1957:  * document in any form. It is just a programming support that allows
                   1958:  * developers to avoid creating complex and independent structures to
                   1959:  * the xml document while developing XML based solutions.
                   1960:  * 
                   1961:  * While using annotation support, you can use low level functions
                   1962:  * that provide a simple way to store pointers associated to
                   1963:  * particular nodes and retrieve them using:
                   1964:  * 
                   1965:  * - \ref axl_node_annotate_data_full
                   1966:  * - \ref axl_node_annotate_data
                   1967:  * - \ref axl_node_annotate_get
                   1968:  *
                   1969:  * However, additional functions are provided to store and retreive
                   1970:  * easily integers, strings and double data annotated. See the
                   1971:  * following:
                   1972:  * 
                   1973:  *  - \ref axl_node_annotate_int
                   1974:  *  - \ref axl_node_annotate_string
                   1975:  *  - \ref axl_node_annotate_double
                   1976:  *
                   1977:  * If you use this function to store a double data you must use \ref
                   1978:  * axl_node_annotate_get_double to retreive data stored. You can't use \ref axl_node_annotate_get.
                   1979:  * 
                   1980:  * @param node The node where the annotation will be aplied.
                   1981:  *
                   1982:  * @param key The key to index the data annotated to the node.
                   1983:  *
                   1984:  * @param double_value A string value that will be annotated to the node
                   1985:  * received under the key provided.
                   1986:  */
                   1987: void       axl_node_annotate_double              (axlNode    * node,
                   1988:                                                 const char * key,
                   1989:                                                 double       double_value)
                   1990: {
                   1991:        AnnotateNodeData * data;
                   1992:        
                   1993:        /* check received values */
                   1994:        axl_return_if_fail (node);
                   1995:        axl_return_if_fail (key);
                   1996: 
                   1997:        /* allocate the node */
                   1998:        data                     = axl_new (AnnotateNodeData, 1);
                   1999:        data->type               = ANNOTATE_DOUBLE;
                   2000:        data->value.double_value = double_value;
                   2001: 
                   2002:        /* annotate the value */
                   2003:        axl_node_annotate_data_full (node, key, NULL, data, (axlDestroyFunc) __axl_annotate_data_free);
                   2004:        
                   2005:        return;
                   2006: }
                   2007: 
                   2008: /** 
                   2009:  * @brief Allows to retrieve the annotated int value stored on the
                   2010:  * particular node, under the provided key.
                   2011:  * 
                   2012:  * @param node The node that is required to return the annotated data.
                   2013:  *
                   2014:  * @param key The key to be used to lookup for the data annotated.
                   2015:  *
                   2016:  * @param lookup_in_parent Once the lookup fails, this variable allows
                   2017:  * to signal the function to also lookup the value in the parent
                   2018:  * nodes. This mechanism allows to store data on parent nodes that are
                   2019:  * shared by child nodes.
                   2020:  *
                   2021:  * NOTE: To make this function work properly you must store double
                   2022:  * values using \ref axl_node_annotate_int. Storing values using
                   2023:  * other functions will lead to unpredictable results.
                   2024:  * 
                   2025:  * @return The integer value stored using \ref
                   2026:  * axl_node_annotate_int. If the key provided doesn't exists, the
                   2027:  * function returns 0.
                   2028:  */
                   2029: int        axl_node_annotate_get_int             (axlNode    * node,
                   2030:                                                  const char * key,
                   2031:                                                  axl_bool     lookup_in_parent)
                   2032: {
                   2033:        AnnotateNodeData * data;
                   2034:        
                   2035:        /* check received values */
                   2036:        axl_return_val_if_fail (node, 0);
                   2037:        axl_return_val_if_fail (key, 0);
                   2038: 
                   2039:        /* get the annotated data */
                   2040:        data = axl_node_annotate_get (node, key, lookup_in_parent);
                   2041: 
                   2042:        /* check for null value. */
                   2043:        if (data == NULL)
                   2044:                return 0;
                   2045: 
                   2046:        if (data->type != ANNOTATE_INT) {
                   2047:                /* drop a log */
                   2048:                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "accesing to a annotation data that isn't flaged as integer");
                   2049:                return 0;
                   2050:        }
                   2051:        
                   2052:        /* return the integer value inside */
                   2053:        return data->value.int_value;
                   2054: }
                   2055: 
                   2056: /** 
                   2057:  * @brief Allows to retrieve the annotated string value stored on the
                   2058:  * particular node, under the provided key.
                   2059:  * 
                   2060:  * @param node The node that is required to return the annotated data.
                   2061:  *
                   2062:  * @param key The key to be used to lookup for the data annotated.
                   2063:  *
                   2064:  * @param lookup_in_parent Once the lookup fails, this variable allows
                   2065:  * to signal the function to also lookup the value in the parent
                   2066:  * nodes. This mechanism allows to store data on parent nodes that are
                   2067:  * shared by child nodes.
                   2068:  *
                   2069:  * NOTE: To make this function work properly you must store double
                   2070:  * values using \ref axl_node_annotate_string. Storing values using
                   2071:  * other functions will lead to unpredictable results.
                   2072:  * 
                   2073:  * @return The string value stored using \ref
                   2074:  * axl_node_annotate_string. If the key provided doesn't exists, the
                   2075:  * function returns NULL.
                   2076:  */
                   2077: char *     axl_node_annotate_get_string          (axlNode    * node,
                   2078:                                                  const char * key,
                   2079:                                                  axl_bool     lookup_in_parent)
                   2080: {
                   2081:        AnnotateNodeData * data;
                   2082:        
                   2083:        /* check received values */
                   2084:        axl_return_val_if_fail (node, NULL);
                   2085:        axl_return_val_if_fail (key, NULL);
                   2086: 
                   2087:        /* get the annotated data */
                   2088:        data = axl_node_annotate_get (node, key, lookup_in_parent);
                   2089: 
                   2090:        /* check for null value. */
                   2091:        if (data == NULL)
                   2092:                return NULL;
                   2093: 
                   2094:        if (data->type != ANNOTATE_STRING) {
                   2095:                /* drop a log */
                   2096:                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "accesing to a annotation data that isn't flaged as string");
                   2097:                return NULL;
                   2098:        }
                   2099:        
                   2100:        /* return the string value inside */
                   2101:        return data->value.string_value;
                   2102: }
                   2103: 
                   2104: /** 
                   2105:  * @brief Allows to retrieve the annotated double value stored on the
                   2106:  * particular node, under the provided key.
                   2107:  * 
                   2108:  * @param node The node that is required to return the annotated data.
                   2109:  *
                   2110:  * @param key The key to be used to lookup for the data annotated.
                   2111:  *
                   2112:  * @param lookup_in_parent Once the lookup fails, this variable allows
                   2113:  * to signal the function to also lookup the value in the parent
                   2114:  * nodes. This mechanism allows to store data on parent nodes that are
                   2115:  * shared by child nodes.
                   2116:  *
                   2117:  * NOTE: To make this function work properly you must store double
                   2118:  * values using \ref axl_node_annotate_double. Storing values using
                   2119:  * other functions will lead to unpredictable results.
                   2120:  * 
                   2121:  * @return The double value stored using \ref
                   2122:  * axl_node_annotate_double. If the key provided doesn't exists, the
                   2123:  * function returns 0.0.
                   2124:  */
                   2125: double     axl_node_annotate_get_double          (axlNode    * node,
                   2126:                                                  const char * key,
                   2127:                                                  axl_bool     lookup_in_parent)
                   2128: {
                   2129:        AnnotateNodeData * data;
                   2130:        
                   2131:        /* check received values */
                   2132:        axl_return_val_if_fail (node, 0.0);
                   2133:        axl_return_val_if_fail (key, 0.0);
                   2134: 
                   2135:        /* get the annotated data */
                   2136:        data = axl_node_annotate_get (node, key, lookup_in_parent);
                   2137: 
                   2138:        /* check for null value. */
                   2139:        if (data == NULL)
                   2140:                return 0.0;
                   2141: 
                   2142:        if (data->type != ANNOTATE_DOUBLE) {
                   2143:                /* drop a log */
                   2144:                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "accesing to a annotation data that isn't flaged as double");
                   2145:                return 0.0;
                   2146:        }
                   2147:        
                   2148:        /* return the double value inside */
                   2149:        return data->value.double_value;
                   2150: }
                   2151: 
                   2152: /**
                   2153:  * @}
                   2154:  */
                   2155: 
                   2156: /** 
                   2157:  * \addtogroup axl_node_module
                   2158:  * @{
                   2159:  */
                   2160: 
                   2161: /** 
                   2162:  * @brief Allows to configure the given node to be empty.
                   2163:  *
                   2164:  * A \ref axlNode is empty when it is known that the node doesn't have
                   2165:  * any content inside it as a child element. If the node has content,
                   2166:  * and the value provided to this function is \ref axl_true, the function
                   2167:  * will deallocate the content inside.
                   2168:  *
                   2169:  * You can use this function to clear all the node content (\ref
                   2170:  * ITEM_CONTENT and \ref ITEM_CDATA) found inside the node, as follows:
                   2171:  * \code
                   2172:  * // clear all content inside 
                   2173:  * axl_node_set_is_empty (node, axl_true);
                   2174:  * \endcode
                   2175:  *
                   2176:  * @param node The node to configure as empty.
                   2177:  *
                   2178:  * @param empty The value for emptyness to be used. axl_false will
                   2179:  * mean that the node is not empty.
                   2180:  */
                   2181: void      axl_node_set_is_empty (axlNode * node, axl_bool empty)
                   2182: {
                   2183:        axlItem * child;
                   2184:        axlItem * aux;
                   2185:        int       removed = 0;
                   2186:        int       count   = 0;
                   2187: 
                   2188:        axl_return_if_fail (node);
                   2189: 
                   2190:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "received set to empty node=<%s> is_empty=\"%s\"",
                   2191:                   node->name, empty ? "true" : "false");
                   2192: 
                   2193:        /* do no perform any operation if axl_false is received */
                   2194:        if (! empty)
                   2195:                return;
                   2196: 
                   2197:        /* get the first child and eliminate all content */
                   2198:        child = node->first;
                   2199:        while (child != NULL) {
                   2200: 
                   2201:                /* count each item found */
                   2202:                count++;
                   2203: 
                   2204:                /* get a reference to the next */
                   2205:                aux = child->next;
                   2206: 
                   2207:                /* check item node that represents content, and
                   2208:                 * therefore, an emptyless state */
                   2209:                if (axl_item_get_type (child) == ITEM_CONTENT || 
                   2210:                    axl_item_get_type (child) == ITEM_CDATA) {
                   2211: 
                   2212:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found item content and item CDATA..");
                   2213: 
                   2214:                        /* remove the node */
                   2215:                        axl_item_remove (child, axl_true);
                   2216: 
                   2217:                        /* count each item removed */
                   2218:                        removed++;
                   2219:                        
                   2220:                } /* end if */
                   2221: 
                   2222:                /* update to the next */
                   2223:                child = aux;
                   2224:                
                   2225:        } /* end while */
                   2226: 
                   2227:        /* now check if items removed are equal to items counted */
                   2228:        if (removed == count) {
                   2229:                /* then clear node references */
                   2230:                node->first = NULL;
                   2231:                node->last  = NULL;
                   2232:        }
                   2233:        
                   2234:        return;
                   2235: }
                   2236: 
                   2237: /** 
                   2238:  * @brief Allows to get current xml node name.
                   2239:  *
                   2240:  * If it is required to check if the given \ref axlNode have a
                   2241:  * particular name you can use the macro \ref NODE_CMP_NAME.
                   2242:  *
                   2243:  * Here is an example:
                   2244:  * \code
                   2245:  * void check_name (axlNode * node) {
                   2246:  *     if (NODE_CMP_NAME (node, "data")) {
                   2247:  *         // we got a xml node called "data" 
                   2248:  *     }
                   2249:  *   // the node doesn't have that name
                   2250:  * }
                   2251:  * \endcode
                   2252:  *
                   2253:  * @param node The \ref axlNode where the name will be returned.
                   2254:  * 
                   2255:  * @return A string reference containing the name. Returned value must
                   2256:  * not deallocated. If a copy is required use \ref axl_strdup
                   2257:  * function.
                   2258:  */
                   2259: const char    * axl_node_get_name           (axlNode * node)
                   2260: {
                   2261:        axl_return_val_if_fail (node, NULL);
                   2262: 
                   2263:        return node->name;
                   2264: }
                   2265: 
                   2266: /** 
                   2267:  * @brief Allows to get the parent xml node (\ref axlNode) of the
                   2268:  * provided xml node reference.
                   2269:  *
                   2270:  * @param node The xml node that is requested to return its parent
                   2271:  * node.
                   2272:  * 
                   2273:  * @return An internal reference to the parent node, that must not be
                   2274:  * deallocated, or NULL if fails. The function will also return NULL
                   2275:  * if the node provided is the document root. The function could only
                   2276:  * fail if the provided reference is NULL.
                   2277:  */
                   2278: axlNode * axl_node_get_parent         (axlNode * node)
                   2279: {
                   2280:        axl_return_val_if_fail (node, NULL);
                   2281: 
                   2282:        /* if holder is NULL, no parent is posible */
                   2283:        if (node->holder == NULL) {
                   2284:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "received a node without holder (an axlItem reference), unable to get the parent reference: %s", 
                   2285:                           node->name);
                   2286:                return NULL;
                   2287:        }
                   2288: 
                   2289:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "the node has a holder reference, returning current parent");
                   2290:        
                   2291:        /* return the parent */
                   2292:        return node->holder->parent;
                   2293: }
                   2294: 
                   2295: /** 
                   2296:  * @brief Allows to get the node that is located, at the same level,
                   2297:  * on the next position on the child list.
                   2298:  *
                   2299:  * When a parent node holds more node childs, all of them have the
                   2300:  * same parent child, and at the same time, all of them have a brother
                   2301:  * relation. This relation makes that two nodes that are childs for a
                   2302:  * parent node, are positioned sequentially as childs for the parent.
                   2303:  *
                   2304:  * This function allows to get the next child that is stored at the
                   2305:  * next position, inside the same level, for the given child node.
                   2306:  *
                   2307:  * There are an alternative API that allows to get the next node,
                   2308:  * following to the node selected, but providing the name to match. See
                   2309:  * \ref axl_node_get_next_called.
                   2310:  *
                   2311:  * @param node The node to get the next xml node reference.
                   2312:  * 
                   2313:  * @return Returns an internal reference to the next xml node or NULL
                   2314:  * if fails. The function will also return NULL if no next xml node is
                   2315:  * found starting from the provided reference. The root node will
                   2316:  * always returns a NULL reference.
                   2317:  */
                   2318: axlNode * axl_node_get_next           (axlNode * node)
                   2319: {
                   2320:        axlItem * item;
                   2321: 
                   2322:        axl_return_val_if_fail (node, NULL);
                   2323: 
                   2324:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "getting next node for=<%s>", axl_node_get_name (node));
                   2325: 
                   2326:        if (node->holder == NULL) {
                   2327:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "received a node without item holder (maybe it wasn't inserted into a xml document)");
                   2328:                return NULL;
                   2329:        }
                   2330:        
                   2331:        /* get the next axlNode situated at the same level of the
                   2332:         * provided axlNode reference */
                   2333:        item = axl_item_get_next (node->holder);
                   2334: 
                   2335:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "%s", (item != NULL) ? "next item is defined, check if it is a node" : "next item isn't defined");
                   2336:        
                   2337:        /* while the item is not null and different from item node,
                   2338:         * get the next */
                   2339:        while (item != NULL) {
                   2340: 
                   2341:                /* get the item found */
                   2342:                if (axl_item_get_type (item) == ITEM_NODE)
                   2343:                        return item->data;
                   2344: 
                   2345:                /* get next item */
                   2346:                item = item->next;
                   2347:                
                   2348:        } /* end while */
                   2349: 
                   2350:        /* or null if no reference is defined */
                   2351:        return NULL;
                   2352: }
                   2353: 
                   2354: /** 
                   2355:  * @brief Allows to get the next node, following to the node provided,
                   2356:  * matching the given name.
                   2357:  *
                   2358:  * <i><b>NOTE:</b> This function isn't XML Namespace aware. You must
                   2359:  * use \ref axl_ns_node_get_next_called instead. See \ref
                   2360:  * axl_ns_doc_validate. </i>
                   2361:  * 
                   2362:  * @param node The node that is requested to return its next sibling
                   2363:  * node.
                   2364:  *
                   2365:  * @param name The name to match for the next node.
                   2366:  * 
                   2367:  * @return A reference to the next node or NULL if it fails. The
                   2368:  * returned reference mustn't be deallocated.
                   2369:  */
                   2370: axlNode * axl_node_get_next_called    (axlNode       * node, 
                   2371:                                       const char    * name)
                   2372: {
                   2373:        axlNode * next;
                   2374:        axl_return_val_if_fail (node, NULL);
                   2375:        axl_return_val_if_fail (name, NULL);
                   2376: 
                   2377:        /* while there is a next node */
                   2378:        next = axl_node_get_next (node);
                   2379:        while (next != NULL) {
                   2380:                /* check the node */
                   2381:                if (NODE_CMP_NAME (next, name))
                   2382:                        return next;
                   2383: 
                   2384:                /* update to the next */
                   2385:                next = axl_node_get_next (next);
                   2386:        } /* end while */
                   2387: 
                   2388:        /* no node was found */
                   2389:        return NULL;
                   2390: }
                   2391: 
                   2392: /** 
                   2393:  * @brief Allows to get the previous reference relative to the node
                   2394:  * reference provided.
                   2395:  *
                   2396:  * See \ref axl_node_get_next. Previous reference is the considered
                   2397:  * the previous node to the referenced provided that shares the same
                   2398:  * parent and it is situated in the same level.
                   2399:  * 
                   2400:  * @param node The node where the previous reference to the previous
                   2401:  * node will be returned.
                   2402:  * 
                   2403:  * @return The previous node reference or NULL if the node doesn't
                   2404:  * have previous reference or NULL if the function fails (the function
                   2405:  * only fails if the node reference provided is null).
                   2406:  */
                   2407: axlNode * axl_node_get_previous (axlNode * node)
                   2408: {
                   2409:        axlItem * item;
                   2410: 
                   2411:        axl_return_val_if_fail (node, NULL);
                   2412: 
                   2413:        /* get the previous axlNode situated at the same level of the
                   2414:         * provided axlNode reference */
                   2415:        item = axl_item_get_previous (node->holder);
                   2416: 
                   2417:        /* while the item is not null and different from item node,
                   2418:         * get the previous */
                   2419:        while ((item != NULL) && axl_item_get_type (item) !=ITEM_NODE)
                   2420:                item = axl_item_get_previous (item);
                   2421: 
                   2422:        /* return the previous reference */
                   2423:        if (item != NULL)
                   2424:                return item->data;
                   2425: 
                   2426:        /* or null if no reference is defined */
                   2427:        return NULL;
                   2428: }
                   2429: 
                   2430: /** 
                   2431:  * @brief Allows to get the previous node, preceding to the node
                   2432:  * provided, matching the given name.
                   2433:  *
                   2434:  * <i><b>NOTE:</b> This function isn't XML Namespace aware. You must
                   2435:  * use \ref axl_ns_node_get_previous_called instead. See \ref
                   2436:  * axl_ns_doc_validate. </i>
                   2437:  * 
                   2438:  * @param node The node that is requested to return its previous sibling node.
                   2439:  * @param name The name to match for the previous node.
                   2440:  * 
                   2441:  * @return A reference to the previous node or NULL if it fails. The
                   2442:  * returned reference mustn't be deallocated.
                   2443:  */ 
                   2444: axlNode *  axl_node_get_previous_called     (axlNode       * node, 
                   2445:                                             const char    * name)
                   2446: {
                   2447:        axlNode * previous;
                   2448: 
                   2449:        axl_return_val_if_fail (node, NULL);
                   2450:        axl_return_val_if_fail (name, NULL);
                   2451: 
                   2452:        /* while there is a previous node */
                   2453:        previous = axl_node_get_previous (node);
                   2454:        while (previous != NULL) {
                   2455:                /* check the node */
                   2456:                if (NODE_CMP_NAME (previous, name))
                   2457:                        return previous;
                   2458: 
                   2459:                /* update to the next */
                   2460:                previous = axl_node_get_previous (previous);
                   2461:        } /* end while */
                   2462: 
                   2463:        /* no node was found */
                   2464:        return NULL;
                   2465: 
                   2466: } 
                   2467: 
                   2468: 
                   2469: /** 
                   2470:  * @brief Allows to get the first child that holds the node.
                   2471:  *
                   2472:  * This function is considered inside the CHILDREN API, which is the
                   2473:  * set of functions that are used to handle XML documents that have
                   2474:  * node that contains more nodes or content, but not mixed.
                   2475:  *
                   2476:  * This function allows to get the first child found that is an \ref
                   2477:  * axlNode. In the case your application is handling a document that
                   2478:  * don't mix nodes and content at the same level inside another xml
                   2479:  * nodes, you'll get the expected results.
                   2480:  *
                   2481:  * But, calling to this function on a node that contains content mixed
                   2482:  * with another nodes, you will skip all items stored before the first
                   2483:  * xml node found as child. 
                   2484:  *
                   2485:  * Let's see some examples to clarify this. Provided the following xml
                   2486:  * document:
                   2487:  *
                   2488:  * \code
                   2489:  * <document>
                   2490:  *   <child>
                   2491:  *     Content
                   2492:  *   </child>
                   2493:  * </document>
                   2494:  * \endcode
                   2495:  *
                   2496:  * If you want to get a reference to the <b>child</b> node you can do
                   2497:  * the following:
                   2498:  * 
                   2499:  * \code
                   2500:  * // supposing the document is already loaded in "doc"
                   2501:  * axlNode * node = axl_doc_get_root (doc);
                   2502:  *
                   2503:  * // get the first child 
                   2504:  * node = axl_node_get_first_child (node);
                   2505:  *
                   2506:  * // now you have in "node" a reference to the child node.
                   2507:  * \endcode
                   2508:  *
                   2509:  * However, in the case the previous content mix node with content as
                   2510:  * follows:
                   2511:  *
                   2512:  * \code
                   2513:  * <document>
                   2514:  *   Some content previous to the first child.
                   2515:  *   <child>
                   2516:  *     Content
                   2517:  *   </child>
                   2518:  * </document>
                   2519:  * \endcode
                   2520:  *
                   2521:  * Using this function will make you to skip the first content, that
                   2522:  * is, <i>"Some content previous to the first child"</i>, which is found
                   2523:  * before the &lt;child> node. In the case you want to have full
                   2524:  * access to all items stored as child for a particular node, check
                   2525:  * \ref axl_item_get_first_child.
                   2526:  * 
                   2527:  * @param node The node that is requested to return its first child.
                   2528:  * 
                   2529:  * @return The first child node or NULL if it has no child node.
                   2530:  */
                   2531: axlNode * axl_node_get_first_child    (axlNode * node)
                   2532: {
                   2533:        axlItem * item;
                   2534: 
                   2535:        /* check values */
                   2536:        axl_return_val_if_fail (node, NULL);
                   2537: 
                   2538:        /* get first item child and lookup for the first child that is
                   2539:         * a node */
                   2540:        item = node->first;
                   2541:        while (item != NULL) {
                   2542:                /* check the item type */
                   2543:                if (axl_item_get_type (item) == ITEM_NODE)
                   2544:                        return item->data;
                   2545: 
                   2546:                /* get the next */
                   2547:                item = item->next;
                   2548:        }
                   2549: 
                   2550:        /* return NULL: no child axlNode was found */
                   2551:        return NULL;
                   2552: }
                   2553: 
                   2554: /** 
                   2555:  * @brief Allows to get the last child that holds the node.
                   2556:  *
                   2557:  * See also \ref axl_node_get_first_child and \ref axl_item_get_last_child.
                   2558:  * 
                   2559:  * @param node The node that is requested to return its last child.
                   2560:  * 
                   2561:  * @return The last child node or NULL if it has no child node.
                   2562:  */
                   2563: axlNode * axl_node_get_last_child     (axlNode * node)
                   2564: {
                   2565:        axlItem * item;
                   2566: 
                   2567:        /* check values */
                   2568:        axl_return_val_if_fail (node, NULL);
                   2569: 
                   2570:        /* get first item child and lookup for the first child that is
                   2571:         * a node */
                   2572:        item = node->last;
                   2573:        while (item != NULL) {
                   2574:                /* check the item type */
                   2575:                if (axl_item_get_type (item) == ITEM_NODE)
                   2576:                        return item->data;
                   2577: 
                   2578:                /* get the next */
                   2579:                item = item->previous;
                   2580:        }
                   2581: 
                   2582:        /* return NULL: no child axlNode was found */
                   2583:        return NULL;
                   2584: }
                   2585: 
                   2586: /** 
                   2587:  * @brief Allows to check if the provided \ref axlNode is empty.
                   2588:  *
                   2589:  * If a node have content, this function will return \ref
                   2590:  * axl_false. The content must not be confused with the node childs. A
                   2591:  * xml node (\ref axlNode) could be empty but have childs at the same
                   2592:  * time (\ref axl_node_have_childs).
                   2593:  *
                   2594:  * The following xml code snipet shows a xml &lt;data> node with
                   2595:  * childs that have content, but the parent node, &lt;data> do not
                   2596:  * have content, therefore is empty.
                   2597:  *
                   2598:  * \code
                   2599:  * <data>
                   2600:  *    <row>Some data</row>
                   2601:  *    <row>More content</row>
                   2602:  * </data>
                   2603:  * \endcode
                   2604:  *
                   2605:  * A node that is empty will return NULL data once called to \ref
                   2606:  * axl_node_get_content.
                   2607:  * 
                   2608:  * @param node The node to check for its empty status. 
                   2609:  * 
                   2610:  * @return \ref axl_true if the node is empty or \ref axl_false if
                   2611:  * not.
                   2612:  */
                   2613: axl_bool          axl_node_is_empty        (axlNode * node)
                   2614: {
                   2615:        axlItem * child;
                   2616:        axl_return_val_if_fail (node, axl_false);
                   2617: 
                   2618:        /* get the first child */
                   2619:        child = node->first;
                   2620:        while (child != NULL) {
                   2621:                
                   2622:                /* check item node that represents content, and
                   2623:                 * therefore, an emptyless state */
                   2624:                if (axl_item_get_type (child) == ITEM_CONTENT || 
                   2625:                    axl_item_get_type (child) == ITEM_CDATA) {
                   2626: 
                   2627:                        /* the node has content */
                   2628:                        return axl_false;
                   2629:                        
                   2630:                } /* end if */
                   2631: 
                   2632:                /* go to the next */
                   2633:                child = child->next;
                   2634: 
                   2635:        } /* end while */
                   2636: 
                   2637:        return axl_true;
                   2638: }
                   2639: 
                   2640: /** 
                   2641:  * @brief Allows to get current xml node content (\ref axlNode).
                   2642:  * 
                   2643:  * See \ref axl_node_is_empty for more details. This function allows
                   2644:  * to get current xml node content, which is the free text enclosed
                   2645:  * inside the node.
                   2646:  *
                   2647:  * Returned value is an internal reference to the content stored. So,
                   2648:  * in the case a local copy is desired, you should check \ref
                   2649:  * axl_node_get_content_copy. 
                   2650:  *
                   2651:  * Keep in mind that the content returned could have references like
                   2652:  * "&amp;" or "&quot;" which are entities references not translated
                   2653:  * into the application level values. 
                   2654:  * 
                   2655:  * This is done because while using the content, you may be interested
                   2656:  * in getting the raw content to be passed to another xml parser which
                   2657:  * is also able to process that entities.
                   2658:  *
                   2659:  * If you don't like this behaviour you can check \ref
                   2660:  * axl_node_get_content_trans which returns a copy for the xml node
                   2661:  * content with all entities references translated.
                   2662:  *
                   2663:  * Here is a summary of functions available to get the content of a
                   2664:  * node:
                   2665:  * 
                   2666:  * - \ref axl_node_get_content_copy (the same like this function but
                   2667:  * producing an independent copy)
                   2668:  *
                   2669:  * - \ref axl_node_get_content_trans (the same like this function but
                   2670:  * translating all entity references and producing an indenpendent
                   2671:  * copy).
                   2672:  *
                   2673:  * - \ref axl_node_get_content_trim (the same like this function but
                   2674:  * removing initial and trailing white spaces in the W3C sense: spaces,
                   2675:  * tabulars, carry returns and line feed values).
                   2676:  * 
                   2677:  * @param node The \ref axlNode node where the content will be retrieved.
                   2678:  *
                   2679:  * @param content_size Optional pointer to an integer variable where
                   2680:  * the content size will be reported. If the variable is not set, the
                   2681:  * function will not report the content size. If this value is
                   2682:  * configured, it will contain the content size starting from 0 up to
                   2683:  * the content size.
                   2684:  * 
                   2685:  * @return Current xml node content. You must not deallocate reference
                   2686:  * returned. If you want a permanet copy you should use \ref
                   2687:  * axl_node_get_content_copy. Keep in mind that the function will always
                   2688:  * return an string reference. In the case the node has no content, an
                   2689:  * empty string will be returned, not NULL.
                   2690:  */
                   2691: const char    * axl_node_get_content     (axlNode * node, int * content_size)
                   2692: {
                   2693:        axlNodeContent * content;
                   2694:        axlItem        * child;
                   2695: 
                   2696:        axl_return_val_if_fail (node, NULL);
                   2697: 
                   2698:        /* get the first child */
                   2699:        child = node->first;
                   2700:        while (child != NULL) {
                   2701:                
                   2702:                /* check item node that represents content, and
                   2703:                 * therefore, an emptyless state */
                   2704:                if (axl_item_get_type (child) == ITEM_CONTENT || 
                   2705:                    axl_item_get_type (child) == ITEM_CDATA) {
                   2706:                        /* cast a reference */
                   2707:                        content = child->data;
                   2708: 
                   2709:                        /* return the content */
                   2710:                        if (content_size != NULL)
                   2711:                                *content_size = content->content_size;
                   2712: 
                   2713:                        /* return a local reference */
                   2714:                        return content->content;
                   2715:                } /* end if */
                   2716: 
                   2717:                /* get the next item */
                   2718:                child = child->next;
                   2719: 
                   2720:        } /* end while */
                   2721: 
                   2722:        /* set content size to zero */
                   2723:        if (content_size != NULL)
                   2724:                *content_size = 0;
                   2725:        return "";
                   2726: }
                   2727: 
                   2728: /** 
                   2729:  * @brief Allows to set content to the given \ref axlNode instance.
                   2730:  *
                   2731:  * The xml node content is that part defined inside two balanced xml tags,
                   2732:  * using the same label. Here is an example:
                   2733:  * \code
                   2734:  * <data>
                   2735:  *   Content inside the xml node.
                   2736:  * </data>
                   2737:  * \endcode
                   2738:  *
                   2739:  * The function perform a local copy from the content received, doing
                   2740:  * all entity replacement required.
                   2741:  *
                   2742:  * The following table shows the set of characters that this function
                   2743:  * will translate into its corresponding entity:
                   2744:  *
                   2745:  * <table>
                   2746:  * <tr><td><b>Character</b></td><td>Entity name</td></tr>
                   2747:  * <tr><td>'</td><td>&amp;apos;</td></tr>
                   2748:  * <tr><td><</td><td>&amp;lt;</td></tr>
                   2749:  * <tr><td>></td><td>&amp;gt;</td></tr>
                   2750:  * <tr><td>&</td><td>&amp;amp;</td></tr>
                   2751:  * <tr><td>"</td><td>&amp;quot;</td></tr>
                   2752:  * </table>
                   2753:  *
                   2754:  * @param node The xml node, represented by an already initialized
                   2755:  * \ref axlNode, where the node content will be set.
                   2756:  *
                   2757:  * @param content The content to set to the \ref axlNode. The function
                   2758:  * will perform a local copy from it.
                   2759:  *
                   2760:  * @param content_size The content size that is being provided. If -1
                   2761:  * is used, the function will use strlen function to get current
                   2762:  * content size.
                   2763:  */
                   2764: void      axl_node_set_content        (axlNode    * node, 
                   2765:                                       const char * content, 
                   2766:                                       int          content_size)
                   2767: {
                   2768:        axlNodeContent * itemContent;
                   2769:        int              additional_size = 0;
                   2770: 
                   2771:        axl_return_if_fail (node);
                   2772:        axl_return_if_fail (content);
                   2773: 
                   2774:        /* get current content in the case a -1 is provided */
                   2775:        if (content_size == -1)
                   2776:                content_size = strlen (content);
                   2777: 
                   2778:        /* allocate the content */
                   2779:        itemContent  = axl_new (axlNodeContent, 1);
                   2780: 
                   2781:        /* check if the string received have escapable characters */
                   2782:        if (axl_node_has_invalid_chars (content, content_size, 
                   2783:                                        &additional_size)) {
                   2784:                /* copy content */
                   2785:                itemContent->content        = __axl_node_content_copy_and_escape (content, 
                   2786:                                                                                  content_size, 
                   2787:                                                                                  additional_size,
                   2788:                                                                                  axl_false);
                   2789:                /* set node content size */
                   2790:                itemContent->content_size   = content_size + additional_size;
                   2791:        }else {
                   2792:                /* set current content */
                   2793:                itemContent->content_size   = content_size;
                   2794:                itemContent->content        = axl_new (char, content_size + 1);
                   2795: 
                   2796:                /* copy content */
                   2797:                memcpy (itemContent->content, content, itemContent->content_size);
                   2798:        }
                   2799: 
                   2800:        /* add it to the current node */
                   2801:        axl_item_set_child (node, ITEM_CONTENT, itemContent);
                   2802:        
                   2803: 
                   2804:        /* job done */
                   2805:        return;
                   2806: }
                   2807: 
                   2808: /** 
                   2809:  * @internal Common implementation for axl_node_set_content_ref and
                   2810:  * axl_node_set_content_from_factory.
                   2811:  */
                   2812: void __axl_node_set_content_common_ref (axlFactory     * factory, 
                   2813:                                        axlNode        * node, 
                   2814:                                        char           * content, 
                   2815:                                        int              content_size, 
                   2816:                                        axl_bool         from_factory,
                   2817:                                        axl_bool         cdata)
                   2818: {
                   2819:        
                   2820:        axlNodeContent * itemContent;
                   2821: 
                   2822:        axl_return_if_fail (node);
                   2823:        axl_return_if_fail (content);
                   2824: 
                   2825:        /* get current content in the case a -1 is provided */
                   2826:        if (content_size == -1)
                   2827:                content_size = strlen (content);
                   2828: 
                   2829:        /* create a content checking it it comes from the
                   2830:         * factory. Because the string received could come from the
                   2831:         * factory, already allocated, do not call to allocate */
                   2832:        if (from_factory && factory)
                   2833:                itemContent = axl_factory_get (factory);
                   2834:        else 
                   2835:                itemContent = axl_new (axlNodeContent, 1);
                   2836:                
                   2837:        /* configure content size */
                   2838:        itemContent->content_size = content_size;
                   2839: 
                   2840:        /* set current content */
                   2841:        itemContent->content  = content;
                   2842: 
                   2843:        if (from_factory) {
                   2844:                if (cdata) {
                   2845:                        /* store it */
                   2846:                        axl_item_set_child (node, ITEM_CDATA | ITEM_CONTENT_FROM_FACTORY, itemContent);
                   2847:                } else {
                   2848:                        /* store it */
                   2849:                        axl_item_set_child (node, ITEM_CONTENT | ITEM_CONTENT_FROM_FACTORY, itemContent);
                   2850:                }
                   2851:        } else {
                   2852:                /* store it */
                   2853:                if (cdata) {
                   2854:                        /* store as cdata */
                   2855:                        axl_item_set_child (node, ITEM_CDATA, itemContent);
                   2856:                } else {
                   2857:                        /* store as parsed xml content */
                   2858:                        axl_item_set_child (node, ITEM_CONTENT, itemContent);
                   2859:                }
                   2860:        } /* end if */
                   2861: 
                   2862:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "setting xml node (name: %s) content (size: %d) %s",
                   2863:                   node->name, itemContent->content_size, itemContent->content);
                   2864: 
                   2865:        return;
                   2866: }
                   2867: 
                   2868: /** 
                   2869:  * @brief Set the content for the provided node, reusing the reference
                   2870:  * provided, without making a local copy.
                   2871:  *
                   2872:  * This function works like \ref axl_node_set_content_ref but without
                   2873:  * copy memory provided. This allows reduce memory allocations if the
                   2874:  * memory was already allocated by the user space.
                   2875:  *
                   2876:  * Because this function doesn't perform a copy, if the content
                   2877:  * received has to be escaped, the function will fail. To use this
                   2878:  * function the caller must ensure that entity references are used to
                   2879:  * especify the &, ', ", < or >.
                   2880:  *
                   2881:  * If the node have content already configured, it is deallocated,
                   2882:  * configuring new content received.
                   2883:  * 
                   2884:  * @param node The \ref axlNode where the content will be set.
                   2885:  *
                   2886:  * @param content The user space allocated content to be set to the
                   2887:  * node.
                   2888:  *
                   2889:  * @param content_size The content size.
                   2890:  */
                   2891: void      axl_node_set_content_ref    (axlNode * node, 
                   2892:                                       char * content, 
                   2893:                                       int content_size)
                   2894: {
                   2895: 
                   2896:        /* call to set content without signaling that the content
                   2897:         * wasn't allocated by a factory. */
                   2898:        __axl_node_set_content_common_ref (NULL, node, content, content_size, axl_false, axl_false);
                   2899:        
                   2900:        /* job done */
                   2901:        return; 
                   2902: }
                   2903: 
                   2904: /** 
                   2905:  * @internal Internal API used by the axl doc module to signal that
                   2906:  * the content was allocated though the string factory and shouldn't
                   2907:  * be deallocated.
                   2908:  */
                   2909: void      axl_node_set_content_from_factory (axlFactory * factory,
                   2910:                                             axlNode    * node,
                   2911:                                             char       * content,
                   2912:                                             int          content_size)
                   2913: {
                   2914:        /* call to set content without signaling that the content was
                   2915:         * allocated by a factory. */
                   2916:        __axl_node_set_content_common_ref (factory, node, content, content_size, axl_true, axl_false);
                   2917:        
                   2918:        /* job done */
                   2919:        return;
                   2920: }
                   2921: 
                   2922: /** 
                   2923:  * @brief Allows to store CDATA enclosed content on the provided node.
                   2924:  *
                   2925:  * Some characters are not allowed to be stored "as is" inside a
                   2926:  * parseable XML document. The basic set of them are: &, ', ", < or >.
                   2927:  *
                   2928:  * In order to store content containing previous characters inside an
                   2929:  * xml node, and to remain valid, functions like \ref
                   2930:  * axl_node_set_content will translate those value, into the accepted
                   2931:  * escape sequences. 
                   2932:  *
                   2933:  * As an alternative, the XML node content could be stored enclosed as
                   2934:  * a CDATA section: <![CDATA[..]]>, which allows to store unparsed
                   2935:  * characters, including those not allowed.
                   2936:  *
                   2937:  * NOTE: In the case content received includes a ]]> declaration, it
                   2938:  * is escaped to allow it. This is provided not to allow nested CDATA
                   2939:  * declarations which is not allowed by XML 1.0 standard but to allow
                   2940:  * binary content to be stored that may include a ]]> declaration.
                   2941:  * 
                   2942:  * @param node The node where the CDATA will be stored.
                   2943:  *
                   2944:  * @param content The content to store.
                   2945:  *
                   2946:  * @param content_size The content size or -1 if required Axl to
                   2947:  * figure out current sizes.
                   2948:  */
                   2949: void      axl_node_set_cdata_content  (axlNode    * node,
                   2950:                                       const char * content,
                   2951:                                       int          content_size)
                   2952: {
                   2953:        char * copy;
                   2954:        int    additional_size = 0;
                   2955: 
                   2956:        axl_return_if_fail (node);
                   2957:        axl_return_if_fail (content);
                   2958: 
                   2959:        /* reconfigure content_size if found -1 value */
                   2960:        if (content_size == -1)
                   2961:                content_size = strlen (content);
                   2962: 
                   2963:        if (axl_node_has_invalid_chars_cdata (content, content_size, &additional_size)) {
                   2964:                /* call to get escaped version */
                   2965:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "CDATA found content to scape (content size: %d): '%s'",
                   2966:                           content_size, content);
                   2967:                copy          = __axl_node_content_copy_and_escape (content, content_size, additional_size, axl_true);
                   2968:                content_size += additional_size;
                   2969:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "CDATA content escaped        (content size: %d): '%s'",
                   2970:                           content_size, copy);
                   2971:        } else {
                   2972:                /* call to set node content */  
                   2973:                copy = axl_strdup (content);
                   2974:        } /* end if */
                   2975: 
                   2976:        /* set content */
                   2977:        __axl_node_set_content_common_ref (NULL, node, copy, content_size, axl_false, axl_true);
                   2978: 
                   2979:        return;
                   2980: }
                   2981: 
                   2982: /** 
                   2983:  * @internal Internal API used by the axl doc module to signal that
                   2984:  * the content was allocated though the string factory and shouldn't
                   2985:  * be deallocated, and the content was found inside cdata
                   2986:  * declarations.
                   2987:  */
                   2988: void      axl_node_set_cdata_content_from_factory (axlFactory * factory,
                   2989:                                                   axlNode    * node,
                   2990:                                                   char       * content,
                   2991:                                                   int          content_size)
                   2992: {
                   2993:        /* call to set content without signaling that the content was
                   2994:         * allocated by a factory. */
                   2995:        __axl_node_set_content_common_ref (factory, node, content, content_size, axl_true, axl_true);
                   2996:        
                   2997:        /* job done */
                   2998:        return; 
                   2999: }
                   3000: 
                   3001: /** 
                   3002:  * @brief Allows to configure a new comment (&lt;!-- xml comment -->) that will be
                   3003:  * stored as a child for the node provided.
                   3004:  * 
                   3005:  * The comment will be placed at the end of the current child
                   3006:  * list. So, if you want to place a xml comment before a xml node,
                   3007:  * call first to this function and then to \ref axl_node_set_child.
                   3008:  *
                   3009:  * @param node The node that will contain the comment.
                   3010:  *
                   3011:  * @param comment The comment to be stored. The function will perform
                   3012:  * a copy from it.
                   3013:  *
                   3014:  * @param comment_size The comment size or -1 to make the function to
                   3015:  * calculate it.
                   3016:  */
                   3017: void      axl_node_set_comment        (axlNode * node,
                   3018:                                       char * comment,
                   3019:                                       int    comment_size)
                   3020: {
                   3021:        axlNodeContent * content;
                   3022: 
                   3023:        axl_return_if_fail (node);
                   3024:        axl_return_if_fail (comment);
                   3025: 
                   3026:        /* check current coment size */
                   3027:        if (comment_size == -1)
                   3028:                comment_size = strlen (comment);
                   3029: 
                   3030:        /* create the comment */
                   3031:        content               = axl_new (axlNodeContent, 1);
                   3032:        content->content      = axl_new (char, comment_size + 1);
                   3033:        content->content_size = comment_size;
                   3034: 
                   3035:        /* copy the content */
                   3036:        memcpy (content->content, comment, comment_size);
                   3037: 
                   3038:        /* now store it on the node */
                   3039:        axl_item_set_child (node, ITEM_COMMENT, content);
                   3040: 
                   3041:        return;
                   3042: }
                   3043: 
                   3044: 
                   3045: /** 
                   3046:  * @brief Allows to get a copy for the content stored inside the given
                   3047:  * \ref axlNode reference. 
                   3048:  *
                   3049:  * This function works the same way than \ref axl_node_get_content but
                   3050:  * returning a copy from the internal content, that the caller is
                   3051:  * responsible of deallocating it.
                   3052:  * 
                   3053:  * @param node The \ref axlNode where the content is being required.
                   3054:  *
                   3055:  * @param content_size An optional reference to an integer variable
                   3056:  * where the content size will be returned. The function will return
                   3057:  * the content size (if the variable is defined) ranging from 0 up to
                   3058:  * the content size.
                   3059:  * 
                   3060:  * @return A newly allocated string representing the node content. 
                   3061:  */
                   3062: char    * axl_node_get_content_copy (axlNode * node, int * content_size)
                   3063: {
                   3064:        int          _content_size;
                   3065:        char       * result;
                   3066:        const char * content;
                   3067: 
                   3068:        /* get the content and check if it is defined */
                   3069:        if (content_size)
                   3070:                content = axl_node_get_content (node, content_size);
                   3071:        else
                   3072:                content = axl_node_get_content (node, &_content_size);
                   3073: 
                   3074:        /* check result */
                   3075:        if (content == NULL || strlen (content) == 0) {
                   3076:                return axl_strdup ("");
                   3077:        }
                   3078: 
                   3079:        /* allocate enough memory for the result */
                   3080:        if (content_size) {
                   3081:                result = axl_new (char, (*content_size) + 1);
                   3082:                memcpy (result, content, *content_size);
                   3083:        }else {
                   3084:                result = axl_new (char, _content_size + 1);
                   3085:                memcpy (result, content, _content_size);
                   3086:        }
                   3087:        
                   3088:        /* return a newly allocated reference to the content */
                   3089:        return result;
                   3090: }
                   3091: 
                   3092: /** 
                   3093:  * @brief Allows to get the content inside the provided node, trimming
                   3094:  * the head and trailing white spaces found.
                   3095:  *
                   3096:  * Note that calling to this function will modify the node content,
                   3097:  * removing beginig and ending "white spaces" found. Once the function
                   3098:  * is called, the node content will be returned by \ref
                   3099:  * axl_node_get_content already trimmed.
                   3100:  *
                   3101:  * @param node The node where the content will be trimmed and
                   3102:  * returned.
                   3103:  *
                   3104:  * @param content_size The node content size reference where the
                   3105:  * content size will be reported.
                   3106:  * 
                   3107:  * @return The reference returned is an internal copy that must not be
                   3108:  * deallocated. The function always return content. If the node has no
                   3109:  * content, the function will return an empty string (but never a NULL
                   3110:  * value).
                   3111:  */
                   3112: char    * axl_node_get_content_trim   (axlNode * node,
                   3113:                                       int * content_size)
                   3114: {
                   3115:        int    trimmed;
                   3116: 
                   3117:        axlNodeContent * content;
                   3118:        axlItem        * child;
                   3119: 
                   3120:        axl_return_val_if_fail (node, NULL);
                   3121: 
                   3122:        /* get the first child */
                   3123:        child = node->first;
                   3124:        while (child != NULL) {
                   3125:                
                   3126:                /* check item node that represents content, and
                   3127:                 * therefore, an emptyless state */
                   3128:                if (axl_item_get_type (child) == ITEM_CONTENT || 
                   3129:                    axl_item_get_type (child) == ITEM_CDATA) {
                   3130:                        /* cast a reference */
                   3131:                        content = child->data;
                   3132: 
                   3133:                        /* trim the content */
                   3134:                        axl_stream_trim_with_size (content->content, &trimmed);
                   3135: 
                   3136:                        /* updates current internal content size */
                   3137:                        content->content_size -= trimmed;
                   3138: 
                   3139:                        /* return the content */
                   3140:                        if (content_size != NULL)
                   3141:                                *content_size = content->content_size;
                   3142: 
                   3143:                        /* return a local reference */
                   3144:                        return content->content;
                   3145:                } /* end if */
                   3146:                
                   3147:                /* get the next item */
                   3148:                child = child->next;
                   3149: 
                   3150:        } /* end while */
                   3151: 
                   3152:        /* set content size to zero */
                   3153:        if (content_size != NULL)
                   3154:                *content_size = 0;
                   3155:        return "";
                   3156: }
                   3157: 
                   3158: void axl_node_get_content_trans_count (axlItem * item, int * count, int *total_size)
                   3159: {
                   3160:        axlNodeContent * content;
                   3161: 
                   3162:        /* reset counters received */
                   3163:        (*count)      = 0;
                   3164:        (*total_size) = 0;
                   3165:        while (item != NULL) {
                   3166: 
                   3167:                /* check item time stored and increase counting */
                   3168:                if (axl_item_get_type (item) == ITEM_CONTENT || 
                   3169:                    axl_item_get_type (item) == ITEM_CDATA) {
                   3170:                        /* found item */
                   3171:                        (*count)++;
                   3172: 
                   3173:                        /* update totals */
                   3174:                        content     = item->data;
                   3175:                        (*total_size) += content->content_size;
                   3176:                }
                   3177:                
                   3178:                /* next item */
                   3179:                item = item->next;
                   3180:        } /* end while */
                   3181:        
                   3182:        return;
                   3183: }
                   3184: 
                   3185: 
                   3186: void axl_node_get_content_trans_copy (axlItem * item, char * result)
                   3187: {
                   3188:        axlNodeContent * content;
                   3189:        int              desp;
                   3190: 
                   3191:        /* reset counters received */
                   3192:        desp = 0;
                   3193:        while (item != NULL) {
                   3194: 
                   3195:                /* check item time stored and increase counting */
                   3196:                if (axl_item_get_type (item) == ITEM_CONTENT || 
                   3197:                    axl_item_get_type (item) == ITEM_CDATA) {
                   3198:                        /* update totals */
                   3199:                        content     = item->data;
                   3200:                        
                   3201:                        /* copy content */
                   3202:                        memcpy (result + desp, content->content, content->content_size);
                   3203: 
                   3204:                        /* update iterator */
                   3205:                        desp += content->content_size;
                   3206:                }
                   3207:                
                   3208:                /* next item */
                   3209:                item = item->next;
                   3210:        } /* end while */
                   3211:        
                   3212:        return;
                   3213: }
                   3214: 
                   3215: /** 
                   3216:  * @brief Allows to the get node content, performing a memory
                   3217:  * allocation for the returned result, translating default entities
                   3218:  * values with its replacement text.
                   3219:  * 
                   3220:  * @param node The XML node where the content is being requested to be
                   3221:  * translated.
                   3222:  *
                   3223:  * @param content_size An optional reference to an integer variable to
                   3224:  * return the node content size.
                   3225:  * 
                   3226:  * @return A newly allocated string, representing the node content,
                   3227:  * with all entities references already translated into the
                   3228:  * replacement text.
                   3229:  */
                   3230: char    * axl_node_get_content_trans (axlNode * node, int * content_size)
                   3231: {
                   3232:        char    * result;
                   3233:        int       _content_size = 0;
                   3234:        int       count;
                   3235:        int       total_size;
                   3236: 
                   3237:        /* check received reference */
                   3238:        axl_return_val_if_fail (node, NULL);
                   3239: 
                   3240:        /* check if the node has one item content inside the node or
                   3241:         * several CDATA or content items */
                   3242:        axl_node_get_content_trans_count (node->first, &count, &total_size);
                   3243: 
                   3244:        /* accoring to the number of items found */
                   3245:        switch (count) {
                   3246:        case 0:
                   3247:                /* report content size */
                   3248:                if (content_size)
                   3249:                        *content_size = 0;
                   3250:                /* nothing found return */
                   3251:                return NULL;
                   3252:        case 1:
                   3253:                /* get a copy for the node content, getting the node
                   3254:                 * content size. If the user don't provide a
                   3255:                 * reference, use a local one. */
                   3256:                if (content_size)
                   3257:                        result = axl_node_get_content_copy (node, content_size);
                   3258:                else
                   3259:                        result = axl_node_get_content_copy (node, &_content_size);
                   3260:                break;
                   3261:        default:
                   3262:                /* if reached this place, only positive values from 2
                   3263:                 * up to N are found */
                   3264:                result = axl_new (char, total_size + 1);
                   3265:                if (content_size)
                   3266:                        *content_size = total_size;
                   3267:                else
                   3268:                        _content_size = total_size;
                   3269:                
                   3270:                /* now copy all content found */
                   3271:                axl_node_get_content_trans_copy (node->first, result);
                   3272:        }
                   3273:        
                   3274: 
                   3275:        /* check result returned */
                   3276:         if (result == NULL || strlen (result) == 0) {
                   3277:                /* do not perform a copy here, it is already done by
                   3278:                 * get_content_copy, even in error */
                   3279:                 return result;
                   3280:        }
                   3281: 
                   3282:        /* translate all references that performs the entities to the
                   3283:         * replacement text. */
                   3284:        if (content_size)
                   3285:                return axl_node_content_translate_defaults (result, content_size);
                   3286:        return axl_node_content_translate_defaults (result, &_content_size);
                   3287: }
                   3288: 
                   3289: 
                   3290: /** 
                   3291:  * @brief Allows to configure a child node to the given parent.
                   3292:  *
                   3293:  * This is a fundamental function while building xml document inside
                   3294:  * memory. The way the xml nodes are linked to conform the xml
                   3295:  * document structure relay on this function. 
                   3296:  * 
                   3297:  * The idea is that every call to this function makes the <b>child
                   3298:  * </b> xml node to be placed at the end of the current item child
                   3299:  * set, that represents current child list for the provided
                   3300:  * <b>parent</b>.
                   3301:  *
                   3302:  * One important question while using this function is that you must
                   3303:  * not reuse the same xml node reference, adding it several time to
                   3304:  * the same parent (or different parents). You must create a new xml
                   3305:  * node reference (axl_node_create) for every call you do to this
                   3306:  * function.
                   3307:  * 
                   3308:  * So, to build the following structure:
                   3309:  * \code
                   3310:  * <document>
                   3311:  *   <child1 />
                   3312:  *   <child2 />
                   3313:  * </document>
                   3314:  * \endcode
                   3315:  * 
                   3316:  * You must perform the following operations:
                   3317:  * \code
                   3318:  * axlNode * parent;
                   3319:  * axlNode * child;
                   3320:  * 
                   3321:  * // create the parent node 
                   3322:  * parent = axl_node_create ("document");
                   3323:  *
                   3324:  * // create the first child 
                   3325:  * child = axl_node_create ("child1");
                   3326:  *
                   3327:  * // set it to the parent 
                   3328:  * axl_node_set_child (parent, child);
                   3329:  *
                   3330:  * // create the second child 
                   3331:  * child = axl_node_create ("child2");
                   3332:  *
                   3333:  * // set it to the parent 
                   3334:  * axl_node_set_child (parent, child);
                   3335:  *
                   3336:  * \endcode
                   3337:  *
                   3338:  * See also \ref axl_node_set_child_after which could help you adding
                   3339:  * new nodes not using a parent node as a reference but a brother
                   3340:  * node.
                   3341:  *
                   3342:  * @param parent The parent node.
                   3343:  *
                   3344:  * @param child The child node. The child node must be a deep
                   3345:  * copy. Passing several references, pointing to the same value, will
                   3346:  * cause to seg fault the program at the time the parent child is
                   3347:  * deallocated. 
                   3348:  */
                   3349: void      axl_node_set_child (axlNode * parent, axlNode * child)
                   3350: {
                   3351:        axl_return_if_fail (parent);
                   3352:        axl_return_if_fail (child);
                   3353: 
                   3354:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "received parent=0x%x and child=0x%x",  parent, child);
                   3355: 
                   3356:        /* set a xml node child */
                   3357:        axl_item_set_child (parent, ITEM_NODE, child);
                   3358: 
                   3359:         return;
                   3360: }
                   3361: 
                   3362: /** 
                   3363:  * @brief Sets a new child after the node provided, using it as a
                   3364:  * reference.
                   3365:  *
                   3366:  * This function is useful to allow configuring new childs placed
                   3367:  * after some particular node. The child configured will be placed
                   3368:  * after the reference and child of the reference's parent node.
                   3369:  * 
                   3370:  * @param reference The xml node acting as a reference.
                   3371:  * @param child The new xml node child to configure.
                   3372:  */
                   3373: void      axl_node_set_child_after    (axlNode * reference,
                   3374:                                       axlNode * child)
                   3375: {
                   3376:        /* call to the item implementation */
                   3377:        axl_item_set_after (reference->holder, ITEM_NODE, child);
                   3378: 
                   3379:        return;
                   3380: }
                   3381: 
                   3382: /** 
                   3383:  * @brief Allows to replace a selected node with a new reference
                   3384:  * inside its context (updating all references: next, previous and
                   3385:  * parent).
                   3386:  *
                   3387:  * The \ref axlNode replaced will be unreference according to dealloc
                   3388:  * value. 
                   3389:  * 
                   3390:  * @param node The node to be replaced by <b>new_node</b> reference.
                   3391:  *
                   3392:  * @param new_node The node that will replace <b>node</b> reference.
                   3393:  *
                   3394:  * @param dealloc Signal if <b>node</b> must be deallocated after the
                   3395:  * replace operation.
                   3396:  */
                   3397: void      axl_node_replace             (axlNode   * node, 
                   3398:                                        axlNode   * new_node,
                   3399:                                        axl_bool    dealloc)
                   3400: {
                   3401:        axlItem * p_item;
                   3402: 
                   3403:        axl_return_if_fail (node);
                   3404:        axl_return_if_fail (new_node);
                   3405: 
                   3406:        if (axl_item_get_parent (node->holder) == NULL) {
                   3407:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "replacing the root node=<%s> with <%s>..", 
                   3408:                           axl_node_get_name (node), axl_node_get_name (new_node));
                   3409:                /* seems to be a root document */
                   3410:                if (axl_item_get_doc (node->holder) != NULL) {
                   3411:                        axl_doc_set_root (axl_item_get_doc (node->holder), new_node);
                   3412:                }
                   3413:        } else {
                   3414: 
                   3415:                /* check for holder reference */
                   3416:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "replacing a non-root node=<%s> with <%s>..",
                   3417:                           axl_node_get_name (node), axl_node_get_name (new_node));
                   3418:                if (node->holder != NULL) {
                   3419: 
                   3420:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "axl item holder is defined for node=<%s>",
                   3421:                                   axl_node_get_name (node));
                   3422:                        /* get a reference to the holder item */
                   3423:                        p_item       = node->holder;
                   3424: 
                   3425:                        /* configure the new node */
                   3426:                        p_item->data = new_node;
                   3427: 
                   3428:                        /* nullify the holder reference, and configure
                   3429:                         * the holder reference in the node */
                   3430:                        node->holder     = NULL;
                   3431:                        new_node->holder = p_item;
                   3432:                        
                   3433:                } /* end if */
                   3434:        }
                   3435: 
                   3436:        /* dealloc node if configured so */
                   3437:        if (dealloc) {
                   3438:                /* free the node */
                   3439:                axl_node_free (node);
                   3440:        }
                   3441:        
                   3442:        return;
                   3443: }
                   3444: 
                   3445: /** 
                   3446:  * @brief Allows to remove the selected reference from the document
                   3447:  * containing it.
                   3448:  *
                   3449:  * The function remove the selected reference from the document. If
                   3450:  * the node asked to be removed is the root one, the node won't be
                   3451:  * removed because the \ref axl_doc_set_root doesn't accept to remove
                   3452:  * the root node.  
                   3453:  *
                   3454:  * All childs hold by the node removed from the document will also be
                   3455:  * removed if dealloc is selected.
                   3456:  * 
                   3457:  * @param node The node to remove.
                   3458:  *
                   3459:  * @param dealloc \ref axl_true to also dealloc the memory used by the
                   3460:  * node. Setting this parameter to \ref axl_false only unlinks the
                   3461:  * node from the document making possible to reuse the node in another
                   3462:  * part of the document or to move the node to a different document.
                   3463:  */
                   3464: void      axl_node_remove             (axlNode  * node,
                   3465:                                       axl_bool   dealloc)
                   3466: {
                   3467:        axlItem * item;
                   3468:        axl_return_if_fail (node);
                   3469: 
                   3470:        /* get a reference to the item element */
                   3471:        item = node->holder;
                   3472: 
                   3473:        /* check if the node is the root node of its document */
                   3474:        if (item != NULL && item->doc != NULL) {
                   3475:                if (axl_doc_get_root (item->doc) == node) {
                   3476:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "attempting to dettach the root node from the document, nullify");
                   3477:                        axl_doc_set_root (item->doc, NULL);
                   3478:                } /* end if */
                   3479:        } /* end if */
                   3480:        
                   3481:        if (axl_item_get_parent (item) != NULL) {
                   3482: 
                   3483:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "doing reference relocation (remove operation) for=<%s>",
                   3484:                           node->name);
                   3485:                
                   3486:                /* make previous node to point to the new node */
                   3487:                if (item->previous != NULL) {
                   3488:                        item->previous->next = item->next;
                   3489:                }
                   3490:                
                   3491:                /* make next node to point to the new node */
                   3492:                if (item->next != NULL) {
                   3493:                        item->next->previous = item->previous;
                   3494:                }
                   3495: 
                   3496:                /* now, update the parent reference */
                   3497:                if (item->previous == NULL) {
                   3498:                        /* seems the node is the first child of the parent,
                   3499:                         * update the reference */
                   3500:                        item->parent->first = item->next;
                   3501:                }
                   3502:                
                   3503:                if (item->next == NULL) {
                   3504:                        /* seems the node is the last child of the parent,
                   3505:                         * update the reference */
                   3506:                        item->parent->last = item->previous;
                   3507:                }
                   3508: 
                   3509:                if (item != NULL) {
                   3510:                        /* disconnect the item */
                   3511:                        item->previous = NULL;
                   3512:                        item->next     = NULL;
                   3513:                } /* end if */
                   3514: 
                   3515:        } /* end if */
                   3516: 
                   3517:        /* dealloc node if configured so */
                   3518:        if (dealloc) {
                   3519:                /* free the node */
                   3520:                axl_node_free (node);
                   3521:        }
                   3522:        
                   3523:        return;
                   3524: }
                   3525: 
                   3526: /** 
                   3527:  * @brief Supposing the node is attached to a xml document (\ref
                   3528:  * axlDoc), this function allows to deattach the node from the
                   3529:  * document that is holding it.
                   3530:  * 
                   3531:  * This function is useful while requiring to reallocate nodes from
                   3532:  * parent to parent, making the parent node that is holding it to
                   3533:  * cancel its references to the node, decreasing all internal counts
                   3534:  * to the node, etc.
                   3535:  *
                   3536:  * If the node isn't attached to any document, the function does
                   3537:  * nothing.
                   3538:  * 
                   3539:  * @param node The node to deattach.
                   3540:  */
                   3541: void axl_node_deattach (axlNode * node)
                   3542: {
                   3543:        axl_return_if_fail (node);
                   3544: 
                   3545:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "deattaching node..");
                   3546: 
                   3547:        /* call to remove */
                   3548:        axl_node_remove (node, axl_false);
                   3549: 
                   3550:        return;
                   3551: }
                   3552: 
                   3553: /** 
                   3554:  * @brief Allows to configure that the given node have child nodes.
                   3555:  *
                   3556:  * <b>DEPRECATED:</b> The function doesn't perform any operation. See
                   3557:  * \ref axl_node_have_childs.
                   3558:  * 
                   3559:  * @param node The node to configure.
                   3560:  *
                   3561:  * @param childs The child configuration, \ref axl_true to notify that
                   3562:  * the node have childs, otherwise, \ref axl_false is returned.
                   3563:  */
                   3564: void      axl_node_set_have_childs (axlNode * node, axl_bool childs)
                   3565: {
                   3566:        /* do nothing */
                   3567:        return;
                   3568: }
                   3569: 
                   3570: /** 
                   3571:  * @brief Allows to get current childs configuration from the given
                   3572:  * xml node (\ref axlNode).
                   3573:  *
                   3574:  * An xml node (represented by an \ref axlNode) is considered to have
                   3575:  * childs only if it has more xml child nodes. The content is not
                   3576:  * considered be a child. See \ref axl_node_is_empty for more
                   3577:  * information.
                   3578:  * 
                   3579:  * @param node The \ref axlNode reference.
                   3580:  * 
                   3581:  * @return An \ref axl_true if the \ref axlNode have childs or \ref
                   3582:  * axl_false if not.
                   3583:  */
                   3584: axl_bool          axl_node_have_childs        (axlNode * node)
                   3585: {
                   3586:        axlItem * item;
                   3587: 
                   3588:        axl_return_val_if_fail (node, axl_false);
                   3589: 
                   3590:        item = node->first;
                   3591:        while (item != NULL) {
                   3592:                /* check item type */
                   3593:                if (axl_item_get_type (item) == ITEM_NODE)
                   3594:                        return axl_true;
                   3595: 
                   3596:                /* go to the next */
                   3597:                item = item->next;
                   3598: 
                   3599:        } /* end while */
                   3600: 
                   3601:        /* return axl_false because no item was found with ITEM_NODE
                   3602:         * type */
                   3603:        return axl_false;
                   3604: }
                   3605: 
                   3606: /** 
                   3607:  * @internal Function that allows to check if the provided node have
                   3608:  * childs, including in the list, nodes, comments, 
                   3609:  * 
                   3610:  * @param node 
                   3611:  * 
                   3612:  * @return 
                   3613:  */
                   3614: axl_bool          axl_node_have_childs_aux        (axlNode * node)
                   3615: {
                   3616:        axlItem * item;
                   3617: 
                   3618:        axl_return_val_if_fail (node, axl_false);
                   3619: 
                   3620:        item = node->first;
                   3621:        while (item != NULL) {
                   3622:                /* check item type */
                   3623:                if (axl_item_get_type (item) == ITEM_NODE || 
                   3624:                    axl_item_get_type (item) == ITEM_PI || 
                   3625:                    axl_item_get_type (item) == ITEM_COMMENT)
                   3626:                        return axl_true;
                   3627: 
                   3628:                /* go to the next */
                   3629:                item = item->next;
                   3630: 
                   3631:        } /* end while */
                   3632: 
                   3633:        /* return axl_false because no item was found with ITEM_NODE
                   3634:         * type */
                   3635:        return axl_false;
                   3636: }
                   3637: 
                   3638: /** 
                   3639:  * @brief Allows to get a particular child node from the given node
                   3640:  * (\ref axlNode).
                   3641:  *
                   3642:  * <i><b>NOTE:</b> This function isn't XML Namespace aware. You must
                   3643:  * use \ref axl_ns_node_get_child_called instead. See \ref
                   3644:  * axl_ns_doc_validate. </i>
                   3645:  * 
                   3646:  * @param parent The parent node where the child will be looked up.
                   3647:  *
                   3648:  * @param name The name for the child to search.
                   3649:  * 
                   3650:  * @return A refernce to a \ref axlNode or NULL if no child exists
                   3651:  * called by the name provided, inside the node provided.
                   3652:  */
                   3653: axlNode * axl_node_get_child_called   (axlNode * parent, const char * name)
                   3654: {
                   3655:        axlNode * node;
                   3656:        axlItem * item;
                   3657:        
                   3658:        axl_return_val_if_fail (parent, NULL);
                   3659:        axl_return_val_if_fail (name, NULL);
                   3660: 
                   3661:        /* if the child list is not defined, assume there is no node
                   3662:         * called the name requested */
                   3663:        if (parent->first == NULL)
                   3664:                return NULL;
                   3665:        
                   3666:        /* if no childs, no result */
                   3667:        item = parent->first;
                   3668:        while (item != NULL) {
                   3669:                /* check item type */
                   3670:                if (axl_item_get_type (item) == ITEM_NODE) {
                   3671:                        /* get a reference to the node */
                   3672:                        node = item->data;
                   3673: 
                   3674:                        /* compare for find the child */ 
                   3675:                        if (NODE_CMP_NAME (node, name))
                   3676:                                return node;
                   3677:                        
                   3678:                } /* end if */
                   3679: 
                   3680:                /* next child */
                   3681:                item = axl_item_get_next (item);
                   3682:        }
                   3683: 
                   3684:        /* no child was found */
                   3685:        return NULL;
                   3686: }
                   3687: 
                   3688: /** 
                   3689:  * @brief Allows to find the first child called <b>name</b>, inside
                   3690:  * all childs (including its descendants) held by the parent provided.
                   3691:  *
                   3692:  * This function is similar to \ref axl_node_get_child_called but
                   3693:  * though it will also look for a child node called as provided not
                   3694:  * only in direct childs but also on its all descendants.
                   3695:  *
                   3696:  * If you are looking for a function to search for a particular child
                   3697:  * node inside direct childs stored for the provided parent, then you
                   3698:  * must use \ref axl_node_get_child_called.
                   3699:  *
                   3700:  * There is also a convenience function that allows to perform a
                   3701:  * lookup using as a reference a document (using the root node from
                   3702:  * it): \ref axl_doc_find_called.
                   3703:  *
                   3704:  * <i><b>NOTE:</b> This function isn't XML Namespace aware. You must
                   3705:  * use \ref axl_ns_node_find_called instead. See \ref
                   3706:  * axl_ns_doc_validate. </i>
                   3707:  *
                   3708:  * @param parent The parent where the lookup will be produced.
                   3709:  *
                   3710:  * @param name The name of the child to be looked up.
                   3711:  * 
                   3712:  * @return A reference to the node found (first instaned matching the
                   3713:  * name) or NULL if it fails to find a child.
                   3714:  */
                   3715: axlNode * axl_node_find_called    (axlNode * parent, const char * name)
                   3716: {
                   3717:        axlNode * node;
                   3718:        axlNode * child;
                   3719: 
                   3720:        /* for the first child found */
                   3721:        node = axl_node_get_first_child (parent);
                   3722:        while (node != NULL) {
                   3723:                /* check and return the node found */
                   3724:                if (NODE_CMP_NAME (node, name))
                   3725:                        return node;
                   3726:                
                   3727:                /* get next */
                   3728:                node = axl_node_get_next (node);
                   3729:        } /* end while */
                   3730: 
                   3731:        /* now, for all childs, try to look for the node */
                   3732:        node = axl_node_get_first_child (parent);
                   3733:        while (node != NULL) {
                   3734:                /* make the search */
                   3735:                child = axl_node_find_called (node, name);
                   3736:                
                   3737:                /* child found, return the reference */
                   3738:                if (child != NULL)
                   3739:                        return child;
                   3740:                
                   3741:                /* get next */
                   3742:                node = axl_node_get_next (node);
                   3743:        } /* end while */
                   3744: 
                   3745:        /* child note found */
                   3746:        return NULL;
                   3747: }
                   3748: 
                   3749: /** 
                   3750:  * @brief Allows to get the child that is located at the given
                   3751:  * position, inside the given parent node.
                   3752:  *
                   3753:  * @param parent The parent node where the child will be looked up.
                   3754:  *
                   3755:  * @param position The position where the child will be looked up. The
                   3756:  * values for the position ranges from 0 up to (N - 1).
                   3757:  * 
                   3758:  * @return A reference to the child node \ref axlNode or NULL if fails. 
                   3759:  */
                   3760: axlNode * axl_node_get_child_nth      (axlNode * parent, int position)
                   3761: {
                   3762:        int       iterator;
                   3763:        axlItem * item;
                   3764: 
                   3765:        /* perform some environment checks */
                   3766:        axl_return_val_if_fail (parent, NULL);
                   3767: 
                   3768:        /* check for first reference */
                   3769:        if (parent->first == NULL) {
                   3770:                return NULL;
                   3771:        }
                   3772: 
                   3773:        /* get the first item */
                   3774:        item = parent->first;
                   3775: 
                   3776:        /* get the first node found */
                   3777:        iterator = 0;
                   3778:        while (item != NULL) {
                   3779:                /* check the item type */
                   3780:                if (axl_item_get_type (item) == ITEM_NODE) {
                   3781:                        if (iterator == position) {
                   3782:                                return item->data;
                   3783:                        } else
                   3784:                                iterator++;
                   3785:                } /* end if */
                   3786: 
                   3787:                /* get the next */
                   3788:                item = item->next;
                   3789: 
                   3790:        } /* end while */
                   3791: 
                   3792:        /* no first child found */
                   3793:        return NULL;
                   3794: }
                   3795: 
                   3796: /** 
                   3797:  * @brief Allows to get the number of childs that the provided node
                   3798:  * has.
                   3799:  * 
                   3800:  * @param parent The node where the number of childs is being queried.
                   3801:  * 
                   3802:  * @return The number of childs or -1 if fails.
                   3803:  */
                   3804: int       axl_node_get_child_num      (axlNode * parent)
                   3805: {
                   3806:        int       count;
                   3807:        axlItem * item;
                   3808: 
                   3809:        /* perform some environment checks */
                   3810:        axl_return_val_if_fail (parent, -1);
                   3811: 
                   3812:        /* init values */
                   3813:        count = 0;
                   3814:        item  = parent->first;
                   3815: 
                   3816:        /* for each child inside the parent node */
                   3817:        while (item != NULL) {
                   3818:                
                   3819:                /* check item type */
                   3820:                if (axl_item_get_type (item) == ITEM_NODE)
                   3821:                        count++;
                   3822:                
                   3823:                /* get the next */
                   3824:                item = item->next;
                   3825: 
                   3826:        } /* end while */
                   3827: 
                   3828:        /* return the number of chils */
                   3829:        return count;
                   3830: }
                   3831: 
                   3832: 
                   3833: /** 
                   3834:  * @brief Allows to get childs nodes from the given xml node (\ref
                   3835:  * axlNode).
                   3836:  *
                   3837:  * This function creates a newly allocated list. In the case you want
                   3838:  * to iterate over all nodes, it is better to use something similar to
                   3839:  * this:
                   3840:  *
                   3841:  * \code
                   3842:  * axlNode * child;
                   3843:  *
                   3844:  * // get the first child 
                   3845:  * child = axl_node_get_first_child (parent);
                   3846:  * 
                   3847:  * // iterate over all nodes 
                   3848:  * while (child != NULL) {
                   3849:  *
                   3850:  *    // do something with the child 
                   3851:  *    do_some_work (child);
                   3852:  * 
                   3853:  *    // update the reference to the next child
                   3854:  *    child = axl_node_get_next (child);   
                   3855:  * }
                   3856:  * \endcode
                   3857:  *
                   3858:  * @param node The node where the childs will be returned.
                   3859:  * 
                   3860:  * @return An \ref axlList containing \ref axlNode items or NULL if it
                   3861:  * fails. The list returned MUST be deallocated.
                   3862:  */
                   3863: axlList * axl_node_get_childs         (axlNode * node)
                   3864: {
                   3865:        axlItem * child;
                   3866:        axlList * result;
                   3867: 
                   3868:        axl_return_val_if_fail (node, NULL);
                   3869:        
                   3870:        /* create the result list without destroy function */
                   3871:        result  = axl_list_new (__axl_node_equal, NULL);
                   3872:        
                   3873:        /* get the first child */
                   3874:        child = node->first;
                   3875: 
                   3876:        while (child != NULL) {
                   3877:                /* check the node type */
                   3878:                if (axl_item_get_type (child) == ITEM_NODE) {
                   3879:                        /* add the child to the list */
                   3880:                        axl_list_add (result, child->data);
                   3881:                        
                   3882:                } /* end if */
                   3883: 
                   3884:                /* update the reference to the next child */
                   3885:                child = child->next;
                   3886:        } /* end while */
                   3887: 
                   3888:        /* return current childs */
                   3889:        return result;
                   3890: }
                   3891: 
                   3892: axl_bool __axl_node_are_equal_attr (axlPointer key, 
                   3893:                                    axlPointer value, 
                   3894:                                    axlPointer user_data, 
                   3895:                                    axlPointer user_data2)
                   3896: {
                   3897:        char                * value2;
                   3898:        axl_bool                * result = user_data2;
                   3899:        
                   3900:        /* get the attr value and compare it with data */
                   3901:        value2 = axl_hash_get ((axlHash *) user_data, (char *) key);
                   3902: 
                   3903:        if (! axl_cmp ((char *) value, value2)) {
                   3904:                /* flag that node attributes aren't equal */
                   3905:                (* result) = axl_false;
                   3906: 
                   3907:                /* stop foreach */
                   3908:                return axl_true;
                   3909:        }
                   3910:                        
                   3911:        /* make the process to continue */
                   3912:        return axl_false;
                   3913: }
                   3914: 
                   3915: /** 
                   3916:  * @brief Allows to check if the provided references represents two
                   3917:  * equivalent nodes.
                   3918:  *
                   3919:  * The function will check node name, node content and node attributes
                   3920:  * and its values.
                   3921:  * 
                   3922:  * @param node The node to check.
                   3923:  * @param node2 The second node to check.
                   3924:  * @param error Optional reference to an \ref axlError where the particular differ is reported.
                   3925:  * 
                   3926:  * @return axl_true if both nodes are equivalent or axl_false if not.
                   3927:  */
                   3928: axl_bool          axl_node_are_equal_full          (axlNode * node, axlNode * node2, axlError ** error)
                   3929: {
                   3930:        axl_bool result;
                   3931:        
                   3932:        if (node == NULL) {
                   3933:                axl_error_report (error, -1, "Nodes differs because first node reference is NULL");
                   3934:                return axl_false;
                   3935:        } /* end if */
                   3936:        if (node2 == NULL) {
                   3937:                axl_error_report (error, -1, "Nodes differs because second node reference is NULL");
                   3938:                return axl_false;
                   3939:        } /* end if */
                   3940: 
                   3941:        /* check document root name */
                   3942:        if (! axl_cmp (axl_node_get_name (node), axl_node_get_name (node2))) {
                   3943:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "node names aren't equal <%s> != <%s>",
                   3944:                           node->name, node2->name);
                   3945:                axl_error_report (error, -1, "node names aren't equal <%s> != <%s>",
                   3946:                                  node->name, node2->name);
                   3947:                return axl_false;
                   3948:        }
                   3949: 
                   3950:        /* check empty ness configuration */
                   3951:        if (axl_node_is_empty (node) != axl_node_is_empty (node2)) {
                   3952:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "emptyness configuration differs <%s> != <%s>",
                   3953:                           node->name, node2->name);
                   3954: 
                   3955:                axl_error_report (error, -1, "emptyness configuration differs <%s> != <%s>",
                   3956:                                  node->name, node2->name);
                   3957:                return axl_false;
                   3958:        }
                   3959:        
                   3960:        /* check childs configuration */
                   3961:        if (axl_node_have_childs (node) != axl_node_have_childs (node2)) {
                   3962:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "childs configuration differs <%s> != <%s>",
                   3963:                           node->name, node2->name);
                   3964:                axl_error_report (error, -1, "childs configuration differs <%s> != <%s>",
                   3965:                                  node->name, node2->name);
                   3966:                return axl_false;
                   3967:        }
                   3968: 
                   3969:        /* check childs number */
                   3970:        if (axl_node_get_child_num (node) != axl_node_get_child_num (node2)) {
                   3971:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "child number differs <%s>(%d) != <%s>(%d)",
                   3972:                           node->name, axl_node_get_child_num (node), node2->name, axl_node_get_child_num (node2));
                   3973:                axl_error_report (error, -1, "childs configuration differs <%s> != <%s>",
                   3974:                                  node->name, node2->name);
                   3975:                return axl_false;
                   3976:        }
                   3977: 
                   3978:        /* check attribute values */
                   3979:        if ((node->attributes != NULL && node2->attributes != NULL)) {
                   3980: 
                   3981:                /* check the number of attributes that has the hash */
                   3982:                if (node->attr_num != node2->attr_num) {
                   3983:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "both nodes have different number of attributes (<%s>:%d != <%s>:%d)",
                   3984:                                   node->name, node->attr_num, 
                   3985:                                   node2->name, node2->attr_num);
                   3986:                        axl_error_report (error, -1, "both nodes have different number of attributes (<%s>:%d != <%s>:%d)",
                   3987:                                   node->name, node->attr_num, 
                   3988:                                   node2->name, node2->attr_num);
                   3989:                        return axl_false;
                   3990:                }
                   3991: 
                   3992:                /* now both hashes */
                   3993:                result = axl_true;
                   3994:                if (node->attr_num <= 10) {
                   3995:                        /* check both list are equal */
                   3996:                        result = __axl_node_attr_list_is_equal ((axlNodeAttr *) node->attributes, (axlNodeAttr *) node2->attributes);
                   3997:                } else {
                   3998:                        /* check both hashes are equal */
                   3999:                        axl_hash_foreach2 ((axlHash *) node->attributes, __axl_node_are_equal_attr, (axlHash *) node2->attributes, &result);
                   4000:                }
                   4001: 
                   4002:                if (! result) {
                   4003:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "node attributes differs <%s> != <%s>",
                   4004:                                   node->name, node2->name);
                   4005:                        axl_error_report (error, -1, "node attributes differs <%s> != <%s>",
                   4006:                                          node->name, node2->name);
                   4007:                        /* attribute missmatch */
                   4008:                        return axl_false;
                   4009:                }
                   4010:        } else {
                   4011:                if (node->attributes == NULL && node2->attributes != NULL) {
                   4012:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "node <%s> has no attributes but <%s> has",
                   4013:                                   axl_node_get_name (node), axl_node_get_name (node2));
                   4014:                        axl_error_report (error, -1, "node <%s> has no attributes but <%s> has",
                   4015:                                          axl_node_get_name (node), axl_node_get_name (node2));
                   4016:                        return axl_false;
                   4017:                }
                   4018: 
                   4019:                if (node2->attributes == NULL && node->attributes != NULL) {
                   4020:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "node <%s> has no attributes but <%s> has",
                   4021:                                   axl_node_get_name (node2), axl_node_get_name (node));
                   4022:                        axl_error_report (error, -1, "node <%s> has no attributes but <%s> has",
                   4023:                                          axl_node_get_name (node2), axl_node_get_name (node));
                   4024:                        return axl_false;
                   4025:                }
                   4026: 
                   4027:        } /* end if */
                   4028: 
                   4029:        /* both nodes seems to be equal */
                   4030:        return axl_true;
                   4031: }
                   4032: 
                   4033: /** 
                   4034:  * @brief Allows to check if the provided references represents two
                   4035:  * equivalent nodes.
                   4036:  *
                   4037:  * The function will check node name, node content and node attributes
                   4038:  * and its values.
                   4039:  * 
                   4040:  * @param node The node to check.
                   4041:  * @param node2 The second node to check.
                   4042:  * 
                   4043:  * @return axl_true if both nodes are equivalent or axl_false if not.
                   4044:  */
                   4045: axl_bool          axl_node_are_equal          (axlNode * node, axlNode * node2)
                   4046: {
                   4047:        /* use common implementation */
                   4048:        return axl_node_are_equal_full (node, node2, NULL);
                   4049: }
                   4050: 
                   4051: /** 
                   4052:  * @brief Allows to associate a PI element, including its content to
                   4053:  * the provided node.
                   4054:  *
                   4055:  * See the following function for more information: \ref
                   4056:  * axl_doc_add_pi_target.
                   4057:  *
                   4058:  * @param node The \ref axlNode where the PI element (\ref axlPI) will
                   4059:  * be added.
                   4060:  *
                   4061:  * @param target The PI target name to add.
                   4062:  *
                   4063:  * @param content Optional PI content.
                   4064:  */
                   4065: void      axl_node_add_pi_target            (axlNode * node, 
                   4066:                                             char * target, 
                   4067:                                             char * content)
                   4068: {
                   4069:        axlPI   * pi;
                   4070: 
                   4071:        /* perform some environmental checks */
                   4072:        axl_return_if_fail (node);
                   4073:        axl_return_if_fail (target);
                   4074: 
                   4075:        /* create the PI element */
                   4076:        pi = axl_pi_create (target, content);
                   4077: 
                   4078:        /* set the new process instruction found */
                   4079:        axl_item_set_child (node, ITEM_PI, pi);
                   4080: 
                   4081:        return;
                   4082: }
                   4083: 
                   4084: 
                   4085: /** 
                   4086:  * @brief Allows to check if the provided Processing instruction
                   4087:  * target is defined on the given xml node document (\ref axlNode).
                   4088:  *
                   4089:  * Processing instruction are a way to configure the xml node document
                   4090:  * with processing information to instruct the application level that
                   4091:  * is going to consume the XML information.
                   4092:  *
                   4093:  * @param node The \ref axlNode where the processing instruction will
                   4094:  * be read.
                   4095:  *
                   4096:  * @param pi_target The process instruction name.
                   4097:  * 
                   4098:  * @return axl_true is the processing instruction is defined,
                   4099:  * otherwise axl_false is returned.
                   4100:  */
                   4101: axl_bool          axl_node_has_pi_target            (axlNode * node, 
                   4102:                                                     char    * pi_target)
                   4103: {
                   4104:        axlPI   * pi;
                   4105:        axlItem * item;
                   4106:        
                   4107:        axl_return_val_if_fail (node,      axl_false);
                   4108:        axl_return_val_if_fail (pi_target, axl_false);
                   4109: 
                   4110:        /* assume the pi target doesn't exist if it is not
                   4111:         * initialized */
                   4112:        item = node->first;
                   4113:        while (item != NULL) {
                   4114:                
                   4115:                /* check the type */
                   4116:                if (axl_item_get_type (item) == ITEM_PI) {
                   4117:                        /* get a reference */
                   4118:                        pi = item->data;
                   4119: 
                   4120:                        /* only check the first ocurrency */
                   4121:                        if (axl_cmp (axl_pi_get_name (pi), pi_target))
                   4122:                                return axl_true;
                   4123:                } /* end if */
                   4124: 
                   4125:                /* get the next item */
                   4126:                item = item->next;
                   4127: 
                   4128:        } /* end while */
                   4129: 
                   4130:        return axl_false;
                   4131: }
                   4132: 
                   4133: /** 
                   4134:  * @brief Allows to get current processing instruction content.
                   4135:  * 
                   4136:  * @param node The document where the processing instruction is placed.
                   4137:  *
                   4138:  * @param pi_target The processing instruction target to get current
                   4139:  * content.
                   4140:  * 
                   4141:  * @return An internal reference to the process instruction target
                   4142:  * content. Value returned mustn't be deallocated
                   4143:  */
                   4144: char    * axl_node_get_pi_target_content    (axlNode * node, 
                   4145:                                            char * pi_target)
                   4146: {
                   4147:        axlPI   * pi;
                   4148:        axlItem * item;
                   4149:        
                   4150:        axl_return_val_if_fail (node,      NULL);
                   4151:        axl_return_val_if_fail (pi_target, NULL);
                   4152: 
                   4153:        /* assume the pi target doesn't exist if it is not
                   4154:         * initialized */
                   4155:        item = node->first;
                   4156:        while (item != NULL) {
                   4157:                
                   4158:                /* check the type */
                   4159:                if (axl_item_get_type (item) == ITEM_PI) {
                   4160:                        /* get a reference */
                   4161:                        pi = item->data;
                   4162: 
                   4163:                        /* only check the first ocurrency */
                   4164:                        if (axl_cmp (axl_pi_get_name (pi), pi_target))
                   4165:                                return axl_pi_get_content (pi);
                   4166:                } /* end if */
                   4167: 
                   4168:                /* get the next item */
                   4169:                item = item->next;
                   4170: 
                   4171:        } /* end while */
                   4172: 
                   4173:        return NULL;
                   4174: }
                   4175: 
                   4176: /** 
                   4177:  * @brief Allows to transfer (move from) all childs (including
                   4178:  * comments, content, PI, nodes, etc) from the old parent to the new
                   4179:  * parent.
                   4180:  *
                   4181:  * This function is particular useful while moving content from nodes.
                   4182:  * 
                   4183:  * @param old_parent The old parent node where all childs will be
                   4184:  * removed and placed in the new parent.
                   4185:  *
                   4186:  * @param new_parent The parent node where the content will be
                   4187:  * placed. If the parent node already have childs, the content will be
                   4188:  * appended.
                   4189:  */
                   4190: void      axl_node_transfer_childs          (axlNode * old_parent, 
                   4191:                                             axlNode * new_parent)
                   4192: {
                   4193:        axlItem * item;
                   4194:        axlItem * item_aux;
                   4195:        
                   4196:        /* get the first child for the old parent */
                   4197:        item = old_parent->first;
                   4198:        while (item != NULL) {
                   4199: 
                   4200:                /* get a reference to the next before adding */
                   4201:                item_aux = item->next;
                   4202: 
                   4203:                /* set the item to parent for the new node */
                   4204:                axl_item_set_child_ref (new_parent, item);
                   4205: 
                   4206:                
                   4207:                /* get the next */
                   4208:                item = item_aux;
                   4209: 
                   4210:        } /* end while */
                   4211: 
                   4212:        /* clear reference from previous parent */
                   4213:        old_parent->first     = NULL;
                   4214:        old_parent->last      = NULL;
                   4215:        
                   4216:        return;
                   4217: }
                   4218: 
                   4219: /** 
                   4220:  * @internal Implementation for the public API provided to dump node content.
                   4221:  */
                   4222: axl_bool __axl_node_dump_common (axlNode * node, char ** content, int * size, axl_bool pretty_print, int level, int tabular)
                   4223: {
                   4224:        int    _size;
                   4225:        int    index;
                   4226:        char * result;
                   4227: 
                   4228:        /* check refererences received */
                   4229:        axl_return_val_if_fail (node,    axl_false);
                   4230:        axl_return_val_if_fail (content, axl_false);
                   4231: 
                   4232:        /* get dump size */
                   4233:        _size = axl_node_get_flat_size (node, pretty_print, level, tabular);
                   4234: 
                   4235:        /* dump the content */
                   4236:        result = axl_new (char, _size + 1);
                   4237:        index  = axl_node_dump_at (node, result, 0, pretty_print, level, tabular);
                   4238: 
                   4239:        /* check result */
                   4240:        if (index != _size) {
                   4241:                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "failed to dump xml node, size dump operation mismatch: %d != %d", 
                   4242:                           index, _size);
                   4243:                /* free allocated result */
                   4244:                axl_free (result);
                   4245: 
                   4246:                /* nullify content */
                   4247:                if (size)
                   4248:                        *size = -1;
                   4249:                *content      = NULL;
                   4250:                
                   4251:                return axl_false;
                   4252:        } /* end if */
                   4253: 
                   4254:        /* fill the size */
                   4255:        if (size)
                   4256:                *size = _size;
                   4257:        *content      = result;
                   4258: 
                   4259:        /* return content */
                   4260:        return axl_true;
                   4261: }
                   4262: 
                   4263: /** 
                   4264:  * @brief Allows to dump the xml content taking as starting point the
                   4265:  * xml node provided. 
                   4266:  * 
                   4267:  * @param node The \ref axlNode used as reference and starting point
                   4268:  * to dump.
                   4269:  *
                   4270:  * @param content The reference where the result will be returned.
                   4271:  *
                   4272:  * @param size The reference where the document content size will be
                   4273:  * returned. 
                   4274:  *
                   4275:  * @return The function returns \ref axl_true if the dump operation
                   4276:  * was performed. Otherwise \ref axl_false is returned.
                   4277:  */
                   4278: axl_bool      axl_node_dump                    (axlNode  * node, 
                   4279:                                                char    ** content, 
                   4280:                                                int      * size)
                   4281: {
                   4282:        /* use common implementation for all functions */
                   4283:        return __axl_node_dump_common (node, content, size, axl_false, 0, 0);
                   4284: }
                   4285: 
                   4286: /** 
                   4287:  * @brief Allows to perform a pretty print operation using as
                   4288:  * reference (starting point) the node provided.
                   4289:  * 
                   4290:  * @param node The node to be used as reference for the dump operation.
                   4291:  * 
                   4292:  * @param content A reference to a user defined pointer where the
                   4293:  * content will be placed. Non optional parameter.
                   4294:  *
                   4295:  * @param size A reference to a user defined pointer where the content
                   4296:  * size will be placed. Optional parameter.
                   4297:  * 
                   4298:  * @param tabular How many spaces to be placed on each level.
                   4299:  * 
                   4300:  * @return \ref axl_true if the dump operation was properly done, otherwise
                   4301:  * \ref axl_false is returned.
                   4302:  */
                   4303: axl_bool      axl_node_dump_pretty             (axlNode  * node,
                   4304:                                                char    ** content,
                   4305:                                                int      * size,
                   4306:                                                int        tabular)
                   4307: {
                   4308:        /* use common implementation for all functions */
                   4309:        return __axl_node_dump_common (node, content, size, axl_true, 0, tabular);
                   4310: }
                   4311: 
                   4312: /** 
                   4313:  * @brief Allows to dump the xml document using as reference the node
                   4314:  * provided, at the file path provided.
                   4315:  * 
                   4316:  * @param node The document node reference to use to build the
                   4317:  * content.
                   4318:  *
                   4319:  * @param file_path File path where place the result.
                   4320:  * 
                   4321:  * @return \ref axl_true if the dump operation was done, otherwise \ref axl_false is
                   4322:  * returned.
                   4323:  */
                   4324: axl_bool      axl_node_dump_to_file            (axlNode  * node,
                   4325:                                                char     * file_path)
                   4326: {
                   4327:        char * content;
                   4328:        int    size;
                   4329:        FILE * fd;
                   4330:        int    written;
                   4331: 
                   4332:        /* use common implementation for all functions */
                   4333:        if (!  __axl_node_dump_common (node, &content, &size, axl_true, 0, 0))
                   4334:                return axl_false;
                   4335: 
                   4336:        /* open the file and check */
                   4337: #if defined(AXL_OS_WIN32) && ! defined(__GNUC__)
                   4338:        if (fopen_s (&fd, file_path, "w") != 0) {
                   4339: #else
                   4340:        if ((fd = fopen (file_path, "w")) == NULL) {
                   4341: #endif
                   4342:                /* failed to open the file to dump the content */
                   4343:                axl_free (content);
                   4344: 
                   4345:                return axl_false;
                   4346:        }
                   4347: 
                   4348:        /* dump the content */
                   4349:        written = fwrite (content, 1, size, fd);
                   4350: 
                   4351:        /* free the content */
                   4352:        axl_free (content);
                   4353: 
                   4354:        /* close file */
                   4355:        fclose (fd);
                   4356: 
                   4357:        /* return if we have failed to dump all the content to the
                   4358:         * file or not. */
                   4359:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "returning that the dump was: %s (written:%d == size:%d)", 
                   4360:                   (written == size) ? "OK" : "FAILED", 
                   4361:                   written, size);
                   4362:                   
                   4363:        return (written == size);
                   4364:                
                   4365: }
                   4366: 
                   4367: /** 
                   4368:  * @brief Allows to pretty print dump the xml document using as
                   4369:  * reference the node provided, at the file path provided.
                   4370:  * 
                   4371:  * @param node The document node reference to use to build the
                   4372:  * content.
                   4373:  *
                   4374:  * @param file_path File path where place the result.
                   4375:  *
                   4376:  * @param tabular How many spaces to be placed at each level.
                   4377:  * 
                   4378:  * @return \ref axl_true if the dump operation was done, otherwise \ref axl_false is
                   4379:  * returned.
                   4380:  */
                   4381: axl_bool      axl_node_dump_pretty_to_file     (axlNode  * node,
                   4382:                                                char     * file_path,
                   4383:                                                int        tabular)
                   4384: {
                   4385:        char * content;
                   4386:        int    size;
                   4387:        FILE * fd;
                   4388:        int    written;
                   4389: 
                   4390:        /* use common implementation for all functions */
                   4391:        if (!  __axl_node_dump_common (node, &content, &size, axl_true, 0, tabular))
                   4392:                return axl_false;
                   4393: 
                   4394:        /* open the file and check */
                   4395: #if defined(AXL_OS_WIN32) && ! defined(__GNUC__)
                   4396:        if (fopen_s (&fd, file_path, "w") != 0) {
                   4397: #else
                   4398:        if ((fd = fopen (file_path, "w")) == NULL) {
                   4399: #endif
                   4400:                /* failed to open the file to dump the content */
                   4401:                axl_free (content);
                   4402: 
                   4403:                return axl_false;
                   4404:        }
                   4405: 
                   4406:        /* dump the content */
                   4407:        written = fwrite (content, 1, size, fd);
                   4408: 
                   4409:        /* free the content */
                   4410:        axl_free (content);
                   4411: 
                   4412:        /* close file */
                   4413:        fclose (fd);
                   4414: 
                   4415:        /* return if we have failed to dump all the content to the
                   4416:         * file or not. */
                   4417:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "returning that the dump was: %s (written:%d == size:%d)", 
                   4418:                   (written == size) ? "OK" : "FAILED", 
                   4419:                   written, size);
                   4420:                   
                   4421:        return (written == size);
                   4422: }
                   4423: 
                   4424: /** 
                   4425:  * @brief Allows to get a list which contains \ref axlPI nodes,
                   4426:  * representing all process instruction that the \ref axlNode (xml
                   4427:  * document node) has.
                   4428:  *
                   4429:  * While using PI, you can use the following functions to get PI
                   4430:  * information:
                   4431:  * 
                   4432:  *  - \ref axl_node_has_pi_target
                   4433:  *  - \ref axl_node_get_pi_target_content
                   4434:  *
                   4435:  * However, this function will return first ocurrence for PI found
                   4436:  * inside the xml document. If you don't use repeated PI elements, you
                   4437:  * won't find problems, but, if you need to iterate ever all PI found
                   4438:  * or you are using repeated PI, you can use this function as follows
                   4439:  * to get current pi elements:
                   4440:  *
                   4441:  * \code
                   4442:  * void show_all_pi (axlNode * node) 
                   4443:  * {
                   4444:  *      int       iterator;
                   4445:  *      axlPI   * pi;
                   4446:  *      axlList * PIs;
                   4447:  *
                   4448:  *      // get all PI target that the node has
                   4449:  *      PIs      = axl_node_get_pi_target_list (node);
                   4450:  *      iterator = 0;
                   4451:  *
                   4452:  *      while (iterator < axl_list_length (PIs)) {
                   4453:  *            // get next pi stored 
                   4454:  *            pi = axl_list_get_nth (PIs, iterator);
                   4455:  *
                   4456:  *            // do some stuff 
                   4457:  *            printf ("PI found target name=%s, content=%s\n",
                   4458:  *                    axl_pi_get_name (pi),
                   4459:  *                    axl_pi_get_content (pi));
                   4460:  *            
                   4461:  *            // update the iterator
                   4462:  *            iterator++;
                   4463:  *      }
                   4464:  *
                   4465:  *      // once finished, free the list 
                   4466:  *      axl_list_free (PIs);
                   4467:  *      return;
                   4468:  * }
                   4469:  * \endcode
                   4470:  * 
                   4471:  * @param node The xml node (\ref axlNode) where the process
                   4472:  * instruction will be returned.
                   4473:  * 
                   4474:  * @return A reference to the list of processing instruction that the
                   4475:  * xml node (\ref axlNode) has. The returned list, if defined, must be
                   4476:  * deallocated.
                   4477:  */
                   4478: axlList * axl_node_get_pi_target_list       (axlNode * node)
                   4479: {
                   4480:        axlList * result = NULL;
                   4481:        axlItem * item;
                   4482:        
                   4483:        axl_return_val_if_fail (node, NULL);
                   4484: 
                   4485:        /* assume the pi target doesn't exist if it is not
                   4486:         * initialized */
                   4487:        item = node->first;
                   4488:        while (item != NULL) {
                   4489:                
                   4490:                /* check the type */
                   4491:                if (axl_item_get_type (item) == ITEM_PI) {
                   4492:                        /* create the result list */
                   4493:                        if (result == NULL)
                   4494:                                result = axl_list_new (axl_list_always_return_1, (axlDestroyFunc) axl_pi_free);  
                   4495: 
                   4496:                        /* add the list */
                   4497:                        axl_list_add (result, item->data);
                   4498:                        
                   4499:                } /* end if */
                   4500: 
                   4501:                /* get the next item */
                   4502:                item = item->next;
                   4503: 
                   4504:        } /* end while */
                   4505: 
                   4506:        return result;
                   4507: }
                   4508: 
                   4509: axl_bool __axl_node_get_flat_size_attributes_foreach (axlPointer attr, 
                   4510:                                                      axlPointer value, 
                   4511:                                                      axlPointer user_data)
                   4512: {
                   4513:        int * length = user_data;
                   4514: 
                   4515:        /* " attribute='value' */
                   4516:        (*length) += 4 + strlen ((char*) attr) + strlen ((char*) value);
                   4517: 
                   4518:        /* make the process to continue */
                   4519:        return axl_false;
                   4520: }
                   4521: 
                   4522: /** 
                   4523:  * @internal
                   4524:  * @brief Returns the space required to write the attribute part.
                   4525:  */
                   4526: int __axl_node_get_flat_size_attributes (axlNode * node)
                   4527: {
                   4528: 
                   4529:        int            length = 0;
                   4530:        axlNodeAttr  * attr   = NULL;
                   4531:        
                   4532:        /* if attribute list is not defined just return 0 */
                   4533:        if (node->attributes == NULL)
                   4534:                return 0;
                   4535: 
                   4536:        /* perform a foreach and accumulate */
                   4537:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "get flat size for node <%s>", 
                   4538:                   axl_node_get_name (node));
                   4539:        if (node->attr_num <= 10) {
                   4540:                /* get the first reference */
                   4541:                attr = (axlNodeAttr *) node->attributes;
                   4542:                while (attr != NULL) {
                   4543:                        /* call to get length */
                   4544:                        __axl_node_get_flat_size_attributes_foreach (attr->attribute, attr->value, &length);
                   4545:                        
                   4546:                        /* get the next */
                   4547:                        attr = attr->next;
                   4548:                }
                   4549:                
                   4550:        } else {
                   4551:                /* perform a foreach */
                   4552:                axl_hash_foreach ((axlHash *) node->attributes, __axl_node_get_flat_size_attributes_foreach, &length);
                   4553:        }
                   4554: 
                   4555:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "after foreach flat size for node <%s> is %d", 
                   4556:                   axl_node_get_name (node), length);
                   4557: 
                   4558:        /* return the length */
                   4559:        return length;
                   4560: }
                   4561: 
                   4562: /** 
                   4563:  * @internal
                   4564:  *
                   4565:  * Returns which the size that the node and its childs will hold if
                   4566:  * the are represented into a flat xml stream.
                   4567:  * 
                   4568:  * @param node The node that is requested its stream xml size.
                   4569:  *
                   4570:  * @param pretty_print If pretty print is activated.
                   4571:  *
                   4572:  * @param level Which is the relative level of the node respected to
                   4573:  * the root node.
                   4574:  * 
                   4575:  * @return The stream size or -1 if fails.
                   4576:  */
                   4577: int       axl_node_get_flat_size            (axlNode * node, axl_bool pretty_print, int level, int tabular)
                   4578: {
                   4579:        int              result    = 0;
                   4580:        axlItem        * item;
                   4581:        axlNodeContent * content;
                   4582:        axl_bool         is_empty;
                   4583:        axl_bool         have_childs;
                   4584: 
                   4585:        axl_return_val_if_fail (node, -1);
                   4586: 
                   4587:        /* get values */
                   4588:        is_empty    = axl_node_is_empty (node);
                   4589:        have_childs = axl_node_have_childs_aux (node);
                   4590: 
                   4591:        if (have_childs || (!have_childs && !is_empty)) {
                   4592:                /* the node is emtpy because it has no content but it has
                   4593:                 * childs:
                   4594:                 *
                   4595:                 * "<" + strlen (node-name) + ">" + ... + "</" + strlen (node-name) + ">" */
                   4596:                result = 5 + (2 * strlen (node->name)) + __axl_node_get_flat_size_attributes (node);
                   4597:                
                   4598:                /* check pretty_print */
                   4599:                if (pretty_print) {
                   4600:                        /* two tabulations plus two carry return \r\n
                   4601:                         * on windows and \n on unix */
                   4602:                        if (have_childs) 
                   4603:                                result += (level * tabular * 2) + 2; 
                   4604:                        else
                   4605:                                result += (level * tabular) + 1; 
                   4606: #ifdef __AXL_OS_WIN32__
                   4607:                        if (have_childs)
                   4608:                                result += 2;
                   4609:                        else
                   4610:                                result ++;
                   4611: #endif
                   4612:                }
                   4613:        } else {
                   4614:                if (is_empty) {
                   4615:                        /* "<" + strlen (node-name) + " />" */
                   4616:                        result = strlen (node->name) + 4 + __axl_node_get_flat_size_attributes (node);
                   4617:                        
                   4618:                        /* check pretty print */
                   4619:                        if (pretty_print) {
                   4620:                                /* one tabular plus one carry return
                   4621:                                 * \r\n on windows and \n on unix */
                   4622:                                result += (level * tabular) + 1;
                   4623: #ifdef __AXL_OS_WIN32__
                   4624:                                result += 1;
                   4625: #endif
                   4626:                        }
                   4627:                        
                   4628:                        /* return sum */
                   4629:                        return result;
                   4630:                }
                   4631:        }
                   4632: 
                   4633:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "node=<%s> count=%d", node->name, result);
                   4634:        
                   4635:        /* get first child */
                   4636:        item = node->first;
                   4637:        while (item != NULL) {
                   4638:                /* according to the type, check a size */
                   4639:                switch (axl_item_get_type (item)) {
                   4640:                case ITEM_NODE:
                   4641:                        /* count how many bytes the node holds */
                   4642:                        result += axl_node_get_flat_size (item->data, pretty_print, level + 1, tabular);
                   4643:                        break;
                   4644:                case ITEM_CONTENT:
                   4645:                        /* content */
                   4646:                        content = (axlNodeContent *) item->data;
                   4647:                        result += content->content_size;
                   4648:                        break;
                   4649:                case ITEM_CDATA:
                   4650:                        /* content + '<![CDATA[' + ']]>' */
                   4651:                        content = (axlNodeContent *) item->data;
                   4652:                        result += content->content_size + 12;
                   4653:                        break;
                   4654:                case ITEM_PI:
                   4655:                        /* get current size */
                   4656:                        result += axl_pi_get_size (item->data);
                   4657:                        break;
                   4658:                case ITEM_COMMENT:
                   4659:                        /* content + '<!-- ' + ' -->' */
                   4660:                        content = (axlNodeContent *) item->data;
                   4661: 
                   4662:                        /* check if the content has already defined white spaces */
                   4663:                        if (content->content[0] == ' ' && content->content[content->content_size - 1] == ' ')
                   4664:                                result += content->content_size + 7;
                   4665:                        else if (content->content[0] != ' ' && content->content[content->content_size - 1] == ' ')
                   4666:                                result += content->content_size + 8;
                   4667:                        else if (content->content[0] == ' ' && content->content[content->content_size - 1] != ' ')
                   4668:                                result += content->content_size + 8;
                   4669:                        else
                   4670:                                result += content->content_size + 9;
                   4671:                        if (pretty_print) {
                   4672:                                /* tabular indent + \n */
                   4673:                                result += ((level + 1) * tabular) + 1;
                   4674: #ifdef __AXL_OS_WIN32__
                   4675:                                /* \r\n */
                   4676:                                result += 1;
                   4677: #endif
                   4678:                        }
                   4679: 
                   4680:                        break;
                   4681:                case ITEM_REF:
                   4682:                        /* item ref + '&' + ';' */
                   4683:                        content = (axlNodeContent *) item->data;
                   4684:                        result += content->content_size + 2;
                   4685:                        break;
                   4686:                case ITEM_FROM_FACTORY:
                   4687:                case ITEM_CONTENT_FROM_FACTORY:
                   4688:                        /* never reached */
                   4689:                        break;
                   4690:                }
                   4691:                /* get next item */
                   4692:                item = item->next;
                   4693:                        
                   4694:        } /* end while */
                   4695:                
                   4696:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "child processing finished for: parent=<%s>, count=%d", node->name, result);
                   4697: 
                   4698:        /* return the result */
                   4699:        return result;
                   4700: }
                   4701: 
                   4702: axl_bool __axl_node_dump_attributes_at_foreach (axlPointer key, 
                   4703:                                                axlPointer value, 
                   4704:                                                axlPointer user_data,
                   4705:                                                axlPointer user_data2)
                   4706: {
                   4707:        char      * content    = user_data;
                   4708:        int       * _desp      = user_data2;
                   4709:        axl_bool    terminator = axl_false;
                   4710:        int         desp       = (*_desp);
                   4711:        int         length;
                   4712: 
                   4713:        memcpy (content + desp, " ", 1);
                   4714:        desp += 1;
                   4715:        
                   4716:        length = strlen ((char*) key);
                   4717:        memcpy (content + desp, (char *) key, length);
                   4718:        desp += length;
                   4719: 
                   4720:        /* check if the content contains a ' so, enclose the attribute
                   4721:         * with " */
                   4722:        if (strstr (value, "'") == NULL) {
                   4723:                memcpy (content + desp, "='", 2);
                   4724:                desp += 2;
                   4725:        }else {
                   4726:                terminator = axl_true;
                   4727:                memcpy (content + desp, "=\"", 2);
                   4728:                desp += 2;
                   4729:        }
                   4730:        
                   4731:        length = strlen ((char*) value);
                   4732:        memcpy (content + desp, (char*) value, length);
                   4733:        desp += length;
                   4734: 
                   4735:        /* dump attribute termination */
                   4736:        if (terminator) {
                   4737:                memcpy (content + desp, "\"", 1);
                   4738:        }else {
                   4739:                memcpy (content + desp, "'", 1);                
                   4740:        }
                   4741:        desp += 1;
                   4742: 
                   4743:        /* update desp */
                   4744:        (*_desp) = desp;
                   4745: 
                   4746:        /* make the process to continue */
                   4747:        return axl_false;
                   4748: }
                   4749: 
                   4750: void __axl_node_dump_at_the_end (axlNodeAttr * attr, char * content, int * desp)
                   4751: {
                   4752:        /* return if no attribute must be dumped */
                   4753:        if (attr == NULL)
                   4754:                return;
                   4755: 
                   4756:        /* call to dump next attributes first */
                   4757:        __axl_node_dump_at_the_end (attr->next, content, desp);
                   4758: 
                   4759:        /* now dump our attribute */
                   4760:        __axl_node_dump_attributes_at_foreach (attr->attribute, attr->value, content, desp);
                   4761: 
                   4762:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "dumping attribute: %s=%s", attr->attribute, attr->value);
                   4763: 
                   4764:        return;
                   4765: }
                   4766: 
                   4767: /** 
                   4768:  * @internal
                   4769:  * 
                   4770:  * Internal support function which dumps current attribute
                   4771:  * configuration into the given memory using the provided desp.
                   4772:  */
                   4773: int axl_node_dump_attributes_at (axlNode * node, char * content, int desp)
                   4774: {
                   4775:        axlNodeAttr  * attr   = NULL;   
                   4776: 
                   4777:        /* if attribute list is not defined just return 0 */
                   4778:        if (node->attributes == NULL)
                   4779:                return desp;
                   4780: 
                   4781:        /* according to the attribute num */
                   4782:        if (node->attr_num <= 10) {
                   4783:                /* get the first reference */
                   4784:                attr = (axlNodeAttr *) node->attributes;
                   4785:                __axl_node_dump_at_the_end (attr, content, &desp);
                   4786: 
                   4787:        } else {
                   4788:                /* foreach attribute dump */
                   4789:                axl_hash_foreach2 ((axlHash *) node->attributes, __axl_node_dump_attributes_at_foreach, content, &desp);
                   4790:        }
                   4791: 
                   4792:        /* return the length */
                   4793:        return desp;
                   4794: }
                   4795: 
                   4796: /** 
                   4797:  * @internal Writes the indentation according to the tabular size and
                   4798:  * the indent level.
                   4799:  * 
                   4800:  * @param content The reference to the content where the dump
                   4801:  * operation will be performed.
                   4802:  *
                   4803:  * @param tabular The tabular size to be applied for each level.
                   4804:  *
                   4805:  * @param level The indent level to be applied.
                   4806:  * 
                   4807:  * @return The number of bytes written.
                   4808:  */
                   4809: int __axl_node_dump_at_write_indent (char * content, int tabular, int level)
                   4810: {
                   4811:        int iterator = 0;
                   4812: 
                   4813:        while (iterator < (tabular * level)) {
                   4814:                /* write tabular info */
                   4815:                memcpy (content + iterator, " ", 1);
                   4816:                
                   4817:                /* update iterator */
                   4818:                iterator++;
                   4819:        } /* end while */
                   4820: 
                   4821:        return iterator;
                   4822: }
                   4823:        
                   4824: /* dump content */
                   4825: int __axl_node_dump_items (axlItem * item, char * content, int level, axl_bool pretty_print, int desp, int tabular)
                   4826: {
                   4827: 
                   4828:        axlNodeContent * nodeContent;
                   4829:        char           * string_aux;
                   4830: 
                   4831:        /* get first child */
                   4832:        while (item != NULL) {
                   4833:                /* according to the type, check a size */
                   4834:                switch (axl_item_get_type (item)) {
                   4835:                case ITEM_NODE:
                   4836:                        /* write axl node content */
                   4837:                        desp  = axl_node_dump_at (item->data, content, desp, pretty_print, level + 1, tabular);
                   4838:                        break;
                   4839:                case ITEM_CONTENT:
                   4840:                        /* write content information */
                   4841:                        nodeContent = (axlNodeContent *)item->data;
                   4842:                        memcpy (content + desp, nodeContent->content, nodeContent->content_size);
                   4843:                        desp += nodeContent->content_size;
                   4844:                        break;
                   4845:                case ITEM_CDATA:
                   4846:                        /* write content information */
                   4847:                        nodeContent = (axlNodeContent *)item->data;
                   4848:                        
                   4849:                        /* write cdata content */
                   4850:                        memcpy (content + desp, "<![CDATA[", 9);
                   4851:                        desp += 9;
                   4852:                        
                   4853:                        /* write content */
                   4854:                        memcpy (content + desp, nodeContent->content, nodeContent->content_size);
                   4855:                        desp += nodeContent->content_size;
                   4856:                        
                   4857:                        /* write cdata end */
                   4858:                        memcpy (content + desp, "]]>", 3);
                   4859:                        desp += 3;
                   4860:                        break;
                   4861:                case ITEM_PI:
                   4862:                        /* write pi start */
                   4863:                        memcpy (content + desp, "<?", 2);
                   4864:                        desp += 2;
                   4865:                        
                   4866:                        /* write pi name */
                   4867:                        string_aux = axl_pi_get_name (item->data);
                   4868:                        memcpy (content + desp, string_aux, strlen (string_aux));
                   4869:                        desp += strlen (string_aux);
                   4870:                        
                   4871:                        /* write pi start */
                   4872:                        memcpy (content + desp, " ", 1);
                   4873:                        desp += 1;
                   4874:                        
                   4875:                        /* write pi content */
                   4876:                        string_aux = axl_pi_get_content (item->data);
                   4877:                        memcpy (content + desp, string_aux, strlen (string_aux));
                   4878:                        desp += strlen (string_aux);
                   4879:                        
                   4880:                        /* write pi start */
                   4881:                        memcpy (content + desp, "?>", 2);
                   4882:                        desp += 2;
                   4883:                        break;
                   4884:                case ITEM_COMMENT:
                   4885: 
                   4886:                        /* check for pretty print to write indent */
                   4887:                        if (pretty_print) {
                   4888:                                desp += __axl_node_dump_at_write_indent (content + desp, tabular, level + 1);
                   4889:                        }
                   4890: 
                   4891:                        /* get a reference to the content */
                   4892:                        nodeContent = (axlNodeContent *)item->data;
                   4893: 
                   4894:                        /* add an space if the content is found to not
                   4895:                         * have one */
                   4896:                        if (nodeContent->content [0] == ' ') {
                   4897:                                memcpy (content + desp, "<!--", 4);
                   4898:                                desp += 4;
                   4899:                        } else {
                   4900:                                memcpy (content + desp, "<!-- ", 5);
                   4901:                                desp += 5;
                   4902:                        }
                   4903:                        
                   4904: 
                   4905:                        
                   4906:                        /* write content */
                   4907:                        memcpy (content + desp, nodeContent->content, nodeContent->content_size);
                   4908:                        desp += nodeContent->content_size;
                   4909:                        
                   4910:                        /* add an space if the content is found to not
                   4911:                         * have one */
                   4912:                        if (nodeContent->content [nodeContent->content_size - 1] == ' ') {
                   4913:                                memcpy (content + desp, "-->", 3);
                   4914:                                desp += 3;
                   4915:                        } else {
                   4916:                                memcpy (content + desp, " -->", 4);
                   4917:                                desp += 4;
                   4918:                        } /* end if */
                   4919: 
                   4920:                        if (pretty_print) {
                   4921: #ifdef __AXL_OS_WIN32__
                   4922:                                memcpy (content + desp, "\r\n", 2);
                   4923:                                desp += 2;
                   4924: #else
                   4925:                                memcpy (content + desp, "\n", 1);
                   4926:                                desp += 1;
                   4927: #endif
                   4928:                        }
                   4929: 
                   4930:                        break;
                   4931:                case ITEM_REF:
                   4932:                        /* content + '&' + ';' */
                   4933:                        memcpy (content + desp, "&", 1);
                   4934:                        desp += 1;
                   4935:                        
                   4936:                        /* get a reference to the content */
                   4937:                        nodeContent = (axlNodeContent *)item->data;
                   4938:                        
                   4939:                        /* write content */
                   4940:                        memcpy (content + desp, nodeContent->content, nodeContent->content_size);
                   4941:                        desp += nodeContent->content_size;
                   4942:                        
                   4943:                        memcpy (content + desp, ";", 1);
                   4944:                        desp += 1;
                   4945:                        break;
                   4946:                case ITEM_FROM_FACTORY:
                   4947:                case ITEM_CONTENT_FROM_FACTORY:
                   4948:                        /* never reached */
                   4949:                        break;
                   4950:                }
                   4951:                
                   4952:                /* get next item */
                   4953:                item = item->next;
                   4954:                
                   4955:        } /* end while */
                   4956: 
                   4957:        /* return desp calculated */
                   4958:        return desp;
                   4959: 
                   4960: } /* end __axl_node_dump_items */
                   4961: 
                   4962: /** 
                   4963:  * @internal
                   4964:  *
                   4965:  * Writes the node information represented by the node provided at the
                   4966:  * given position into the buffer provided.
                   4967:  * 
                   4968:  * @param node The node to dump and its childs.
                   4969:  *
                   4970:  * @param content The memory buffer where the content will be dumped.
                   4971:  *
                   4972:  * @param desp A memory desp where to dump the node content inside the
                   4973:  * memory provided.
                   4974:  * 
                   4975:  * @return The new desp value to be used on the next dump.
                   4976:  */
                   4977: int       axl_node_dump_at                  (axlNode * node,
                   4978:                                             char    * content,
                   4979:                                             int       desp,
                   4980:                                             axl_bool  pretty_print,
                   4981:                                             int       level,
                   4982:                                             int       tabular)
                   4983: {
                   4984:        axlItem        * item;
                   4985:        axl_bool         have_childs;
                   4986: 
                   4987:        axl_return_val_if_fail (node, -1);
                   4988: 
                   4989:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "dumping node=<%s> at %d", 
                   4990:                   axl_node_get_name (node), desp);
                   4991: 
                   4992:        /* get current have childs status */
                   4993:        have_childs = axl_node_have_childs_aux (node);
                   4994: 
                   4995:        /* check for pretty print and tabular */
                   4996:        if (pretty_print) {
                   4997:                desp += __axl_node_dump_at_write_indent (content + desp, tabular, level);
                   4998:        } /* end if */
                   4999: 
                   5000:        /* check if the node is empty */
                   5001:        if (axl_node_is_empty (node)) {
                   5002:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "the node <%s> is empty", 
                   5003:                           axl_node_get_name (node));
                   5004: 
                   5005:                if (! have_childs) {
                   5006:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "dumping an empty node without childs=<%s>",
                   5007:                                   axl_node_get_name (node));
                   5008:                        
                   5009:                        /* "<" + strlen (node-name) + " />" */
                   5010:                        memcpy (content + desp, "<", 1);
                   5011:                        desp += 1;
                   5012: 
                   5013:                        memcpy (content + desp, node->name, strlen (node->name));
                   5014:                        desp += strlen (node->name);
                   5015: 
                   5016:                        /* dump attribute values */
                   5017:                        desp = axl_node_dump_attributes_at (node, content, desp);
                   5018: 
                   5019:                        memcpy (content + desp, " />", 3);
                   5020:                        desp += 3;
                   5021: 
                   5022:                        /* write traling node information */
                   5023:                        if (pretty_print) {
                   5024: #ifdef __AXL_OS_WIN32__
                   5025:                                memcpy (content + desp, "\r\n", 2);
                   5026:                                desp += 2;
                   5027: #else
                   5028:                                memcpy (content + desp, "\n", 1);
                   5029:                                desp += 1;
                   5030: #endif
                   5031:                        }
                   5032: 
                   5033:                        return desp;
                   5034:                }
                   5035:        }
                   5036: 
                   5037:        /* the node is empty because it doesn't have content but it
                   5038:         * has childs 
                   5039:         * "<" + strlen (node-name) + ">" + strlen (node-content) + 
                   5040:         * "</" + strlen (node-name) + ">" */
                   5041:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "getting content for: <%s>", axl_node_get_name (node));
                   5042: 
                   5043:        /* dump node start tag */
                   5044:        memcpy (content + desp, "<", 1);
                   5045:        desp += 1;
                   5046: 
                   5047:        memcpy (content + desp, node->name, strlen (node->name));
                   5048:        desp += strlen (node->name);
                   5049: 
                   5050:        /* dump attribute values */
                   5051:        desp = axl_node_dump_attributes_at (node, content, desp);
                   5052: 
                   5053:        memcpy (content + desp, ">", 1);
                   5054:        desp += 1;
                   5055: 
                   5056:        /* if the node have childs */
                   5057:        if (have_childs) {
                   5058:                
                   5059:                /* write traling node information */
                   5060:                if (pretty_print) {
                   5061: #ifdef __AXL_OS_WIN32__
                   5062:                        memcpy (content + desp, "\r\n", 2);
                   5063:                        desp += 2;
                   5064: #else
                   5065:                        memcpy (content + desp, "\n", 1);
                   5066:                        desp += 1;
                   5067: #endif
                   5068:                } /* end if */
                   5069: 
                   5070:                /* dump content */
                   5071:                item = node->first;
                   5072:                desp = __axl_node_dump_items (item, content, level, pretty_print, desp, tabular);
                   5073:                
                   5074:                /* check for pretty print and tabular */
                   5075:                if (pretty_print) {
                   5076:                        desp += __axl_node_dump_at_write_indent (content + desp, tabular, level);
                   5077:                } /* end if */
                   5078: 
                   5079:        }else {
                   5080:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "the node is not empty and have no childs");
                   5081: 
                   5082:                /* dump content */
                   5083:                item = node->first;
                   5084:                desp = __axl_node_dump_items (item, content, level, pretty_print, desp, tabular);
                   5085:        } /* end if */
                   5086: 
                   5087:        /* dump close tag */
                   5088:        memcpy (content + desp, "</", 2);
                   5089:        desp += 2;
                   5090:        
                   5091:        memcpy (content + desp, node->name, strlen (node->name));
                   5092:        desp += strlen (node->name);
                   5093:        
                   5094:        memcpy (content + desp, ">", 1);
                   5095:        desp += 1;
                   5096: 
                   5097:        /* write traling node information */
                   5098:        if (pretty_print) {
                   5099: #ifdef __AXL_OS_WIN32__
                   5100:                memcpy (content + desp, "\r\n", 2);
                   5101:                desp += 2;
                   5102: #else
                   5103:                memcpy (content + desp, "\n", 1);
                   5104:                desp += 1;
                   5105: #endif
                   5106:        }
                   5107: 
                   5108:        /* return the result */
                   5109:        return desp;
                   5110: }
                   5111: 
                   5112: /**
                   5113:  * @internal Function used by axl_node_has_invalid_chars which also
                   5114:  * provides features for CDATA sections.
                   5115:  */
                   5116: axl_bool      axl_node_has_invalid_chars_internal        (const char * content,
                   5117:                                                          int          content_size,
                   5118:                                                          int        * added_size,
                   5119:                                                          axl_bool     cdata)
                   5120: {
                   5121:        int          iterator = 0;
                   5122:        axl_bool     result   = axl_false;
                   5123:        axl_return_val_if_fail (content, axl_false);
                   5124: 
                   5125:        /* reset additional size value */
                   5126:        if (added_size != NULL)
                   5127:                *added_size = 0;
                   5128: 
                   5129:        /* calculate the content size */
                   5130:        if (content_size == -1)
                   5131:                content_size = strlen (content);
                   5132: 
                   5133:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "checking valid sequence: content size=%d", content_size);
                   5134: 
                   5135:        /* iterate over all content defined */
                   5136:        while (iterator < content_size) {
                   5137:                /* check for &apos; */
                   5138:                if (content [iterator] == '\'') {
                   5139:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found invalid sequence='\\'");
                   5140:                        result = axl_true;
                   5141:                        if (added_size != NULL)
                   5142:                                (*added_size) += 5;
                   5143:                }
                   5144: 
                   5145:                /* check for &quot; */
                   5146:                if (content [iterator] == '"') {
                   5147:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found invalid sequence='\"'");
                   5148:                        result = axl_true;
                   5149:                        if (added_size != NULL)
                   5150:                                (*added_size) += 5;
                   5151:                }
                   5152: 
                   5153:                /* check for &amp; */
                   5154:                if (content [iterator] == '&') {
                   5155:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found invalid sequence='&'");
                   5156:                        result = axl_true;
                   5157:                        if (added_size != NULL)
                   5158:                                (*added_size) += 4;
                   5159:                }
                   5160: 
                   5161:                /* check for &gt; */
                   5162:                if (content [iterator] == '>') {
                   5163:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found invalid sequence='>'");
                   5164:                        result = axl_true;
                   5165:                        if (added_size != NULL)
                   5166:                                (*added_size) += 3;
                   5167:                }
                   5168: 
                   5169:                /* check for &lt; */
                   5170:                if (content [iterator] == '<') {
                   5171:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found invalid sequence='<'");
                   5172:                        result = axl_true;
                   5173:                        if (added_size != NULL)
                   5174:                                (*added_size) += 3;
                   5175:                }
                   5176: 
                   5177:                /* check for ]]> */
                   5178:                if (content [iterator] == ']' && content [iterator + 1] == ']' && content [iterator + 2] == '>') {
                   5179:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found invalid sequence=']]>'");
                   5180:                        result = axl_true;
                   5181:                        if (cdata) {
                   5182:                                /* inside CDATA section that is, we
                   5183:                                 * have to escape this value and
                   5184:                                 * reopen a new CDATA section to match
                   5185:                                 * with the last terminator */
                   5186:                                if (added_size != NULL)
                   5187:                                        (*added_size) += 15;
                   5188:                        } else {
                   5189:                                if (added_size != NULL)
                   5190:                                        (*added_size) += 3;
                   5191:                        }
                   5192:                        iterator += 3;
                   5193:                        continue;
                   5194:                } /* end if */
                   5195: 
                   5196:                /* update the iterator */
                   5197:                iterator++;
                   5198:        }
                   5199: 
                   5200:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "valid sequence checking result=%d: content size=%d, additional size=%d resul=%s", 
                   5201:                   result, content_size, (added_size != NULL) ? *added_size : 0, result ? "HAS INVALID SEQUENCES" : "HAS NO INVALID SEQUENCES");
                   5202: 
                   5203:        /* return results */
                   5204:        return result;
                   5205: }
                   5206: 
                   5207: /** 
                   5208:  * @brief Allows to check if the provided string have invalid chars
                   5209:  * that must be escaped by using the entity reference rather the value
                   5210:  * itself.
                   5211:  *
                   5212:  * This function is useful in the sense it allows to know if a
                   5213:  * particular content will contain elements not allowed by the XML 1.0
                   5214:  * definition to be placed directly (like &, <, ;, ' and ").
                   5215:  *
                   5216:  *
                   5217:  * This function use usually complemented with \ref axl_node_content_copy_and_escape. 
                   5218:  * 
                   5219:  * @param content The content to check.
                   5220:  *
                   5221:  * @param content_size The size of the content to be checked. If -1 is
                   5222:  * provided, the function will calculate the content length.
                   5223:  *
                   5224:  * @param added_size An integer reference where the additional size
                   5225:  * variable will be added. This additional size will be the space
                   5226:  * required to replace non-valid characters with entity
                   5227:  * references. This parameter is optional, so passing a NULL value is
                   5228:  * allowed.
                   5229:  * 
                   5230:  * @return \ref axl_true if the string contains non valid chars
                   5231:  * that must be escaped using entity references.
                   5232:  */
                   5233: axl_bool      axl_node_has_invalid_chars        (const char * content,
                   5234:                                                 int          content_size,
                   5235:                                                 int        * added_size)
                   5236: {
                   5237:        /* call to internal implementation supposing this is for a
                   5238:         * node without CDATA section */
                   5239:        return axl_node_has_invalid_chars_internal (content, content_size, added_size, axl_false);
                   5240: }
                   5241: 
                   5242: /** 
                   5243:  * @brief Allows to check if the provided string have escape sequences
                   5244:  * that must be defined by using the entity reference rather the value
                   5245:  * itself, taking into consideration the content will be used for a
                   5246:  * <![CDATA[..]]> section.
                   5247:  *
                   5248:  * This function is useful in the sense it allows to know if a
                   5249:  * particular content will contain elements not allowed by the XML 1.0
                   5250:  * definition to be placed directly (like &, <, ;, ' and ").
                   5251:  *
                   5252:  * This function use usually complemented with \ref axl_node_content_copy_and_escape_cdata. 
                   5253:  *
                   5254:  * @param content The content to check.
                   5255:  *
                   5256:  * @param content_size The size of the content to be checked. If -1 is
                   5257:  * provided, the function will calculate the content length.
                   5258:  *
                   5259:  * @param added_size An integer reference where the additional size
                   5260:  * variable will be added. This additional size will be the space
                   5261:  * required to replace non-valid characters with entity
                   5262:  * references. This parameter is optional, so passing a NULL value is
                   5263:  * allowed.
                   5264:  * 
                   5265:  * @return axl_true if the string contains non valid sequences that
                   5266:  * must be escaped using entity references.
                   5267:  */
                   5268: axl_bool      axl_node_has_invalid_chars_cdata        (const char * content,
                   5269:                                                       int          content_size,
                   5270:                                                       int        * added_size)
                   5271: {
                   5272:        /* call to internal implementation supposing this is for a
                   5273:         * node with CDATA section */
                   5274:        return axl_node_has_invalid_chars_internal (content, content_size, added_size, axl_true);
                   5275: }
                   5276: 
                   5277: /** 
                   5278:  * @brief Allows to perform a copy from the content provided, doing an
                   5279:  * xml character escaping for non allowed values (&, <, >, ' and ").
                   5280:  *
                   5281:  * This function must be used with \ref axl_node_has_invalid_chars to
                   5282:  * check if the content has escapable chars an to get the additional
                   5283:  * content that must be allocated by this function.
                   5284:  *
                   5285:  * Here is an example:
                   5286:  * \code
                   5287:  * char * content = "Some content with invalid chars & < >";
                   5288:  * int    additional_size;
                   5289:  * char * new_content
                   5290:  *
                   5291:  * if (axl_node_has_invalid_chars (content, strlen (content), &additional_size)) {
                   5292:  *      // found that the string has invalid chars, escape them
                   5293:  *      new_content = axl_node_content_copy_and_escape (content, strlen (content), additional_size);
                   5294:  * } 
                   5295:  *
                   5296:  * \endcode
                   5297:  * 
                   5298:  * @param content The content to be escaped. If this parameter is
                   5299:  * NULL, the function returns NULL.
                   5300:  * 
                   5301:  * @param content_size The content size for the first parameter.
                   5302:  *
                   5303:  * @param additional_size The additional size calculated from \ref axl_node_has_invalid_chars.
                   5304:  *
                   5305:  * @return A newly allocated string with all characters escaped. Use
                   5306:  * \ref axl_free to dealloc the result.
                   5307:  */
                   5308: char * axl_node_content_copy_and_escape (const char * content, 
                   5309:                                         int          content_size, 
                   5310:                                         int          additional_size)
                   5311: {
                   5312:        axl_return_val_if_fail (content, NULL);
                   5313:        
                   5314:        /* call to the internal implementation */
                   5315:        return __axl_node_content_copy_and_escape (content, content_size, additional_size, axl_false);
                   5316: } 
                   5317: 
                   5318: /** 
                   5319:  * @brief Allows to perform a copy for the content provided, doing an
                   5320:  * xml character escaping for non allowed values (&, <, >, ' and ")
                   5321:  * taking into consideration the content will be placed inside a
                   5322:  * <![CDATA[..]]> declaration.
                   5323:  *
                   5324:  * This function must be used with \ref axl_node_has_invalid_chars_cdata to
                   5325:  * check if the content has escapable chars an to get the additional
                   5326:  * content that must be allocated by this function.
                   5327:  *
                   5328:  * Here is an example:
                   5329:  * \code
                   5330:  * char * content = "Some content with invalid chars & < >";
                   5331:  * int    additional_size;
                   5332:  * char * new_content
                   5333:  *
                   5334:  * if (axl_node_has_invalid_chars_cdata (content, strlen (content), &additional_size)) {
                   5335:  *      // found that the string has invalid chars, escape them
                   5336:  *      new_content = axl_node_content_copy_and_escape_cdata (content, strlen (content), additional_size);
                   5337:  * } 
                   5338:  * \endcode
                   5339:  * 
                   5340:  * @param content The content to be escaped. If this parameter is
                   5341:  * null, the function returns NULL.
                   5342:  * 
                   5343:  * @param content_size The content size for the first parameter.
                   5344:  *
                   5345:  * @param additional_size The additional size calculated from \ref axl_node_has_invalid_chars_cdata.
                   5346:  *
                   5347:  * @return A newly allocated string with all characters escaped. Use
                   5348:  * \ref axl_free to dealloc the result.
                   5349:  */
                   5350: char * axl_node_content_copy_and_escape_cdata (const char * content, 
                   5351:                                               int          content_size, 
                   5352:                                               int          additional_size)
                   5353: {
                   5354:        axl_return_val_if_fail (content, NULL);
                   5355:        
                   5356:        /* call to the internal implementation */
                   5357:        return __axl_node_content_copy_and_escape (content, content_size, additional_size, axl_true);
                   5358: } 
                   5359: 
                   5360: void __axl_node_free_internal (axlNode * node, axl_bool also_childs)
                   5361: {
                   5362:        axlItem * item;
                   5363:        axlItem * itemAux;
                   5364: 
                   5365:        axl_return_if_fail (node);
                   5366: 
                   5367:        /* free current node */
                   5368:        if (node->name != NULL && ! (node->conf & NODE_NAME_FROM_FACTORY))
                   5369:                axl_free (node->name);
                   5370: 
                   5371:        /* release memory hold by attributes */
                   5372:        if (node->attributes != NULL) {
                   5373:                if (node->attr_num <= 10)
                   5374:                        __axl_node_free_attr_list ((axlNodeAttr *) node->attributes);
                   5375:                else 
                   5376:                        axl_hash_free ((axlHash *) node->attributes);
                   5377:        }
                   5378: 
                   5379:        /* release memory hold by childs */
                   5380:        if (node->first != NULL && also_childs) {
                   5381:                /* get the first item */
                   5382:                item = node->first;
                   5383: 
                   5384:                /* foreach item stored */
                   5385:                while (item != NULL) {
                   5386: 
                   5387:                        /* get the next item */
                   5388:                        itemAux = item->next;                   
                   5389: 
                   5390:                        /* free the item */
                   5391:                        axl_item_free (item, axl_true);
                   5392:                        
                   5393:                        /* update reference */
                   5394:                        item = itemAux;
                   5395: 
                   5396:                } /* end while */
                   5397: 
                   5398:        } /* end if */
                   5399: 
                   5400:        /* free the item itself */
                   5401:        if (node->holder != NULL) {
                   5402:                if ((node->holder->type & ITEM_FROM_FACTORY) == 0) {
                   5403:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, 
                   5404:                                   "item holder found to be not from a factory, dealloc reference=0x%x, node=0x%x, type=%d",
                   5405:                                   node->holder, node, node->holder->type);
                   5406:                        axl_free (node->holder);
                   5407:                        node->holder = NULL;
                   5408:                }
                   5409:        }
                   5410: 
                   5411:        /* do not free the node itself */
                   5412:        return;
                   5413: }
                   5414: 
                   5415: /** 
                   5416:  * @brief Destroy the given node provided by the reference.
                   5417:  *
                   5418:  * The function will check for nodes that are NULL references,
                   5419:  * returning immediately.
                   5420:  * 
                   5421:  * @param node The node to destroy. 
                   5422:  */
                   5423: void axl_node_free (axlNode * node) 
                   5424: {
                   5425:        axlHash * hash;
                   5426:        axl_return_if_fail (node);
                   5427:        
                   5428:        /* get a reference to the hash */
                   5429:        hash = node->annotate_data;
                   5430: 
                   5431:        /* free internal content */
                   5432:        __axl_node_free_internal (node, axl_true);
                   5433: 
                   5434:        /* free attributes */
                   5435:        if (! (node->conf & NODE_FROM_FACTORY))
                   5436:                axl_free (node);
                   5437: 
                   5438:        /* annotate data deallocation must be done here because it is
                   5439:         * used by the application user and the library to store
                   5440:         * reference that could be pointing to internal structures
                   5441:         * deallocated by the __axl_node_free_internal */
                   5442:        axl_hash_free (hash);
                   5443: 
                   5444:        /* the node to release */
                   5445:        return;
                   5446: }
                   5447: 
                   5448: /** 
                   5449:  * @brief Allows to remove the provided node, optionally without
                   5450:  * removing childs inside it.
                   5451:  * 
                   5452:  * @param node The node to deallocate.
                   5453:  *
                   5454:  * @param also_childs Signal the function to also dealloc childs or
                   5455:  * not.
                   5456:  */
                   5457: void      axl_node_free_full       (axlNode * node, axl_bool also_childs)
                   5458: {
                   5459:        axlHash * hash;
                   5460:        axl_return_if_fail (node);
                   5461:        
                   5462:        /* get a reference to the hash */
                   5463:        hash = node->annotate_data;
                   5464: 
                   5465:        /* free node */
                   5466:        __axl_node_free_internal (node, axl_false);
                   5467: 
                   5468:        /* free the node itself */
                   5469:        if (!(node->conf & NODE_FROM_FACTORY))
                   5470:                axl_free (node);
                   5471: 
                   5472:        /* annotate data deallocation must be done here because it is
                   5473:         * used by the application user and the library to store
                   5474:         * reference that could be pointing to internal structures
                   5475:         * deallocated by the __axl_node_free_internal */
                   5476:        axl_hash_free (hash);
                   5477: 
                   5478:        return;
                   5479: }
                   5480: 
                   5481: /**
                   5482:  * @}
                   5483:  */
                   5484: 
                   5485: /** 
                   5486:  * \defgroup axl_node_attribute_cursor Axl Node Attribute iteration: An interface provided to iterate attribute nodes without knowing them.
                   5487:  */
                   5488: 
                   5489: /** 
                   5490:  * \addtogroup axl_node_attribute_cursor
                   5491:  * @{
                   5492:  */
                   5493: 
                   5494: 
                   5495: /** 
                   5496:  * @brief Allows to get a cursor to iterate attributes found in the
                   5497:  * provided node in a linear and efficient way.
                   5498:  *
                   5499:  * The \ref axlAttrCursor could be used to iterate attributes
                   5500:  * inside a particular node in an efficient way because it stores
                   5501:  * current state (position), hiding all module details, providing
                   5502:  * access to attributes without knowing them. Then using the following
                   5503:  * functions you can modify the state (current position to get):
                   5504:  * 
                   5505:  *   - \ref axl_node_attr_cursor_first
                   5506:  *   - \ref axl_node_attr_cursor_next
                   5507:  *
                   5508:  * Finally, the following functions are provided to get the key and
                   5509:  * the value data associated to the current selected attribute,
                   5510:  * pointed by the current status of the cursor:
                   5511:  * 
                   5512:  *   - \ref axl_node_attr_cursor_get_key (returns the key of the current attribute selected)
                   5513:  *   - \ref axl_node_attr_cursor_get_value (returns the value of the current attribute selected)
                   5514:  *
                   5515:  * Here is an example:
                   5516:  * \code
                   5517:  * axlPointer           key;
                   5518:  * axlPointer           value;
                   5519:  * axlAttrCursor * cursor;
                   5520:  * 
                   5521:  * // create the cursor 
                   5522:  * cursor   = axl_node_attr_cursor_new (node);
                   5523:  *
                   5524:  * // while there are more elements 
                   5525:  * while (axl_node_attr_cursor_has_item (cursor)) {
                   5526:  *
                   5527:  *   // get the value and key
                   5528:  *   key   = axl_node_attr_cursor_get_key   (cursor);
                   5529:  *   value = axl_node_attr_cursor_get_value (cursor);
                   5530:  *
                   5531:  *   // get the next 
                   5532:  *   axl_node_attr_cursor_next (cursor);
                   5533:  *
                   5534:  * } 
                   5535:  *
                   5536:  * // free the cursor 
                   5537:  * axl_node_attr_cursor_free (cursor);
                   5538:  * \endcode
                   5539:  *
                   5540:  * Once created the \ref axlAttrCursor you must release it and create
                   5541:  * a new one if you modify your \ref axlNode attribute configuration
                   5542:  * adding more items.
                   5543:  * 
                   5544:  * @param node The node that is requested to create the \ref
                   5545:  * axlAttrCursor reference to iterate all attributes inside.
                   5546:  * 
                   5547:  * @return A newly created \ref axlAttrCursor used to iterate
                   5548:  * attributes inside the node provided. Once finished you must call to
                   5549:  * \ref axl_node_attr_cursor_free.
                   5550:  */
                   5551: axlAttrCursor * axl_node_attr_cursor_new       (axlNode * node)
                   5552: {
                   5553:        axlAttrCursor * cursor;
                   5554: 
                   5555:        axl_return_val_if_fail (node, NULL);
                   5556: 
                   5557:        /* create and configure basics */
                   5558:        cursor        = axl_new (axlAttrCursor, 1);
                   5559:        cursor->node  = node;
                   5560:        cursor->count = node->attr_num;
                   5561: 
                   5562:        /* according to the number of attributes configure the hash or
                   5563:         * the linked attribte list */
                   5564:        if (cursor->count <= 10) {
                   5565:                /* just point to the first attribute (managed as AxlNodeAttr) */
                   5566:                cursor->data = node->attributes;                
                   5567:        } else {
                   5568:                /* create an axl hash cursor */
                   5569:                cursor->data = axl_hash_cursor_new ((axlHash *) node->attributes);
                   5570:        } /* end if */
                   5571: 
                   5572:        /* return created cursor */
                   5573:        return cursor;
                   5574: }
                   5575: 
                   5576: /** 
                   5577:  * @brief Allows to configure the provided cursor to point to the
                   5578:  * first attribute found inside the node.
                   5579:  * 
                   5580:  * @param cursor The cursor that is going to be configured.
                   5581:  */
                   5582: void                 axl_node_attr_cursor_first     (axlAttrCursor * cursor)
                   5583: {
                   5584:        axl_return_if_fail (cursor);
                   5585: 
                   5586:        /* check attribute configuration */
                   5587:        if (cursor->count != cursor->node->attr_num) {
                   5588:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "Your cursor was created with another attribute configuration, renew it.");
                   5589:                return;
                   5590:        } /* end if */
                   5591: 
                   5592:        if (cursor->count <= 10) {
                   5593:                /* just point to the first attribute (managed as AxlAttribute) */
                   5594:                cursor->data = cursor->node->attributes;                
                   5595:        } else {
                   5596:                /* make hash cursor to point to the first */ 
                   5597:                axl_hash_cursor_first (cursor->data);
                   5598:        } /* end if */
                   5599:        
                   5600:        return;
                   5601: }
                   5602: 
                   5603: /** 
                   5604:  * @brief Configures the provided attribute cursor to point to the
                   5605:  * next attribute.
                   5606:  * 
                   5607:  * @param cursor The attribute cursor to be configured.
                   5608:  */
                   5609: void                 axl_node_attr_cursor_next      (axlAttrCursor * cursor)
                   5610: {
                   5611:        axl_return_if_fail (cursor);
                   5612: 
                   5613:        /* check attribute configuration */
                   5614:        if (cursor->count != cursor->node->attr_num) {
                   5615:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "Your cursor was created with another attribute configuration, renew it.");
                   5616:                return;
                   5617:        } /* end if */
                   5618: 
                   5619:        if (cursor->count <= 10) {
                   5620:                /* check null values */
                   5621:                if (cursor->data == NULL)
                   5622:                        return;
                   5623: 
                   5624:                /* just point to the first attribute (managed as AxlAttribute) */
                   5625:                cursor->data = ((axlNodeAttr *) cursor->data)->next;
                   5626: 
                   5627:                return;
                   5628:        } /* end if */
                   5629: 
                   5630:        /* make hash cursor to point to the first */ 
                   5631:        axl_hash_cursor_next (cursor->data);
                   5632: 
                   5633:        
                   5634:        return;
                   5635: }
                   5636: 
                   5637: /** 
                   5638:  * @brief Allows to check if the is a next attribute, following
                   5639:  * current attribute selected.
                   5640:  * 
                   5641:  * @param cursor The cursor to be configured.
                   5642:  *
                   5643:  * @return \ref axl_true if it has next element, otherwise \ref axl_false.
                   5644:  */
                   5645: axl_bool                 axl_node_attr_cursor_has_next  (axlAttrCursor * cursor)
                   5646: {
                   5647:        axl_return_val_if_fail (cursor, axl_false);
                   5648: 
                   5649:        if (cursor->count != cursor->node->attr_num) {
                   5650:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "Your cursor was created with another attribute configuration, renew it.");
                   5651:                return axl_false;
                   5652:        } /* end if */
                   5653: 
                   5654:        if (cursor->count <= 10) {
                   5655:                /* just point to the first attribute (managed as AxlAttribute) */
                   5656:                return (((axlNodeAttr *) cursor->data)->next) != NULL;
                   5657:        }  /* end if */
                   5658:        
                   5659:        /* make hash cursor to point to the first */ 
                   5660:        return axl_hash_cursor_has_next (cursor->data);
                   5661: }
                   5662: 
                   5663: /** 
                   5664:  * @brief Allows to check if the current position selected has an
                   5665:  * attribute reference.
                   5666:  * 
                   5667:  * @param cursor The cursor that is being queried.
                   5668:  *
                   5669:  * @return \ref axl_true if it has item element, otherwise \ref axl_false.
                   5670:  */
                   5671: axl_bool                 axl_node_attr_cursor_has_item  (axlAttrCursor * cursor)
                   5672: {
                   5673:        axl_return_val_if_fail (cursor, axl_false);
                   5674: 
                   5675:        /* check attribute configuration */
                   5676:        if (cursor->count != cursor->node->attr_num) {
                   5677:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "Your cursor was created with another attribute configuration, renew it.");
                   5678:                return axl_false;
                   5679:        } /* end if */
                   5680: 
                   5681:        if (cursor->count <= 10) {
                   5682:                /* just point to the first attribute (managed as AxlAttribute) */
                   5683:                return cursor->data != NULL;
                   5684:        }  /* end if */
                   5685:        
                   5686:        /* make hash cursor to point to the first */ 
                   5687:        return axl_hash_cursor_has_item (cursor->data);
                   5688: }
                   5689: 
                   5690: /** 
                   5691:  * @brief Allows to get the attribute key associated to the current
                   5692:  * attribute selected by the cursor.
                   5693:  * 
                   5694:  * @param cursor The cursor that is being queried.
                   5695:  * 
                   5696:  * @return A reference to the attribute key or NULL if it fails.
                   5697:  */
                   5698: const char *         axl_node_attr_cursor_get_key   (axlAttrCursor * cursor)
                   5699: {
                   5700:        axl_return_val_if_fail (cursor, NULL);
                   5701: 
                   5702:        /* check attribute configuration */
                   5703:        if (cursor->count != cursor->node->attr_num) {
                   5704:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "Your cursor was created with another attribute configuration, renew it.");
                   5705:                return NULL;
                   5706:        } /* end if */
                   5707: 
                   5708:        if (cursor->count <= 10) {
                   5709:                /* just point to the first attribute (managed as AxlAttribute) */
                   5710:                return ((axlNodeAttr *) cursor->data)->attribute;
                   5711:        }  /* end if */
                   5712:        
                   5713:        /* make hash cursor to point to the first */ 
                   5714:        return axl_hash_cursor_get_key (cursor->data);
                   5715: }
                   5716: 
                   5717: /** 
                   5718:  * @brief Allows to get the attribute value associated to the
                   5719:  * attribute selected by the cursor.
                   5720:  * 
                   5721:  * @param cursor The cursor that is being queried.
                   5722:  * 
                   5723:  * @return A reference to the attribute value or NULL if it fails.
                   5724:  */
                   5725: const char *         axl_node_attr_cursor_get_value (axlAttrCursor * cursor)
                   5726: {
                   5727:        axl_return_val_if_fail (cursor, NULL);
                   5728: 
                   5729:        /* check attribute configuration */
                   5730:        if (cursor->count != cursor->node->attr_num) {
                   5731:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "Your cursor was created with another attribute configuration, renew it.");
                   5732:                return NULL;
                   5733:        } /* end if */
                   5734: 
                   5735:        if (cursor->count <= 10) {
                   5736:                /* just point to the first attribute (managed as AxlAttribute) */
                   5737:                return ((axlNodeAttr *) cursor->data)->value;
                   5738:        }  /* end if */
                   5739:        
                   5740:        /* make hash cursor to point to the first */ 
                   5741:        return axl_hash_cursor_get_value (cursor->data);        
                   5742: }
                   5743: 
                   5744: /** 
                   5745:  * @brief Allows to release \ref axlAttrCursor.
                   5746:  * 
                   5747:  * @param cursor The cursor to release.
                   5748:  */
                   5749: void                 axl_node_attr_cursor_free      (axlAttrCursor * cursor)
                   5750: {
                   5751:        axl_return_if_fail (cursor);
                   5752: 
                   5753:        /* free hash cursor */
                   5754:        if (cursor->count > 10)
                   5755:                axl_hash_cursor_free (cursor->data);
                   5756: 
                   5757:        /* free the cursor */
                   5758:        axl_free (cursor);
                   5759: 
                   5760:        return;
                   5761: }
                   5762: 
                   5763: 
                   5764: /** 
                   5765:  * @internal Function that helps axl_node_attr_foreach to iterate all
                   5766:  * attributes.
                   5767:  */
                   5768: axl_bool __axl_node_attr_foreach_aux (axlPointer key, axlPointer data, axlPointer user_data, axlPointer user_data2, axlPointer user_data3)
                   5769: {
                   5770:        return ((axlNodeAttrForeachFunc) user_data) (key, data, user_data2, user_data3);
                   5771: }
                   5772: 
                   5773: /** 
                   5774:  * @brief Allows to provide a function which is called for each
                   5775:  * attribute installed on the provided node.
                   5776:  *
                   5777:  * This function will allow you to operate on every attribute
                   5778:  * installed, doing an foreach operation. This is an alternative API
                   5779:  * to the \ref axlAttrCursor, which could be used to save allocations.
                   5780:  * 
                   5781:  * @param node The node for which the provided function will be called
                   5782:  * for each attribute found.
                   5783:  *
                   5784:  * @param func The foreach function to be called.
                   5785:  *
                   5786:  * @param data User defined data to be passed to the foreach function.
                   5787:  *
                   5788:  * @param data2 Second user defined data to be passed to the foreach
                   5789:  * function.
                   5790:  */
                   5791: void            axl_node_attr_foreach          (axlNode       * node, 
                   5792:                                                axlNodeAttrForeachFunc func, 
                   5793:                                                axlPointer      data,
                   5794:                                                axlPointer      data2)
                   5795: {
                   5796:        axlNodeAttr * attr;
                   5797:        axl_return_if_fail (node);
                   5798:        axl_return_if_fail (func);
                   5799:        
                   5800:        /* if no attributes no foreach operation */
                   5801:        if (node->attributes == NULL)
                   5802:                return;
                   5803: 
                   5804:        /* store the attribute using the general case */
                   5805:        if (node->attr_num < 11) {
                   5806:                /* handled as a simple list */
                   5807:                attr = (axlNodeAttr *) node->attributes;
                   5808:                while (attr != NULL) {
                   5809:                        /* call to notify each attribute */
                   5810:                        if (func (attr->attribute, attr->value, data, data2))
                   5811:                                return;
                   5812: 
                   5813:                        /* get the next */
                   5814:                        attr = attr->next;
                   5815:                } /* end while */
                   5816:        } else {
                   5817:                /* handled as a hash */
                   5818:                axl_hash_foreach3 ((axlHash *) node->attributes, __axl_node_attr_foreach_aux, func, data, data2);
                   5819:        } /* end if */
                   5820: 
                   5821:        return;
                   5822: }
                   5823: 
                   5824: /**
                   5825:  * @}
                   5826:  */
                   5827: 
                   5828: /**
                   5829:  * \defgroup axl_item_module Axl Item: A basic item abstraction that represents a child node that could be another node, content, xml comment, etc.
                   5830:  */
                   5831: 
                   5832: /** 
                   5833:  * \addtogroup axl_item_module
                   5834:  * @{
                   5835:  */
                   5836: 
                   5837: /** 
                   5838:  * @brief Allows to create an \ref axlItem, with the provided type and
                   5839:  * holding the provided data.
                   5840:  *
                   5841:  * The function won't configure the parent node holding the
                   5842:  * item. There is an alternative API that allows to create an \ref
                   5843:  * axlItem without performing a copy: \ref axl_item_new_ref.
                   5844:  *
                   5845:  * @param type The type that will represent the \ref axlItem created.
                   5846:  *
                   5847:  * @param data Data associated to the axlItem. In the case the \ref
                   5848:  * axlItem being created will represent content (\ref ITEM_CONTENT),
                   5849:  * an entity ref (\ref ITEM_REF), a comment (\ref ITEM_COMMENT) or
                   5850:  * cdata (\ref ITEM_CDATA), the function will create a local copy. In
                   5851:  * the case of a \ref ITEM_NODE, the function will copy the entire
                   5852:  * node, and all its childs.
                   5853:  * 
                   5854:  * @return A newly allocated \ref axlItem with no parent and holding
                   5855:  * the data provided.
                   5856:  */
                   5857: axlItem     * axl_item_new             (AxlItemType type,
                   5858:                                        axlPointer  data)
                   5859: {
                   5860:        axlItem        * item = NULL;
                   5861:        axlNode        * node;
                   5862:        axlNodeContent * content;
                   5863: 
                   5864:        /* allocate an item type */
                   5865:        item         = axl_new (axlItem, 1);
                   5866:        item->type   = type;
                   5867: 
                   5868:        switch (axl_item_get_type (item)) {
                   5869:        case ITEM_NODE:
                   5870:                /* item the node */
                   5871:                node                 = axl_node_copy (item->data, axl_true, axl_true);
                   5872:                node->holder         = item;
                   5873:                item->data           = node;
                   5874:                break;
                   5875:        case ITEM_CONTENT:
                   5876:        case ITEM_CDATA:
                   5877:        case ITEM_COMMENT:
                   5878:                /* item content */
                   5879:                content               = axl_new (axlNodeContent, 1);
                   5880:                content->content      = axl_strdup ((const char *) data);
                   5881:                content->content_size = strlen ((const char *) data);
                   5882: 
                   5883:                /* item content */
                   5884:                item->data = content;
                   5885:                break;
                   5886:        case ITEM_PI:
                   5887:                /* item pi */
                   5888:                item->data = axl_pi_copy (data);
                   5889:                break;
                   5890:        case ITEM_REF:
                   5891:                /* not implemented yet */
                   5892:                break;
                   5893:        case ITEM_FROM_FACTORY:
                   5894:        case ITEM_CONTENT_FROM_FACTORY:
                   5895:                /* never reached */
                   5896:                break;
                   5897:        } /* end switch */
                   5898: 
                   5899:        /* return item created */
                   5900:        return item;
                   5901: }
                   5902: 
                   5903: /** 
                   5904:  * @brief Allows to create an \ref axlItem, with the provided type and
                   5905:  * holding the provided data.
                   5906:  *
                   5907:  * The function won't configure the parent node holding the item.
                   5908:  *
                   5909:  * @param type The type that will represent the \ref axlItem created.
                   5910:  *
                   5911:  * @param data Data associated to the axlItem. This function won't
                   5912:  * perform any copy for the data received. The user calling to this
                   5913:  * API must check that the data is only owned by the \ref axlItem
                   5914:  * created (that is, used by this function).
                   5915:  * 
                   5916:  * @return A newly allocated \ref axlItem with no parent and holding
                   5917:  * the data provided.
                   5918:  */
                   5919: axlItem     * axl_item_new_ref         (AxlItemType type,
                   5920:                                        axlPointer  data)
                   5921: {
                   5922:        axlItem        * item = NULL;
                   5923:        axlNode        * node;
                   5924:        axlNodeContent * content;
                   5925: 
                   5926:        /* allocate an item type */
                   5927:        item         = axl_new (axlItem, 1);
                   5928:        item->type   = type;
                   5929: 
                   5930:        switch (axl_item_get_type (item)) {
                   5931:        case ITEM_NODE:
                   5932:                /* item the node */
                   5933:                node = data;
                   5934:                node->holder         = item;
                   5935:                item->data           = node;
                   5936:                break;
                   5937:        case ITEM_CONTENT:
                   5938:        case ITEM_CDATA:
                   5939:        case ITEM_COMMENT:
                   5940:                /* item content */
                   5941:                content               = axl_new (axlNodeContent, 1);
                   5942:                content->content      = data;
                   5943:                content->content_size = strlen ((const char *) data);
                   5944: 
                   5945:                /* item content */
                   5946:                item->data = content;
                   5947:                break;
                   5948:        case ITEM_PI:
                   5949:                /* item pi */
                   5950:                item->data = data;
                   5951:                break;
                   5952:        case ITEM_REF:
                   5953:                /* not implemented yet */
                   5954:                break;
                   5955:        case ITEM_FROM_FACTORY:
                   5956:        case ITEM_CONTENT_FROM_FACTORY:
                   5957:                /* never reached */
                   5958:                break;
                   5959:        } /* end switch */
                   5960: 
                   5961:        /* return item created */
                   5962:        return item;
                   5963: }
                   5964: 
                   5965: 
                   5966: /** 
                   5967:  * @brief Allows to get the reference to the document that is holding
                   5968:  * the provided item without taking into consideration the item type.
                   5969:  * 
                   5970:  * @param item The item that is required to return its document.
                   5971:  * 
                   5972:  * @return A reference to the \ref axlDoc that is holding the item.
                   5973:  */
                   5974: axlDoc  * axl_item_get_doc         (axlItem * item)
                   5975: {
                   5976:        /* do not report an error since it is usual to have a node
                   5977:         * without an item hold configured: for example after
                   5978:         * axl_node_create */
                   5979:        if (item == NULL)
                   5980:                return NULL;
                   5981: 
                   5982:        /* return the document reference */
                   5983:        return item->doc;
                   5984: }
                   5985: 
                   5986: /** 
                   5987:  * @internal Internal function that allows to configure the document
                   5988:  * that is holding the item provided.
                   5989:  * 
                   5990:  * @param item The axlItem to be configured.
                   5991:  * @param doc The axlDoc reference to configure.
                   5992:  */
                   5993: void      axl_item_set_doc         (axlItem * item, axlDoc * doc)
                   5994: {
                   5995:        axl_return_if_fail (item);
                   5996: 
                   5997:        /* configure document */
                   5998:        item->doc = doc;
                   5999: 
                   6000:        return;
                   6001: }
                   6002: 
                   6003: /** 
                   6004:  * @brief Allows to get the parent that is containing the \ref axlItem
                   6005:  * provider. The parent of a \ref axlItem is always a node.
                   6006:  * 
                   6007:  * @param item The \ref axlItem reference that is required to return
                   6008:  * its parent.
                   6009:  * 
                   6010:  * @return A reference to the \ref axlNode.
                   6011:  */
                   6012: axlNode * axl_item_get_parent      (axlItem * item)
                   6013: {
                   6014:        /* return that we don't have parent */
                   6015:        if (item == NULL)
                   6016:                return NULL;
                   6017: 
                   6018:        /* return the parent */
                   6019:        return item->parent;
                   6020: }
                   6021: 
                   6022: /** 
                   6023:  * @brief Allows to get the following element that is next to the item
                   6024:  * reference provided (\ref axlItem), and at the same level.
                   6025:  * 
                   6026:  * @param item The item that is required to return its next reference.
                   6027:  * 
                   6028:  * @return A reference to the next element or NULL if it fails or no
                   6029:  * element is found next to the element provided.
                   6030:  */
                   6031: axlItem * axl_item_get_next        (axlItem * item)
                   6032: {
                   6033:        axl_return_val_if_fail (item, NULL);
                   6034: 
                   6035:        /* return the next element */
                   6036:        return item->next;
                   6037: }
                   6038: 
                   6039: /** 
                   6040:  * @brief Returns the following \ref axlItem to the \ref axlNode
                   6041:  * reference, in the same level.
                   6042:  * 
                   6043:  * @param node The node that is required to return the following item
                   6044:  * to it.
                   6045:  * 
                   6046:  * @return An reference to the following or NULL.
                   6047:  */
                   6048: axlItem * axl_item_node_next (axlNode * node)
                   6049: {
                   6050:        axl_return_val_if_fail (node, NULL);
                   6051: 
                   6052:        if (node->holder != NULL) {
                   6053:                /* return the next */
                   6054:                return node->holder->next;
                   6055:        }
                   6056: 
                   6057:        /* no holder, no next */
                   6058:        return NULL;
                   6059: 
                   6060: }
                   6061: 
                   6062: /** 
                   6063:  * @brief Allows to get the following element that is previous to the
                   6064:  * item reference provided (\ref axlItem), and at the same level.
                   6065:  * 
                   6066:  * @param item The item that is required to return its previous
                   6067:  * reference.
                   6068:  * 
                   6069:  * @return A reference to the previous element or NULL if it fails or
                   6070:  * no element is found previous to the element provided.
                   6071:  */
                   6072: axlItem * axl_item_get_previous        (axlItem * item)
                   6073: {
                   6074:        axl_return_val_if_fail (item, NULL);
                   6075: 
                   6076:        /* return the previous element */
                   6077:        return item->previous;
                   6078: }
                   6079: 
                   6080: /** 
                   6081:  * @brief Returns the previous \ref axlItem to the \ref axlNode
                   6082:  * reference, in the same level.
                   6083:  * 
                   6084:  * @param node The node that is required to return the previous item
                   6085:  * to it.
                   6086:  * 
                   6087:  * @return An reference to the previous or NULL.
                   6088:  */
                   6089: axlItem * axl_item_node_previous (axlNode * node)
                   6090: {
                   6091:        axl_return_val_if_fail (node, NULL);
                   6092: 
                   6093:        if (node->holder != NULL) {
                   6094:                /* return the previousx */
                   6095:                return node->holder->previous;
                   6096:        }
                   6097: 
                   6098:        /* no holder, no previous */
                   6099:        return NULL;
                   6100: }
                   6101: 
                   6102: /** 
                   6103:  * @brief Allows to get the \ref axlItem reference that is holding the
                   6104:  * node provided.
                   6105:  * 
                   6106:  * @param node The node that is required to return its holding item.
                   6107:  * 
                   6108:  * @return The item reference or NULL if it fails or it isn't set.
                   6109:  */
                   6110: axlItem     * axl_item_node_holder     (axlNode * node)
                   6111: {
                   6112:        axl_return_val_if_fail (node, NULL);
                   6113: 
                   6114:        /* return the holder */
                   6115:        return node->holder;
                   6116: }
                   6117: 
                   6118: /** 
                   6119:  * @brief Allows to get the very first child item stored on the
                   6120:  * provided \ref axlNode.
                   6121:  *
                   6122:  * This function is similar to \ref axl_node_get_first_child, but
                   6123:  * returning the first \ref axlItem no matter its type.
                   6124:  *
                   6125:  * This function is mainly used inside the MIXED API where nodes are
                   6126:  * expected to enclose content mixed with another xml nodes. See \ref
                   6127:  * axl_node_get_first_child for more details.
                   6128:  * 
                   6129:  * @param node The \ref axlNode reference that is required to return
                   6130:  * is first child reference (\ref axlItem).
                   6131:  * 
                   6132:  * @return The \ref axlItem reference or NULL if the axlNode is empty
                   6133:  * (\ref axl_node_is_empty) and have no childs (\ref
                   6134:  * axl_node_have_childs). The function also returns NULL if it fails
                   6135:  * (when it receives a NULL reference).
                   6136:  */
                   6137: axlItem     * axl_item_get_first_child (axlNode * node)
                   6138: {
                   6139:        /* check reference received */
                   6140:        axl_return_val_if_fail (node, NULL);
                   6141: 
                   6142:        /* return the first item reference */
                   6143:        return node->first;
                   6144: }
                   6145: 
                   6146: /** 
                   6147:  * @brief Allows to get the very last child item stored on the
                   6148:  * provided \ref axlNode.
                   6149:  *
                   6150:  * This function is similar to \ref axl_node_get_last_child, but
                   6151:  * returning the last \ref axlItem no matter its type.
                   6152:  *
                   6153:  * This function is mainly used inside the MIXED API where nodes are
                   6154:  * expected to enclose content mixed with another xml nodes. See \ref
                   6155:  * axl_node_get_last_child for more details.
                   6156:  * 
                   6157:  * @param node The \ref axlNode reference that is required to return
                   6158:  * is last child reference (\ref axlItem).
                   6159:  * 
                   6160:  * @return The \ref axlItem reference or NULL if the axlNode is empty
                   6161:  * (\ref axl_node_is_empty) and have no childs (\ref
                   6162:  * axl_node_have_childs). The function also returns NULL if it fails
                   6163:  * (when it receives a NULL reference).
                   6164:  */
                   6165: axlItem     * axl_item_get_last_child  (axlNode * node) 
                   6166: {
                   6167:        /* check reference received */
                   6168:        axl_return_val_if_fail (node, NULL);
                   6169: 
                   6170:        /* return the last item reference */
                   6171:        return node->last;
                   6172: }
                   6173: 
                   6174: /** 
                   6175:  * @brief Allows to get the item type that represents the reference
                   6176:  * received (\ref axlItem).
                   6177:  *
                   6178:  * Every \ref axlItem represents a particular content that could be
                   6179:  * found inside an xml document parsed by the library (\ref
                   6180:  * axlDoc). This function allows to return the type associated to the
                   6181:  * element encapsulated by the \ref axlItem. See \ref AxlItemType for
                   6182:  * more details.
                   6183:  * 
                   6184:  * @param item The reference that is required to return its type.
                   6185:  * 
                   6186:  * @return The type that is inside the reference or -1 if it fails.
                   6187:  */
                   6188: AxlItemType   axl_item_get_type        (axlItem * item)
                   6189: {
                   6190:        /* return stored type */
                   6191:        return item->type & (~ (ITEM_FROM_FACTORY | ITEM_CONTENT_FROM_FACTORY));
                   6192: }
                   6193: 
                   6194: /** 
                   6195:  * @brief Returns the item data that is stored inside the \ref axlItem
                   6196:  * received.
                   6197:  *
                   6198:  * According to the type that is representing the \ref axlItem
                   6199:  * received, it will return a particular type. Check \ref AxlItemType
                   6200:  * for more information.
                   6201:  *
                   6202:  * @param item The item that is required to return the data
                   6203:  * encapsulated on it.
                   6204:  * 
                   6205:  * @return A pointer to the data stored, or NULL if it fails. The
                   6206:  * pointer returned, in the case it is defined, mustn't be
                   6207:  * released. It is a internal reference to the content.
                   6208:  */
                   6209: axlPointer axl_item_get_data (axlItem * item)
                   6210: {
                   6211:        axl_return_val_if_fail (item, NULL);
                   6212: 
                   6213:        /* return stored type */
                   6214:        return item->data;
                   6215: }
                   6216: 
                   6217: /** 
                   6218:  * @brief Convenience API that allows to get the content stored (and
                   6219:  * its size) from the received \ref axlItem, supposing it is storing
                   6220:  * an \ref ITEM_CONTENT, \ref ITEM_CDATA, \ref ITEM_COMMENT or \ref ITEM_REF.
                   6221:  *
                   6222:  * @param item The \ref axlItem that is supposed to store an item with
                   6223:  * type: \ref ITEM_CONTENT, \ref ITEM_CDATA, \ref ITEM_COMMENT or \ref
                   6224:  * ITEM_REF.
                   6225:  *
                   6226:  * @param size Optional variable reference. If defined, if returns the
                   6227:  * content size.
                   6228:  * 
                   6229:  * @return An internal reference to the content stored and optionally
                   6230:  * the content size notified on the variable received. In the case the
                   6231:  * function receives an incompatible \ref axlItem (which is not \ref
                   6232:  * ITEM_CONTENT, \ref ITEM_CDATA, \ref ITEM_COMMENT or \ref ITEM_REF),
                   6233:  * the function will return NULL, and the optional variable will be
                   6234:  * filled with -1.
                   6235:  */
                   6236: char        * axl_item_get_content     (axlItem * item, 
                   6237:                                        int     * size)
                   6238: {
                   6239:        axlNodeContent * content;
                   6240: 
                   6241:        /* check content received */
                   6242:        if (size != NULL)
                   6243:                *size = -1;
                   6244:        
                   6245:        /* check if the item reference is NULL */
                   6246:        axl_return_val_if_fail (item, 
                   6247:                                NULL);
                   6248:        axl_return_val_if_fail (axl_item_get_type (item) != ITEM_NODE && axl_item_get_type (item) != ITEM_PI, 
                   6249:                                NULL);
                   6250: 
                   6251:        /* get the content */
                   6252:        content = item->data;
                   6253: 
                   6254:        /* fill the size */
                   6255:        if (size != NULL)
                   6256:                *size = content->content_size;
                   6257: 
                   6258:        /* return a pointer to the content */
                   6259:        return content->content;
                   6260: }
                   6261: 
                   6262: /* prepare the item to be added to the xml document */
                   6263: axlItem *  __axl_item_common_configure (axlNode * parent, AxlItemType type, axlPointer data)
                   6264: {
                   6265:        axlNode * node = NULL;
                   6266:        axlItem * item = NULL;
                   6267: 
                   6268:        /* return if the parent is defined */
                   6269:        axl_return_val_if_fail (parent, NULL);
                   6270: 
                   6271:        /* check if the node received already have a pointer to a
                   6272:         * holder created */
                   6273:        if (type & ITEM_NODE) {
                   6274:                /* get a reference to the node */
                   6275:                node = (axlNode *) data;
                   6276: 
                   6277:                /* get a reference to the holder */
                   6278:                item = node->holder;
                   6279: 
                   6280:                /* check if the current item was allocated from a
                   6281:                 * factory to ensure we don't loose that
                   6282:                 * information */
                   6283:                if ((item != NULL) && (item->type & ITEM_FROM_FACTORY)) 
                   6284:                        type = type | ITEM_FROM_FACTORY;
                   6285:        }
                   6286: 
                   6287:        /* create an item to hold the child, configuring the node, the
                   6288:         * parent and the document */
                   6289:        if (item == NULL) {
                   6290:                if ((parent->holder != NULL) && (parent->holder->doc != NULL)) {
                   6291:                        item = axl_item_factory_get (axl_doc_get_item_factory (parent->holder->doc));
                   6292:                        type = type | ITEM_FROM_FACTORY; 
                   6293:                } else 
                   6294:                        item   = axl_new (axlItem, 1);
                   6295:        }
                   6296:        item->type     = type;
                   6297:        item->data     = data;
                   6298:        item->doc      = (parent->holder != NULL) ? parent->holder->doc : NULL;
                   6299: 
                   6300:        if (item->type & ITEM_NODE) {
                   6301:                /* now configure the item that will hold the new child */
                   6302:                node->holder  = item;
                   6303:        } /* end if */  
                   6304:        
                   6305:        /* return item created */
                   6306:        return item;
                   6307: }
                   6308: 
                   6309: /** 
                   6310:  * @internal Function that helps adding a new item to the provided
                   6311:  * parent node.
                   6312:  *
                   6313:  * The new item will be added as flaged by the type provided. The
                   6314:  * function isn't exposed to the public API because there are better
                   6315:  * alternatives to add items to a \ref axlNode. Don't use this API
                   6316:  * directly.
                   6317:  * 
                   6318:  * @param parent The axl node that will receive the new content.
                   6319:  *
                   6320:  * @param type The type to configure to the new item.
                   6321:  *
                   6322:  * @param data The data associated to the data being stored.
                   6323:  *
                   6324:  * NOTE: the function doesn't check data received as it is supposed to
                   6325:  * receive calls from the library.
                   6326:  */
                   6327: void axl_item_set_child (axlNode * parent, AxlItemType type, axlPointer data)
                   6328: {
                   6329:        axlItem * item;
                   6330: 
                   6331:        /* prepare the item to be added to the xml document */
                   6332:        item = __axl_item_common_configure (parent, type, data);
                   6333: 
                   6334:        /* call to set child with a created item */
                   6335:        axl_item_set_child_ref (parent, item);
                   6336: 
                   6337:        return;
                   6338: }
                   6339: 
                   6340: /** 
                   6341:  * @brief Allows to configure xml content just after the item used as
                   6342:  * reference.
                   6343:  *
                   6344:  * @param item The item used as reference to place the content after
                   6345:  * it.
                   6346:  *
                   6347:  * @param type AxlItemType to configure the content to be placed.
                   6348:  *
                   6349:  * @param data Pointer that is associated to the type.
                   6350:  */
                   6351: void          axl_item_set_after       (axlItem * item,
                   6352:                                        AxlItemType type,
                   6353:                                        axlPointer data)
                   6354: {
                   6355:        axlItem * new_item = NULL;
                   6356: 
                   6357:        /* prepare the item to be added to the xml document */
                   6358:        new_item = __axl_item_common_configure (item->parent, type, data);
                   6359: 
                   6360:        /* configure the parent node */
                   6361:        new_item->parent   = item->parent;
                   6362: 
                   6363:        /* configure new item references */
                   6364:        new_item->previous = item;
                   6365:        new_item->next     = item->next;
                   6366:        
                   6367:        /* configure item references */
                   6368:        if (item->next != NULL)
                   6369:                item->next->previous = new_item;
                   6370:        else
                   6371:                item->parent->last  = new_item;
                   6372:        item->next = new_item;
                   6373: 
                   6374:        return;
                   6375: }
                   6376: 
                   6377: /* call to set child with a created item */
                   6378: void axl_item_set_child_ref (axlNode * parent, axlItem * item)
                   6379: {
                   6380:        axl_return_if_fail (parent);
                   6381:        axl_return_if_fail (item);
                   6382: 
                   6383:        /* configure the parent node */
                   6384:        item->parent   = parent;
                   6385: 
                   6386:        /* get the current last child */
                   6387:        if (parent->first == NULL) {
                   6388:                /* init first and last reference to the only one
                   6389:                 * child */
                   6390:                parent->first = item;
                   6391:                parent->last  = item;
                   6392:        }else {
                   6393:                /* configure the next item to the current last
                   6394:                 * child */
                   6395:                parent->last->next = item;
                   6396: 
                   6397:                /* update the last child reference */
                   6398:                item->previous    = parent->last;
                   6399:                item->next        = NULL;
                   6400:                parent->last      = item;
                   6401:        }
                   6402: 
                   6403:        return;
                   6404: }
                   6405: 
                   6406: /** 
                   6407:  * @brief Copy the reference provided creating a newly allocated
                   6408:  * reference, including the content inside.
                   6409:  * 
                   6410:  * @param item The item to copy.
                   6411:  *
                   6412:  * @param set_parent Optionally, allows to provide the parent to be
                   6413:  * configured to the item created. This is really required while
                   6414:  * copying items that contains nodes.
                   6415:  * 
                   6416:  * @return A newly allocated \ref axlItem reference, containing the
                   6417:  * same data (a deep copy) and optionally configured with the provided
                   6418:  * parent.
                   6419:  */
                   6420: axlItem * axl_item_copy (axlItem * item, axlNode * set_parent)
                   6421: {
                   6422:        axlItem        * copy;
                   6423:        axlNode        * node;
                   6424:        axlNodeContent * content;
                   6425: 
                   6426:        /* check values received */
                   6427:        axl_return_val_if_fail (item, NULL);
                   6428: 
                   6429:        /* allocate an copy type */
                   6430:        copy         = axl_new (axlItem, 1);
                   6431:        copy->type   = axl_item_get_type (item);
                   6432:        copy->parent = set_parent;
                   6433: 
                   6434:        switch (axl_item_get_type (item)) {
                   6435:        case ITEM_NODE:
                   6436:                /* copy the node */
                   6437:                node                 = axl_node_copy (item->data, axl_true, axl_true);
                   6438:                node->holder         = copy;
                   6439:                copy->data           = node;
                   6440:                break;
                   6441:        case ITEM_CONTENT:
                   6442:        case ITEM_CDATA:
                   6443:        case ITEM_COMMENT:
                   6444:                /* copy content */
                   6445:                content               = axl_new (axlNodeContent, 1);
                   6446:                content->content      = axl_strdup (((axlNodeContent * ) item->data)->content);
                   6447:                content->content_size = ((axlNodeContent * ) item->data)->content_size;
                   6448: 
                   6449:                /* copy content */
                   6450:                copy->data = content;
                   6451:                break;
                   6452:        case ITEM_PI:
                   6453:                /* copy pi */
                   6454:                copy->data = axl_pi_copy (item->data);
                   6455:                break;
                   6456:        case ITEM_REF:
                   6457:                /* not implemented yet */
                   6458:                break;
                   6459:        case ITEM_FROM_FACTORY:
                   6460:        case ITEM_CONTENT_FROM_FACTORY:
                   6461:                /* never reached */
                   6462:                break;
                   6463:        } /* end switch */
                   6464: 
                   6465:        /* return copy created */
                   6466:        return copy;
                   6467: }
                   6468: 
                   6469: /** 
                   6470:  * @brief Allows to remove the \ref axlItem instance from the document
                   6471:  * that is currently holding it, optionally deallocating the memory
                   6472:  * used by the structure.
                   6473:  * 
                   6474:  * @param item The item to remove from its container (without taking
                   6475:  * into consideration the item type).
                   6476:  *
                   6477:  * @param dealloc Deallocs the memory used by the \ref axlItem
                   6478:  * reference.
                   6479:  */
                   6480: void          axl_item_remove          (axlItem   * item,
                   6481:                                        axl_bool    dealloc)
                   6482: {
                   6483: 
                   6484:        /* free the item */
                   6485:        axl_return_if_fail (item);
                   6486: 
                   6487:        /* realloc references */
                   6488:        if (item->previous != NULL)
                   6489:                item->previous->next = item->next;
                   6490: 
                   6491:        if (item->next != NULL)
                   6492:                item->next->previous = item->previous;
                   6493: 
                   6494:        /* realloc parent references in the case of a node */
                   6495:        if (axl_item_get_type (item) == ITEM_NODE) {
                   6496:                if (item->previous == NULL)
                   6497:                        item->parent->first = item->next;
                   6498: 
                   6499:                if (item->next == NULL)
                   6500:                        item->parent->last  = item->previous;
                   6501:        } /* end if */
                   6502:        
                   6503:        /* free the item */
                   6504:        item->next     = NULL;
                   6505:        item->previous = NULL;
                   6506: 
                   6507:        if (dealloc) {
                   6508:                axl_item_free (item, axl_true);
                   6509:        } /* end if */
                   6510: 
                   6511:        return;
                   6512: 
                   6513: } /* end axl_item_remove */
                   6514: 
                   6515: /** 
                   6516:  * @brief Allows to replace the content held by the \ref axlItem
                   6517:  * reference with a new \ref axlItem, updating all references, and
                   6518:  * optionally, deallocating the memory used by the previous item
                   6519:  * reference.
                   6520:  * 
                   6521:  * @param item The item to be replaced.
                   6522:  *
                   6523:  * @param new_item The new item to be placed where the previous one is
                   6524:  * located.
                   6525:  *
                   6526:  * @param dealloc Signal to function to dealloc the memory hold the
                   6527:  * the item replaced.
                   6528:  */
                   6529: void          axl_item_replace        (axlItem  * item, 
                   6530:                                       axlItem  * new_item,
                   6531:                                       axl_bool   dealloc)
                   6532: {
                   6533:        /* free the item */
                   6534:        axl_return_if_fail (item);
                   6535:        axl_return_if_fail (new_item);
                   6536: 
                   6537:        /* realloc references */
                   6538:        if (item->previous != NULL) {
                   6539:                item->previous->next = new_item;
                   6540:                new_item->previous   = item->previous;
                   6541:        }
                   6542: 
                   6543:        if (item->next != NULL) {
                   6544:                item->next->previous = new_item;
                   6545:                new_item->next       = item->next;
                   6546:        }
                   6547: 
                   6548:        /* realloc parent references in the case of a node */
                   6549:        if (axl_item_get_type (item) == ITEM_NODE) {
                   6550:                if (item->previous == NULL)
                   6551:                        item->parent->first = new_item;
                   6552: 
                   6553:                if (item->next == NULL)
                   6554:                        item->parent->last = new_item;
                   6555:        } /* end if */
                   6556: 
                   6557:        /* free the item */
                   6558:        item->next     = NULL;
                   6559:        item->previous = NULL;
                   6560: 
                   6561:        /* configure values */
                   6562:        new_item->parent = item->parent;
                   6563:        new_item->doc    = item->doc;
                   6564: 
                   6565:        if (dealloc) {
                   6566:                axl_item_free (item, axl_true);
                   6567: 
                   6568:        } /* end if */
                   6569: 
                   6570:        return;
                   6571: 
                   6572: } /* end axl_item_replace */
                   6573: 
                   6574: /** 
                   6575:  * @brief Allows to transfer all childs contained inside the provided
                   6576:  * \ref axlNode (old_parent) placed after the provided axlItem
                   6577:  * (item_ref) on the same level.
                   6578:  *
                   6579:  * This function allows to manipulate a xml document loaded inside
                   6580:  * memory, by transfering all childs (including xml nodes, xml
                   6581:  * comments, content, process instructions and entity references) from
                   6582:  * the selected parent (the old parent) provided by the
                   6583:  * <i>old_parent</i> attribute, to be placed at the same level, where
                   6584:  * the <i>item_ref</i> is situated following it.
                   6585:  *
                   6586:  * 
                   6587:  * @param old_parent Previous parent, where the childs to be
                   6588:  * transfered will be found.
                   6589:  *
                   6590:  * @param item_ref The \ref axlItem that will act as a reference
                   6591:  * placing all childs following the item.
                   6592:  */
                   6593: void          axl_item_transfer_childs_after (axlNode * old_parent,
                   6594:                                              axlItem * item_ref)
                   6595: {
                   6596:        axlItem * item;
                   6597:        axlItem * item_aux;
                   6598: 
                   6599:        /* get the first child for the old parent */
                   6600:        item = old_parent->first;
                   6601: 
                   6602:        /* check if the parent node contains childs to be
                   6603:         * transferred. If no child is found, just return */
                   6604:        if (item == NULL)
                   6605:                return;
                   6606: 
                   6607:        /* remember previous next */
                   6608:        item_aux       = item_ref->next;
                   6609:        
                   6610:        /* make the first child to follow the item ref */
                   6611:        item_ref->next = item;
                   6612:        item->previous = item_ref;
                   6613: 
                   6614:        /* set the next at the end of all items transferred, and the
                   6615:         * new parent node */
                   6616:        while (item != NULL) {
                   6617:                /* configure the new parent */
                   6618:                item->parent = item_ref->parent;
                   6619: 
                   6620:                /* check the item to be the last */
                   6621:                if (item->next == NULL) {
                   6622:                        /* the last item was found, configure it */
                   6623:                        item->next = item_aux;
                   6624: 
                   6625:                        /* configure it to point to the last item
                   6626:                         * transferred */
                   6627:                        if (item_aux != NULL)
                   6628:                                item_aux->previous = item;
                   6629: 
                   6630:                        /* break the loop! */
                   6631:                        break;
                   6632:                } /* end if */
                   6633: 
                   6634:                /* get the next */
                   6635:                item = item->next;
                   6636:                
                   6637:        } /* end while */
                   6638: 
                   6639:        /* check that the item selected to be reference isn't the last
                   6640:         * child inside new parent node. If it is, update the new
                   6641:         * last */
                   6642:        if (item_aux == NULL) {
                   6643:                /* because item is pointing to the last item in the
                   6644:                 * level, use it as the new last */
                   6645:                item->parent->last = item;
                   6646:        } /* end if */
                   6647: 
                   6648:        /* clear reference from previous parent */
                   6649:        old_parent->first     = NULL;
                   6650:        old_parent->last      = NULL;
                   6651: 
                   6652:        return;
                   6653: }
                   6654: 
                   6655: /** 
                   6656:  * @brief Allows to check if both items are equal, considering the
                   6657:  * item type and the content associated to the item type.
                   6658:  *
                   6659:  * @param item The first item to check.
                   6660:  *
                   6661:  * @param item2 The second item to check.
                   6662:  * 
                   6663:  * @param trimmed This paramenter allows to configure how the equal
                   6664:  * check is performed for content element (\ref ITEM_CONTENT, \ref
                   6665:  * ITEM_CDATA, \ref ITEM_COMMENT and \ref ITEM_REF).
                   6666:  *
                   6667:  * @param error Optional \ref axlError reference where textual
                   6668:  * diagnostic is reported.
                   6669:  *
                   6670:  *
                   6671:  * @return \ref axl_true if the both items represents the same
                   6672:  * information, otherwise \ref axl_false is returned. If the function
                   6673:  * receives a null value it will return axl_false.
                   6674:  */
                   6675: axl_bool          axl_item_are_equal_full      (axlItem    * item,
                   6676:                                                axlItem    * item2,
                   6677:                                                axl_bool     trimmed,
                   6678:                                                axlError  ** error)
                   6679: {
                   6680:        axlNodeContent * content;
                   6681:        axlNodeContent * content2;
                   6682: 
                   6683:        /* trim content */
                   6684:        char           * trim;
                   6685:        char           * trim2;
                   6686:        axl_bool         result;
                   6687:        
                   6688:        axl_return_val_if_fail (item, axl_false);
                   6689:        axl_return_val_if_fail (item2, axl_false);
                   6690: 
                   6691:        /* basic type check */
                   6692:        if (axl_item_get_type (item) != axl_item_get_type (item2)) {
                   6693:                axl_error_report (error, -1, "Items types differs (%d != %d)", 
                   6694:                                  axl_item_get_type (item), axl_item_get_type (item2));
                   6695:                return axl_false;
                   6696:        }
                   6697: 
                   6698:        /* according the type */
                   6699:        switch (axl_item_get_type (item)) {
                   6700:        case ITEM_NODE:
                   6701:                /* check that both nodes are equal */
                   6702:                return axl_node_are_equal_full (item->data, item2->data, error);
                   6703:        case ITEM_CONTENT:
                   6704:        case ITEM_CDATA:
                   6705:        case ITEM_COMMENT:
                   6706:        case ITEM_REF:
                   6707:                /* get the contenet */
                   6708:                content  = item->data;
                   6709:                content2 = item2->data;
                   6710: 
                   6711:                if (! trimmed) {
                   6712:                        /* check first content length */
                   6713:                        if (content->content_size != content2->content_size) {
                   6714:                                axl_error_report (error, -1, "Items content size differs (%s:%d != %s:%d)", 
                   6715:                                                  content->content, 
                   6716:                                                  content->content_size, 
                   6717:                                                  content2->content,
                   6718:                                                  content2->content_size);
                   6719:                                return axl_false;
                   6720:                        }
                   6721:                        
                   6722:                        /* now check content value */
                   6723:                        return axl_cmp (content->content, content2->content);
                   6724:                }else {
                   6725:                        /* duplicate the content */
                   6726:                        trim = axl_strdup (content->content);
                   6727:                        trim2 = axl_strdup (content2->content);
                   6728: 
                   6729:                        /* trim content */
                   6730:                        axl_stream_trim (trim);
                   6731:                        axl_stream_trim (trim2);
                   6732: 
                   6733:                        /* do the comparision */
                   6734:                        result = axl_cmp (trim, trim2);
                   6735: 
                   6736:                        if (! result) {
                   6737:                                axl_error_report (error, -1, "Trimmed content differs ('%s' != '%s')", trim, trim2);
                   6738:                        } /* end if */
                   6739: 
                   6740:                        /* free data */
                   6741:                        axl_free (trim);
                   6742:                        axl_free (trim2);
                   6743:                        
                   6744:                        return result;
                   6745: 
                   6746:                }
                   6747:        case ITEM_PI:
                   6748:                /* pi case */
                   6749:                return axl_pi_are_equal (item->data, item2->data);
                   6750:        default:
                   6751:                /* no case identified, not equal */
                   6752:                break;
                   6753:        } /* end switch */
                   6754:        
                   6755:        axl_error_report (error, -1, "Item type not found, unable to check");
                   6756:        return axl_false;
                   6757: }
                   6758: 
                   6759: /** 
                   6760:  * @brief Allows to check if both items are equal, considering the
                   6761:  * item type and the content associated to the item type.
                   6762:  *
                   6763:  *
                   6764:  * @param item The first item to check.  
                   6765:  *
                   6766:  * @param item2 The second item to check.
                   6767:  *
                   6768:  * @param trimmed This paramenter allows to configure how equal
                   6769:  * checking is performed for content element (\ref ITEM_CONTENT, \ref
                   6770:  * ITEM_CDATA, \ref ITEM_COMMENT and \ref ITEM_REF).
                   6771:  *
                   6772:  * @return \ref axl_true if the both items represents the same
                   6773:  * information, otherwise \ref axl_false is returned. If the function
                   6774:  * receives a null value it will return axl_false.
                   6775:  */
                   6776: axl_bool          axl_item_are_equal      (axlItem   * item,
                   6777:                                           axlItem   * item2,
                   6778:                                           axl_bool    trimmed)
                   6779: {
                   6780:        /* call to check if both items are equal */
                   6781:        return axl_item_are_equal_full (item, item2, trimmed, NULL);
                   6782: }
                   6783: 
                   6784: /** 
                   6785:  * @brief Allows to release the memory hold the item reference
                   6786:  * provided, and the value stored inside it.
                   6787:  * 
                   6788:  * @param item The item to dealloc.
                   6789:  *
                   6790:  * @param dealloc \ref axl_true to also dealloc the value inside.
                   6791:  */
                   6792: void          axl_item_free           (axlItem  * item,
                   6793:                                       axl_bool   dealloc)
                   6794: {
                   6795:        axl_return_if_fail (item);
                   6796: 
                   6797:        
                   6798:        /* according the type */
                   6799:        switch (axl_item_get_type (item)) {
                   6800:        case ITEM_NODE:
                   6801:                /* free the node */
                   6802:                axl_node_free (item->data);
                   6803:                break;
                   6804:        case ITEM_CONTENT:
                   6805:        case ITEM_CDATA:
                   6806:        case ITEM_COMMENT:
                   6807:        case ITEM_REF:
                   6808:                /* all of them, managed equally */
                   6809: 
                   6810:                /* check and free content */
                   6811:                if ((item->type & ITEM_CONTENT_FROM_FACTORY) == 0) {
                   6812:                        axl_free (((axlNodeContent *)item->data)->content);
                   6813: 
                   6814:                        /* free node */
                   6815:                        axl_free ((axlNodeContent *)item->data);
                   6816:                }
                   6817:                
                   6818:                if ((item->type & ITEM_FROM_FACTORY) == 0)
                   6819:                        axl_free (item);
                   6820:                break;
                   6821:        case ITEM_PI:
                   6822:                /* an process instruction */
                   6823:                axl_pi_free (item->data);
                   6824:                
                   6825:                /* free the item */
                   6826:                if ((item->type & ITEM_FROM_FACTORY) == 0)
                   6827:                        axl_free (item);
                   6828:                break;
                   6829:        case ITEM_FROM_FACTORY:
                   6830:        case ITEM_CONTENT_FROM_FACTORY:
                   6831:                /* never reached */
                   6832:                break;
                   6833:                
                   6834:        } /* end switch */
                   6835: 
                   6836: 
                   6837:        return;
                   6838: }
                   6839: 
                   6840: axlFactory * axl_item_factory_create (void)
                   6841: {
                   6842:        return axl_factory_create (sizeof (axlItem));
                   6843: }
                   6844: 
                   6845: axlItem        * axl_item_factory_get (axlFactory * factory)
                   6846: {
                   6847:        return axl_factory_get (factory);
                   6848: }
                   6849: 
                   6850: axlFactory * axl_node_factory_create (void)
                   6851: {
                   6852:        return axl_factory_create (sizeof (axlNode));
                   6853: }
                   6854: 
                   6855: axlNode    * axl_node_factory_get (axlFactory * factory)
                   6856: {
                   6857:        /* get a node */
                   6858:        axlNode * node = axl_factory_get (factory);
                   6859:        
                   6860:        /* configure it */
                   6861:        node->conf = NODE_FROM_FACTORY;
                   6862: 
                   6863:        return node;
                   6864: }
                   6865: 
                   6866: axlFactory     * axl_item_content_factory_create (void)
                   6867: {
                   6868:        /* create a factory for axlNodeContent elements */
                   6869:        return axl_factory_create (sizeof (axlNodeContent));
                   6870: }
                   6871: 
                   6872: axlFactory     * axl_item_attr_factory_create (void)
                   6873: {
                   6874:        /* create a factory for axlNodeAttr elements */
                   6875:        return axl_factory_create (sizeof (axlNodeAttr));
                   6876: }
                   6877: 
                   6878: /* @} */

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