Annotation of gpl/axl/src/axl_node.c, revision 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>