Annotation of gpl/axl/src/axl_doc.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: /**
        !            41:  * @internal
        !            42:  * @brief XML 1.0 Third edition grammar
        !            43:  *
        !            44:  * [1]  document       ::=   prolog element Misc*
        !            45:  * [1]  status: partially
        !            46:  *
        !            47:  * [2]  Char           ::=   \x9 | \xA | \xD | \x20-\xD7FF | \xE000-\xFFFD | \x10000-\10FFFF
        !            48:  * [2]  status: not implemented 
        !            49:  *
        !            50:  * [3]  S              ::= ( \x20 | \x9 | \xD | \xA)
        !            51:  * [3]  status: ok
        !            52:  *
        !            53:  * [4]  NameChar       ::=   Letter | Digit | '.' | '-' | '_' | ':' | CombiningChar | Extender
        !            54:  * [4]  status: not implemented
        !            55:  *
        !            56:  * [5]  Name           ::= ( Letter | '_' | ':' |) ( NameChar )*
        !            57:  * [5]  status: not implemented
        !            58:  *
        !            59:  * [6]  Names          ::=   Name ( \x20 Name )*
        !            60:  * [6]  status: not implemented
        !            61:  *
        !            62:  * [7]  Nmtoken        ::= ( NameChar ) +
        !            63:  * [7]  status: not implemented
        !            64:  *
        !            65:  * [8]  Nmtokens       ::=   Nmtoken (\x20 Nmtoken)*
        !            66:  * [8]  status: not implemented
        !            67:  *
        !            68:  * [9]  EntityValue    ::=   '"' ( [^%&"] | PEReference | Reference )* '"' | "'" ( [^%&'] ! PEReference | Reference )* "'"
        !            69:  * [9]  status: not implemented
        !            70:  *
        !            71:  * [10] AttValue       ::=   '"' ( [^<&"] | Reference)*  '"' | "'" ( [^<&'] | Reference )* "'"
        !            72:  * [10]  status: not implemented
        !            73:  *
        !            74:  * [11] SystemLiteral  ::= ( '"' [^"]* '"') | ("'" [^']* "'")
        !            75:  * [11]  status: not implemented
        !            76:  *
        !            77:  * [12] PubidLiteral   ::=   '"' PubidChar* '"' | "'" (PubidChar - "'") * "'"
        !            78:  * [12]  status: not implemented
        !            79:  *
        !            80:  * [13] PubidChar      ::=   \x20 | \xD | \xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]
        !            81:  * [13]  status: not implemented
        !            82:  *
        !            83:  * [14] CharData       ::=   [^<&]* - ([^<&]* ']]>' [^<&]*)
        !            84:  * [14]  status: not implemented
        !            85:  *
        !            86:  * [15] Comments       ::=   '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
        !            87:  * [15]  status: not implemented
        !            88:  *
        !            89:  * [16] PI             ::=   '<?' PITarget (S (Char* - (Char* '?<' Char*)))? '?>'
        !            90:  * [16]  status: not implemented
        !            91:  *
        !            92:  * [17] PITarget       ::=   Name - (('X' | 'x') ('M' | 'm') | ('L' | 'l'))
        !            93:  * [17]  status: not implemented
        !            94:  *
        !            95:  * [18] CDsect         ::=   CDStart CData CDend
        !            96:  * [18]  status: not implemented
        !            97:  *
        !            98:  * [19] CDStart        ::=   '<![CDATA['
        !            99:  * [19]  status: not implemented
        !           100:  *
        !           101:  * [20] CData          ::=   (Char* - (Char* ']]>' Char*))
        !           102:  * [20]  status: not implemented
        !           103:  *
        !           104:  * [21] CDEnd          ::=   ']]>'
        !           105:  * [21]  status: not implemented
        !           106:  *
        !           107:  * [22] prolog         ::=   XMLDecl? Misc* (doctypedecl Misc*)?
        !           108:  * [22]  status: partially
        !           109:  *
        !           110:  * [23] XMLDecl        ::=   '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
        !           111:  * [23]  status: ok
        !           112:  *
        !           113:  * [24] VersionInfo    ::=   S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"')
        !           114:  * [24]  status: ok
        !           115:  *
        !           116:  * [25] Eq             ::=   S? '=' S?
        !           117:  * [25]  status: ok
        !           118:  *
        !           119:  * [26] VersionNum     ::=   '1.0'
        !           120:  * [26]  status: ok
        !           121:  *
        !           122:  * [27] Misc           ::=   Comment | PI | S
        !           123:  * [27]  status: not implemented
        !           124:  *
        !           125:  * [28] doctypedecl    ::=   '<!DOCTYPE' S Name (S ExternalID)? S? ('[' intSubsect ']' S?)? '>'
        !           126:  * [28]  status: not implemented
        !           127:  *
        !           128:  * [28a] DeclSep       ::=   PEReference | S
        !           129:  * [28a]  status: not implemented
        !           130:  *
        !           131:  * [28b] intSubset     ::=   (markupdecl | DeclSep)*
        !           132:  * [28b]  status: not implemented
        !           133:  *
        !           134:  * [29] markupdecl     ::=   elementdecl | AttlistDecl | EntityDecl | NotationDecl | PI | Comment
        !           135:  * [29]  status: not implemented
        !           136:  *
        !           137:  * [30] extSubset      ::=   TextDecl? extSubsetDecl
        !           138:  * [30]  status: not implemented
        !           139:  *
        !           140:  * [31] extSubsetDecl  ::=   ( markupdecl | conditionalSect | DeclSep) *
        !           141:  * [31]  status: not implemented
        !           142:  *
        !           143:  * [32] SDDecl          ::=   S 'standalone' Eq (("'" ('yes' | 'no') "'") | ('"'" ('yes' | 'no') '"'))
        !           144:  * [32]  status: ok
        !           145:  *
        !           146:  * 
        !           147:  * ** productions 33 through 39 have been removed. It seems that this
        !           148:  * ** productions were supporting xml:lang stuff that is easily
        !           149:  * ** supported by using directily the xml standard rather than
        !           150:  * ** mention it as an special production inside the language.
        !           151:  *  
        !           152:  * [39] element        ::=   EmptyElemTag | Stag content ETag
        !           153:  * [39]  status: not implemented
        !           154:  *
        !           155:  * [40] Stag           ::=   '<' Name (S Attribute)* S? '>'
        !           156:  * [40]  status: not implemented
        !           157:  *
        !           158:  * [41] Attribute      ::=   Name Eq AttValue
        !           159:  * [41]  status: not implemented
        !           160:  *
        !           161:  * [42] ETag           ::=   '</' Name S? '>'
        !           162:  * [42]  status: not implemented
        !           163:  *
        !           164:  * [43] content        ::=   CharData? ((element | Reference | CDSect | PI | Comment) CharData?)*
        !           165:  * [43]  status: not implemented
        !           166:  *
        !           167:  * [44] EmptyElemTag   ::=   '<' Name (S Attribute)* S? '/>'
        !           168:  * [44]  status: not implemented
        !           169:  *
        !           170:  * [45] elementdecl    ::=   '<!ELEMENT' S Name S contentspec S? '>' 
        !           171:  * [45]  status: not implemented
        !           172:  *
        !           173:  * [46] contentspec    ::=   'EMPTY' | 'ANY' | Mixed | children
        !           174:  * [46]  status: not implemented
        !           175:  *
        !           176:  * [47] children       ::=   (choice | seq) ('?' | '*' | '+')? 
        !           177:  * [47]  status: not implemented
        !           178:  *
        !           179:  * [48] cp             ::=   (Name | choice | seq) ('?' | '*' | '+')? 
        !           180:  * [48]  status: not implemented
        !           181:  *
        !           182:  * [49] choice         ::=   '(' S? cp ( S? '|' S? cp)+ S? ')'
        !           183:  * [49]  status: not implemented
        !           184:  *
        !           185:  * [50] seq            ::=   '(' S? cp ( S? ',' S? cp )* S? ')'
        !           186:  * [50]  status: not implemented
        !           187:  *
        !           188:  * [51] Mixed          ::=   '(' '#PCDATA' (S? '|' S? Name)* S? ')*' | '(' S? '#PCDATA' S? ')'
        !           189:  * [51]  status: not implemented
        !           190:  *
        !           191:  * [52] AttlistDecl    ::=   '<!ATTLIST' S Name AttDef* S? '>'
        !           192:  * [52]  status: not implemented
        !           193:  *
        !           194:  * [53] AttDef         ::=   S Name S AttType S DefaultDecl
        !           195:  * [53]  status: not implemented
        !           196:  *
        !           197:  * [54] AttType        ::=   Stringtype | TokenizedType | Enumeratedtype
        !           198:  * [54]  status: not implemented
        !           199:  *
        !           200:  * [55] StringType     ::=   'CDATA'
        !           201:  * [55]  status: not implemented
        !           202:  *
        !           203:  * [56] tokenized      ::=   'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' | 'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'
        !           204:  * [56]  status: not implemented
        !           205:  *
        !           206:  * [57] EnumeratedType ::=   NotationType | Enumeration
        !           207:  * [57]  status: not implemented
        !           208:  *
        !           209:  * [58] NotationType   ::=   'NOTATION' S '(' S? Name (S? Name (S? '|' S? Name)* S? ')'
        !           210:  * [58]  status: not implemented
        !           211:  *
        !           212:  * [59] Enumeration    ::=   '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
        !           213:  * [59]  status: not implemented
        !           214:  *
        !           215:  * [60] DefaultDecl    ::=   '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
        !           216:  * [60]  status: not implemented
        !           217:  *
        !           218:  * [61] conditionalSect  ::= includeSect | ignoreSect
        !           219:  * [61]  status: not implemented
        !           220:  *
        !           221:  * [62] includeSect    ::= '<![' S? 'INCLUDE S? '[' extSubsetDecl ']]>'
        !           222:  * [62]  status: not implemented
        !           223:  *
        !           224:  * [63] ignoreSect     ::=  <![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
        !           225:  * [63]  status: not implemented
        !           226:  *
        !           227:  * [64] ignoreSectContents ::=  Ignore ('<![' ignoreSectContents ']]>' Ignore) *
        !           228:  * [64]  status: not implemented
        !           229:  *
        !           230:  * [65] Ignore         ::=  Char * - (Char * ('<!' | ']]>') Char *)
        !           231:  * [65]  status: not implemented
        !           232:  *
        !           233:  * [66] CharRef        ::=  '&#' [0-9]+ ';' | '&#x' [0-9a-FA-F]+ ';'
        !           234:  * [66]  status: not implemented
        !           235:  *
        !           236:  * [67] Reference      ::=  EntityRef | CharRef
        !           237:  * [67]  status: not implemented
        !           238:  *
        !           239:  * [68] EntityRef      ::=  '&' Name ';'
        !           240:  * [68]  status: not implemented
        !           241:  *
        !           242:  * [69] PEReference    ::=  '%' Name ';'
        !           243:  * [69]  status: not implemented
        !           244:  *
        !           245:  * [70] EntityDecl     ::=  GEDecl | PEDecl
        !           246:  * [70]  status: not implemented
        !           247:  *
        !           248:  * [71] GEDecl         ::=  '<!ENTITY' S Name S EntityDef S? '>'
        !           249:  * [71]  status: not implemented
        !           250:  *
        !           251:  * [72] PEDecl         ::=  '<!ENTITY' S '%' S Name S PEDef S? '>'
        !           252:  * [72]  status: not implemented
        !           253:  *
        !           254:  * [73] EntityDef      ::=  EntityValue | (ExternalID NDataDecl?)
        !           255:  * [73]  status: not implemented
        !           256:  *
        !           257:  * [74] PEDef          ::=  EntityValue | ExternalID
        !           258:  * [74]  status: not implemented
        !           259:  *
        !           260:  * [75] ExternalID     ::=  'SYSTEM' S SystemLiteral | 'PUBLIC' S PubidLiteral S SystemLiteral
        !           261:  * [75]  status: not implemented
        !           262:  *
        !           263:  * [76] NDataDecl      ::=  S 'NData' S Name
        !           264:  * [76]  status: not implemented
        !           265:  *
        !           266:  * [77] TextDecl       ::=  '<?xml' VersionInfo? EncodingDecl S? '?>'
        !           267:  * [77]  status: not implemented
        !           268:  *
        !           269:  * [78] extParseEnt    ::=  TextDecl? content
        !           270:  * [78]  status: not implemented
        !           271:  *
        !           272:  * [80] EncodingDecl   ::=  S 'encoding' Eq ( '"' EncName '"' | "'" EncName "'" )
        !           273:  * [80]  status: ok
        !           274:  *
        !           275:  * [81] EncName        ::=  [A-Za-z] ([A-Za-z0-9._] | '-')*
        !           276:  * [81]  status: ok
        !           277:  *
        !           278:  * [82] NotationalDecl ::=  '<!NOTATION' S Name S (ExternalID | PublicID) S? '>' 
        !           279:  * [82]  status: not implemented
        !           280:  *
        !           281:  * [83] PublicID       ::=  'PUBLIC' S PubidLiteral
        !           282:  * [83]  status: not implemented
        !           283:  *
        !           284:  * 
        !           285:  * 
        !           286:  * 
        !           287:  */
        !           288: 
        !           289: /**
        !           290:  * \defgroup axl_doc_module Axl Doc: XML Documents related functions, loading XML documents and using them.
        !           291:  */
        !           292: 
        !           293: /** 
        !           294:  * \addtogroup axl_doc_module
        !           295:  * @{
        !           296:  */
        !           297: 
        !           298: #include <axl.h>
        !           299: #include <sys/stat.h>
        !           300: #include <sys/types.h>
        !           301: #include <fcntl.h>
        !           302: 
        !           303: 
        !           304: #define LOG_DOMAIN "axl-doc"
        !           305: 
        !           306: struct _axlDoc {
        !           307:        /** 
        !           308:         * @internal
        !           309:         * @brief A reference to the very first axlNode this axlDoc
        !           310:         * has. 
        !           311:         */
        !           312:        axlNode * rootNode;
        !           313: 
        !           314:        /** 
        !           315:         * @internal
        !           316:         * The document version.
        !           317:         */
        !           318:        char * version;
        !           319: 
        !           320:        /** 
        !           321:         * @internal
        !           322:         * @brief Current xml encoding document.
        !           323:         */
        !           324:        char        * encoding;
        !           325:        /**
        !           326:         * @internal
        !           327:         * @brief Current entity encoding detected.
        !           328:         */ 
        !           329:        const char  * detected_encoding;
        !           330:        
        !           331:        /** 
        !           332:         * @internal If the document was found in a different encoding
        !           333:         * than utf-8, this variable will hold its associated value to
        !           334:         * allow returning to the original encoding.
        !           335:         */
        !           336:        char        * encoding_found;
        !           337:        
        !           338:        /** 
        !           339:         * @internal
        !           340:         * @brief Current standalone configuration of the given \ref
        !           341:         * axlDoc object.
        !           342:         */
        !           343:        axl_bool    standalone;
        !           344: 
        !           345:        /** 
        !           346:         * @internal
        !           347:         *
        !           348:         * @brief Parent node stack. This stack is used to control how
        !           349:         * are nested nodes while creating/parsing xml files. This
        !           350:         * nesting allows to not only properly contruct the xml but
        !           351:         * also to check if it is well balanced.
        !           352:         */
        !           353:        axlStack  * parentNode;
        !           354: 
        !           355:        /** 
        !           356:         * @internal Binary stack to hold the xml:space preserve
        !           357:         * status on each level (associated to the current node).
        !           358:         */
        !           359:        axlBinaryStack * xmlPreserve;
        !           360: 
        !           361:        /** 
        !           362:         * @internal
        !           363:         * 
        !           364:         * @brief Internal list to hold all PI targets readed.
        !           365:         */
        !           366:        axlList   * piTargets;
        !           367: 
        !           368:        /** 
        !           369:         * @internal
        !           370:         *
        !           371:         * @brief Instruct the \ref axlDoc instance to notify that the
        !           372:         * xml header have been defined. This helps to allow define PI
        !           373:         * instruction that are only found inside the root document,
        !           374:         * or after the xml header definition.
        !           375:         */
        !           376:        axl_bool    headerProcess;
        !           377: 
        !           378:        /** 
        !           379:         * @internal Factory to create items in a memory efficient
        !           380:         * manner.
        !           381:         */
        !           382:        axlFactory * item_factory;
        !           383: 
        !           384:        /** 
        !           385:         * @internal Factory to create nodes in a memory efficient
        !           386:         * manner.
        !           387:         */
        !           388:        axlFactory    * node_factory;
        !           389: 
        !           390:        /** 
        !           391:         * @internal Factory to create nodes to hold content elements.
        !           392:         */
        !           393:        axlFactory    * content_factory;
        !           394: 
        !           395:        /** 
        !           396:         * @internal Factory to create nodes to hold attribute
        !           397:         * elements.
        !           398:         */
        !           399:        axlFactory    * attr_factory;
        !           400: 
        !           401:        /** 
        !           402:         * @internal Factory to alloc strings.
        !           403:         */
        !           404:        axlStrFactory * str_factory;
        !           405: };
        !           406: 
        !           407: struct _axlPI {
        !           408:        /** 
        !           409:         * @internal
        !           410:         * 
        !           411:         * @brief PI Target name.
        !           412:         */
        !           413:        char * name;
        !           414:        /** 
        !           415:         * @internal
        !           416:         * 
        !           417:         * @brief PI target content.
        !           418:         */
        !           419:        char * content;
        !           420: };
        !           421: 
        !           422: /* global references to handlers and user defined configuration */
        !           423: axlDocDetectCodification detect_codification_func;
        !           424: axlPointer               detect_codification_data;
        !           425: 
        !           426: axlDocConfigureCodification configure_codification_func;
        !           427: axlPointer                  configure_codification_data;
        !           428: 
        !           429: /** 
        !           430:  * @internal
        !           431:  *
        !           432:  * @brief Creates a new empty \ref axlDoc reference.
        !           433:  *
        !           434:  * Creates the parent stack used for parsing functions.
        !           435:  * 
        !           436:  * @return A newly allocated \ref axlDoc reference.
        !           437:  */
        !           438: axlDoc * __axl_doc_new (axl_bool create_parent_stack) 
        !           439: {
        !           440:        axlDoc    * result = axl_new (axlDoc, 1);
        !           441: 
        !           442:        /* default container lists */
        !           443:        result->parentNode   = axl_stack_new (NULL);
        !           444:        result->piTargets    = axl_list_new (axl_list_always_return_1, (axlDestroyFunc) axl_pi_free);
        !           445:        result->xmlPreserve  = axl_binary_stack_new ();
        !           446: 
        !           447:        /* create factories */
        !           448:        result->item_factory    = axl_item_factory_create ();
        !           449:        result->node_factory    = axl_node_factory_create ();
        !           450:        result->content_factory = axl_item_content_factory_create ();
        !           451:        result->attr_factory    = axl_item_attr_factory_create ();
        !           452:        result->str_factory     = axl_string_factory_create ();
        !           453:        return result;
        !           454: }
        !           455: 
        !           456: /** 
        !           457:  * @internal
        !           458:  *
        !           459:  * Clears internal axlDoc variables used mainly to parse documents.
        !           460:  * 
        !           461:  * @param doc The \ref axlDoc to clear
        !           462:  */
        !           463: void __axl_doc_clean (axlDoc * doc)
        !           464: {
        !           465:        /* release memory used by the parser */
        !           466:        if (doc->parentNode != NULL) {
        !           467:                axl_stack_free (doc->parentNode);
        !           468:                doc->parentNode = NULL;
        !           469:        }
        !           470: 
        !           471:        return;
        !           472: }
        !           473: 
        !           474: /** 
        !           475:  * @internal Function used by the axl doc module to allocate memory to
        !           476:  * be used by the axl stream. Currently this is used to alloc xml node
        !           477:  * names and xml attribute key and its value. The rest of items are
        !           478:  * allocated by the system memory allocation.
        !           479:  * 
        !           480:  * @param size The size that is required by the axl stream to be allocated.
        !           481:  *
        !           482:  * @param doc The axlDoc reference, which contains a reference to the
        !           483:  * string factory used to allocate memory.
        !           484:  * 
        !           485:  * @return A reference to the allocated memory. 
        !           486:  */
        !           487: char * __axl_doc_alloc (int size, axlDoc * doc)
        !           488: {
        !           489:        /* just return a piece of memory */
        !           490:        return axl_string_factory_alloc (doc->str_factory, size);
        !           491: }
        !           492: 
        !           493: /** 
        !           494:  * @internal Internal function that tries to check encoding found to
        !           495:  * configure the proper set of functions to translate from and to
        !           496:  * utf-8.
        !           497:  * 
        !           498:  * @param doc The document being configured.
        !           499:  *
        !           500:  * @param error An optional error that will be filled in the case an
        !           501:  * error is found.
        !           502:  * 
        !           503:  * @return axl_true if the operation was completed, otherwise axl_false is
        !           504:  * returned.
        !           505:  */
        !           506: axl_bool axl_doc_configure_encoding (axlDoc * doc, axlStream * stream, axlError ** error)
        !           507: {
        !           508:        char     * encoding = NULL;
        !           509:        axl_bool   result;
        !           510:        
        !           511:        /* normalize encoding found */
        !           512:        if (doc->encoding) {
        !           513:                /* copy encoding */
        !           514:                encoding = axl_strdup (doc->encoding);
        !           515: 
        !           516:                /* trim encoding */
        !           517:                axl_stream_trim (encoding);
        !           518: 
        !           519:                /* remove characters not required */
        !           520:                axl_stream_remove (encoding, "-", axl_false);
        !           521:                axl_stream_remove (encoding, "_", axl_false); 
        !           522: 
        !           523:                /* make it lower case */
        !           524:                axl_stream_to_lower (encoding);
        !           525:                
        !           526:        } /* end if */
        !           527:        
        !           528:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "configuring final document enconding, previously detected=%s, declared=%s",
        !           529:                   doc->detected_encoding ? doc->detected_encoding : "none",
        !           530:                   encoding ? encoding : "none");
        !           531: 
        !           532:        /* do not perform any configuration if nothing is defined */
        !           533:        if (! configure_codification_func) {
        !           534:                axl_free (encoding);
        !           535:                return axl_true;
        !           536:        }
        !           537: 
        !           538:        /* call to configure encoding */
        !           539:        result = configure_codification_func (stream, encoding, doc->detected_encoding, configure_codification_data, error);
        !           540:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "result from configure encoding function=%d", result);
        !           541: 
        !           542:        if (result) {
        !           543:                /* encoding was fine, that means we are working in
        !           544:                 * utf-8, udate document internals to move encoding to
        !           545:                 * utf-8 */
        !           546:                doc->encoding_found = encoding;
        !           547:                encoding            = NULL;
        !           548: 
        !           549:                /* reset encoding found to the new value */
        !           550:                if (doc->encoding)
        !           551:                        axl_free (doc->encoding);
        !           552:                doc->encoding       = axl_strdup ("utf-8");
        !           553:        }
        !           554:        axl_free (encoding);
        !           555: 
        !           556:        return result;
        !           557: }
        !           558: 
        !           559: /** 
        !           560:  * @internal
        !           561:  * 
        !           562:  * @brief Support for parsing the xml entity header 
        !           563:  * 
        !           564:  * @param stream The axlStream where is expected to receive the xml
        !           565:  * header
        !           566:  *
        !           567:  * @param doc The axlDoc where the header configuration will be
        !           568:  * placed.
        !           569:  *
        !           570:  * @param error An optional error that will be filled in the case an
        !           571:  * error is found.
        !           572:  *
        !           573:  * @return It is supposed that the function return \ref axl_true, an
        !           574:  * not deallocation is performed, and all elements were parsed
        !           575:  * properly. In the case \ref axl_false is returned, memory associated
        !           576:  * with the given stream will be released. If the document is
        !           577:  * associated, it will also be released.
        !           578:  */
        !           579: axl_bool __axl_doc_parse_xml_header (axlStream * stream, axlDoc * doc, axlError ** error)
        !           580: {
        !           581:        char      * string_aux;
        !           582:        int         size;
        !           583: 
        !           584:        /* check if the user is defining the header many times */
        !           585:        if (doc->headerProcess) {
        !           586:                axl_error_new (-1, "Found a new xml header expecification. Only one header is allowed for each xml document.", stream, error);
        !           587:                axl_stream_free (stream);
        !           588:                return axl_false;
        !           589:        }
        !           590: 
        !           591:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "looking for an xml header declaration");
        !           592: 
        !           593:        /* check for initial XMLDec (production 23) */
        !           594:        if (axl_stream_inspect (stream, "<?", 2)) {
        !           595:                
        !           596:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found xml declaration");
        !           597: 
        !           598:                /* check initial <?xml xml header */
        !           599:                if (! (axl_stream_inspect (stream, "xml", 3) > 0)) {
        !           600:                        axl_error_new (-2, "expected initial <?xml declaration, not found.", stream, error);
        !           601:                        axl_stream_free (stream);
        !           602:                        return axl_false;
        !           603:                }
        !           604:                
        !           605:                /* consume spaces */
        !           606:                AXL_CONSUME_SPACES (stream);
        !           607: 
        !           608:                if (! axl_stream_inspect (stream, "version=", 8)) {
        !           609:                        axl_error_new (-2, "expected to find 'version=' declaration, not found.", stream, error);
        !           610:                        axl_stream_free (stream);
        !           611:                        return axl_false;
        !           612:                }
        !           613: 
        !           614:                /* consume spaces */
        !           615:                AXL_CONSUME_SPACES (stream);
        !           616: 
        !           617:                /* check for " or ' */
        !           618:                if (! axl_stream_inspect_several (stream, 2, "\"1.0\"", 5, "'1.0'", 5)) {
        !           619:                        axl_error_new (-2, "expected to find either \" or ' while procesing version number, not found.", stream, error);
        !           620:                        axl_stream_free (stream);
        !           621:                        return axl_false;
        !           622:                }
        !           623: 
        !           624:                /* check for an space */
        !           625:                AXL_CONSUME_SPACES(stream);
        !           626: 
        !           627:                /* now check for encoding */
        !           628:                if (axl_stream_inspect_several (stream, 2, "encoding=\"", 10, "encoding='", 10) > 0) {
        !           629: 
        !           630:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found encoding declaration");
        !           631: 
        !           632:                        /* found encoding instruction */
        !           633:                        string_aux = axl_stream_get_until (stream, NULL, NULL, axl_true, 2, "'", "\"");
        !           634:                        if (string_aux == NULL) {
        !           635:                                axl_error_new (-2, "expected encoding value, not found.", stream, error);
        !           636:                                axl_stream_free (stream);
        !           637:                                return axl_false;
        !           638:                        }
        !           639: 
        !           640:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "encoding found=%s", string_aux);
        !           641: 
        !           642:                        /* set document encoding: do not allocate
        !           643:                         * twice the string returned, just nullify
        !           644:                         * stream internal reference and use the same
        !           645:                         * reference */
        !           646:                        axl_stream_nullify (stream, LAST_CHUNK);
        !           647:                        doc->encoding = string_aux;
        !           648: 
        !           649:                }
        !           650: 
        !           651:                /* check for an space */
        !           652:                AXL_CONSUME_SPACES(stream);
        !           653: 
        !           654:                /* get standalone configuration */
        !           655:                if ((axl_stream_inspect_several (stream, 2, "standalone=\"", 12, "standalone='", 12) > 0)) {
        !           656:                        
        !           657:                        /* found standalone instruction */
        !           658:                        string_aux = axl_stream_get_until (stream, NULL, NULL, axl_true, 2, "'", "\"");
        !           659:                        if (string_aux == NULL) {
        !           660:                                axl_error_new (-2, "expected to receive standalone value, not found.", stream, error);
        !           661:                                axl_stream_free (stream);
        !           662:                                return axl_false;
        !           663:                        }
        !           664: 
        !           665:                        /* set standalone configuration */
        !           666:                        if (memcmp ("yes", string_aux, 3))
        !           667:                                doc->standalone = axl_false;
        !           668:                        else
        !           669:                                doc->standalone = axl_true;
        !           670:                }
        !           671:                
        !           672:                /* check for an space */
        !           673:                AXL_CONSUME_SPACES(stream);
        !           674: 
        !           675:                /* get the trailing header */
        !           676:                if (! (axl_stream_inspect (stream, "?>", 2) > 0)) {
        !           677:                        axl_error_new (-2, "expected to receive the xml trailing header ?>, not found.", stream, error);
        !           678:                        axl_stream_free (stream);
        !           679:                        return axl_false;
        !           680:                }
        !           681: 
        !           682:                /* consume a possible comment */
        !           683:                if (! axl_doc_consume_comments (doc, stream, error))
        !           684:                        return axl_false;
        !           685:        }
        !           686: 
        !           687:        /* configure encoding again, now we could have more data */
        !           688:        if (! axl_doc_configure_encoding (doc, stream, error)) {
        !           689:                axl_stream_free (stream);
        !           690:                return axl_false;
        !           691:        }
        !           692: 
        !           693:        /* now process the document type declaration */
        !           694:        if (axl_stream_inspect (stream, "<!DOCTYPE", 9) > 0) {
        !           695:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found doc type declaration..");
        !           696:                /* found document type declaration, just skip it for
        !           697:                 * now */
        !           698:                axl_stream_get_until_ref (stream, NULL, NULL, axl_true, &size, 1, ">");
        !           699: 
        !           700:                /* consume a possible comment */
        !           701:                if (! axl_doc_consume_comments (doc, stream, error))
        !           702:                        return axl_false;
        !           703:        }
        !           704: 
        !           705:        /* return AXL_TRUE value */
        !           706:        return axl_true;
        !           707: }
        !           708: 
        !           709: /** 
        !           710:  * @internal
        !           711:  *
        !           712:  * @brief Tries to parse the first (and compulsory) node that the xml
        !           713:  * document must have.
        !           714:  *
        !           715:  * The very minimal expresion of an xml document is the one defined by
        !           716:  * only one node, with no content and no attributes. This minimal xml
        !           717:  * could be defined as:
        !           718:  *
        !           719:  * \code
        !           720:  *   <hello/>
        !           721:  * \endcode
        !           722:  *
        !           723:  * Or the other form accepted:
        !           724:  *
        !           725:  * \code
        !           726:  *   <hello />
        !           727:  * \endcode
        !           728:  *
        !           729:  * 
        !           730:  * 
        !           731:  * 
        !           732:  * @param stream The \ref axlStream object where is expected to find
        !           733:  * the xml node content.
        !           734:  *
        !           735:  * @param doc The \ref axlDoc object where node read will be placed
        !           736:  * inside.
        !           737:  * 
        !           738:  * @param node The node that has been added due to calling to this
        !           739:  * function.
        !           740:  *
        !           741:  * @param error An optional error reporting variable to used to report
        !           742:  * upper level the error found.
        !           743:  * 
        !           744:  * @return axl_true if the first node was successfully parsed or
        !           745:  * axl_false if not. If the function find something wrong the document
        !           746:  * is unrefered.
        !           747:  */
        !           748: axl_bool __axl_doc_parse_node (axlStream   * stream, 
        !           749:                               axlDoc      * doc, 
        !           750:                               axlNode    ** calling_node, 
        !           751:                               axl_bool    * is_empty, 
        !           752:                               axlError   ** error)
        !           753: {
        !           754:        char    * string_aux;
        !           755:        char    * string_aux2;
        !           756:        axlNode * node;
        !           757:        int       matched_chunk;
        !           758:        int       length;
        !           759:        axl_bool  delim;
        !           760:        
        !           761:        /* consume a possible comment */
        !           762:        if (! axl_doc_consume_comments (doc, stream, error))
        !           763:                return axl_false;
        !           764: 
        !           765:        /* check for initial < definition */
        !           766:        if (! (axl_stream_inspect (stream, "<", 1) > 0)  && ! axl_stream_remains (stream)) {
        !           767:                /* check if we are reading the first node node */
        !           768:                if (doc->rootNode == NULL)
        !           769:                        axl_error_new (-2, "expected initial < for a root node definition, not found. An xml document must have, at least, one node definition.", 
        !           770:                                       stream, error);
        !           771:                else
        !           772:                        axl_error_new (-2, "expected initial < for a node definition, not found.", stream, error);
        !           773:                axl_stream_free (stream);
        !           774:                return axl_false;
        !           775:        }
        !           776: 
        !           777:        /* get node name, keeping in mind the following:
        !           778:         * chunk_matched
        !           779:         * >  : 0
        !           780:         * /> : 1
        !           781:         * " ": 2
        !           782:         *
        !           783:         * We also reconfigure the alloc method used by the axl stream
        !           784:         * to ensure that the module name is allocated through the
        !           785:         * string factory.
        !           786:         */
        !           787:        axl_stream_set_buffer_alloc (stream, (axlStreamAlloc)__axl_doc_alloc, doc);
        !           788:        string_aux = axl_stream_get_until (stream, NULL, &matched_chunk, axl_true, 2, ">", " ");
        !           789: 
        !           790:        /* nullify */
        !           791:        axl_stream_nullify (stream, LAST_CHUNK);
        !           792: 
        !           793:        if (AXL_IS_STR_EMPTY (string_aux)) {
        !           794:                /* use alloc though string factory */
        !           795:                axl_stream_set_buffer_alloc (stream, NULL, NULL);
        !           796: 
        !           797:                axl_error_new (-2, "expected an non empty content for the node name not found.", stream, error);
        !           798:                axl_stream_free (stream);
        !           799:                return axl_false;
        !           800:        }
        !           801:        
        !           802:        /* if found a '/', it is matched as 1 */
        !           803:        if (matched_chunk == 1)
        !           804:                matched_chunk = 2;
        !           805:        else {
        !           806:                /* get the string length */
        !           807:                length = strlen (string_aux);
        !           808: 
        !           809:                /* if matched / it means that it was readed />, remove
        !           810:                 * it and all white spaces */
        !           811:                if (string_aux[length - 1] == '/') {
        !           812:                        /* flag as matched /> */
        !           813:                        matched_chunk          = 1;
        !           814:                        string_aux[length - 1] = 0;
        !           815:                } /* end if */
        !           816:        } /* end if */
        !           817: 
        !           818:        /* create the node and associate it the node name found */
        !           819:        node = axl_node_factory_get (doc->node_factory);
        !           820:        axl_node_set_name_from_factory (node, string_aux); 
        !           821: 
        !           822:        if (doc->rootNode == NULL) {
        !           823:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "setting as first node found, the root node: <%s>", string_aux);
        !           824: 
        !           825:                doc->rootNode  = node;
        !           826:                
        !           827:                /* set the node read, the root one, to be the parent */
        !           828:                axl_stack_push (doc->parentNode, node);
        !           829: 
        !           830:                /* configure the node */
        !           831:                axl_node_set_doc (node, doc);
        !           832: 
        !           833:        } else {
        !           834:                /* or set the node as a child of the current parent */
        !           835:                axl_doc_set_child_current_parent (doc, node);
        !           836:        }
        !           837: 
        !           838:        /* set the node created to the calling node, so the caller
        !           839:         * could get a reference */
        !           840:        if (calling_node != NULL)
        !           841:                *calling_node = node;
        !           842: 
        !           843:        /* only consume white spaces if matched_chunk is 2 */
        !           844:        if (matched_chunk == 2) {
        !           845:                /* get rid from spaces */
        !           846:                AXL_CONSUME_SPACES (stream);
        !           847:        }
        !           848: 
        !           849:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "node found: [%s]", string_aux);
        !           850: 
        !           851: 
        !           852:        /* now, until the node ends, we have to find the node
        !           853:         * attributes or the node defintion end */
        !           854:        while (1) {
        !           855:                /* check if we have an attribute for the node, or the node
        !           856:                 * definition have ended or the node definition is an empty
        !           857:                 * one 
        !           858:                 * 
        !           859:                 * the following code that relies on matched_chunk is
        !           860:                 * done due to previous call to get_until function. If
        !           861:                 * the value 0 or 1 was matched, this means that we
        !           862:                 * are on "/>" case */
        !           863:                if ((matched_chunk == 1) ||
        !           864:                    axl_stream_inspect (stream, "/>", 2) > 0) {
        !           865:                        /* use alloc though string factory */
        !           866:                        axl_stream_set_buffer_alloc (stream, NULL, NULL);
        !           867: 
        !           868:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found end xml node definition '/>'");
        !           869: 
        !           870:                        /* empty node configuration found */
        !           871:                        *is_empty = axl_true;
        !           872:                        /* axl_node_set_is_empty (node, axl_true); */
        !           873: 
        !           874:                        /* make this node to be completed and no child
        !           875:                         * could be set. */
        !           876:                        axl_stack_pop (doc->parentNode);
        !           877: 
        !           878:                        /* set the parent node to receive all content
        !           879:                         * found in the next parsing elements because
        !           880:                         * the element found is totally empty */
        !           881:                        *calling_node = axl_stack_peek (doc->parentNode);
        !           882:                        return axl_true;
        !           883:                }
        !           884:                
        !           885:                /* check if we have an attribute for the node, or the node
        !           886:                 * definition have ended or the node definition is an empty
        !           887:                 * one 
        !           888:                 * 
        !           889:                 * the following code that relies on matched_chunk is
        !           890:                 * done due to previous call to get_until function. If
        !           891:                 * the value 2 or 3 was matched, this means that we
        !           892:                 * are on ">" case */
        !           893:                if ((matched_chunk == 0) ||
        !           894:                    (axl_stream_inspect (stream, ">", 1) > 0)) {
        !           895:                        /* use alloc though string factory */
        !           896:                        axl_stream_set_buffer_alloc (stream, NULL, NULL);
        !           897:                        
        !           898:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found [end] xml node definition '>', for node: [%s]",
        !           899:                                   axl_node_get_name (node));
        !           900: 
        !           901:                        /* flag that the node is an empty definition */
        !           902:                        *is_empty = axl_false;
        !           903: 
        !           904:                        /* this node is ended */
        !           905:                        return axl_true;
        !           906:                }
        !           907:                
        !           908:                /* get rid from spaces */
        !           909:                AXL_CONSUME_SPACES (stream);
        !           910: 
        !           911:                /* found attribute declaration, try to read it.
        !           912:                 *
        !           913:                 * We also reconfigure the alloc method used by the
        !           914:                 * axl stream to ensure that xml node attributes are
        !           915:                 * allocated through the string factory.
        !           916:                 */
        !           917:                string_aux = axl_stream_get_until (stream, NULL, NULL, axl_true, 1, "=");
        !           918:                if (string_aux != NULL) {
        !           919:                        /* nullify internal reference to the stream:
        !           920:                         * now we have inside string_aux the attribute
        !           921:                         * name */
        !           922:                        axl_stream_nullify (stream, LAST_CHUNK);
        !           923: 
        !           924:                        /* check for empty values at the attribute definition */
        !           925:                        if (string_aux [0] == 0) {
        !           926:                                axl_error_new (-5, "Expected to find an attribute name (but found an empty value)", stream, error);
        !           927:                                axl_stream_free (stream);
        !           928:                                return axl_false;
        !           929:                        } /* end if */
        !           930: 
        !           931:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "attribute found: [%s]", string_aux);
        !           932: 
        !           933:                        /* remove next " and ' if defined */
        !           934:                        /* flag the we are looking for a " */
        !           935:                        delim = axl_true;
        !           936:                        if (! ((axl_stream_inspect (stream, "\"", 1) > 0))) {
        !           937:                                /* seems it is not found, flag we are
        !           938:                                 * looking for ' */
        !           939:                                delim = axl_false;
        !           940:                                if (! (axl_stream_inspect (stream, "\'", 1) > 0)) {
        !           941:                                        /* use alloc though string factory */
        !           942:                                        axl_stream_set_buffer_alloc (stream, NULL, NULL);
        !           943: 
        !           944:                                        axl_error_new (-2, "Expected to find an attribute value initiator (\") or ('), every attribute value must start with them", 
        !           945:                                                       stream, error);
        !           946:                                        axl_stream_free (stream);
        !           947:                                        return axl_false;
        !           948:                                }
        !           949:                        }
        !           950:                        
        !           951:                        
        !           952:                        /* now get the attribute value */
        !           953:                        if (delim)
        !           954:                                string_aux2 = axl_stream_get_until (stream, NULL, NULL, axl_true, 1, "\"");
        !           955:                        else
        !           956:                                string_aux2 = axl_stream_get_until (stream, NULL, NULL, axl_true, 1, "'");
        !           957: 
        !           958:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "value found: [%s]", string_aux2);
        !           959:                        
        !           960:                        /* nullify internal reference so we have the
        !           961:                         * only one reference to attribute value
        !           962:                         * inside string_aux2 */
        !           963:                        axl_stream_nullify (stream, LAST_CHUNK);
        !           964: 
        !           965:                        if (axl_node_has_attribute (node, string_aux)) {
        !           966:                                /* parse error */
        !           967:                                axl_error_new (-3, "Unable to add attribute to node which already has this attribute. Duplicate attribute error.", stream, error);
        !           968:                                axl_stream_free (stream);
        !           969:                                return axl_false;
        !           970:                        } /* end if */
        !           971:                        
        !           972:                        /* set a new attribute for the given node */
        !           973:                        axl_node_set_attribute_from_factory (doc->attr_factory, node, string_aux, string_aux2);
        !           974: 
        !           975:                        /* check xml:space configuration and update binary stack */
        !           976:                        if (axl_cmp (string_aux, "xml:space")) {
        !           977:                                if (axl_cmp (string_aux2, "preserve")) {
        !           978:                                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found xml:space=preseve, notifying..");
        !           979: 
        !           980:                                        /* 1: xml:space=preserve (found)
        !           981:                                         * make current node and all its childs to preserve (by
        !           982:                                         * default) all white spaces found */
        !           983:                                        axl_binary_stack_push (doc->xmlPreserve, axl_true);
        !           984: 
        !           985:                                } else if (axl_cmp (string_aux2, "default")) {
        !           986:                                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found xml:space=default, notifying..");
        !           987: 
        !           988:                                        /* 2: xml:space=default  (found)
        !           989:                                         * make current node and all its childs to not
        !           990:                                         * preserve white spaces (by default) */
        !           991:                                        axl_binary_stack_push (doc->xmlPreserve, axl_false);
        !           992:                                } else {
        !           993:                                        /* parse error */
        !           994:                                        axl_error_new (-2, "xml:space attribute found with other value than 'preserve' or 'default', this is not allowed.", stream, error);
        !           995:                                        axl_stream_free (stream);
        !           996:                                        return axl_false;
        !           997: 
        !           998:                                } /* end if */
        !           999:                        } else {
        !          1000:                                /* 3: xml:space (not found) 
        !          1001:                                 * make the current node to inherint
        !          1002:                                 * default from parent */
        !          1003:                                if (axl_binary_stack_is_empty (doc->xmlPreserve))
        !          1004:                                        axl_binary_stack_push (doc->xmlPreserve, axl_false);
        !          1005:                                else
        !          1006:                                        axl_binary_stack_push_the_same (doc->xmlPreserve);
        !          1007:                        } /* end if */
        !          1008: 
        !          1009:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "attribute installed..");
        !          1010: 
        !          1011:                        /* get rid from spaces */
        !          1012:                        AXL_CONSUME_SPACES (stream);
        !          1013:                        continue;
        !          1014:                }
        !          1015:                
        !          1016:                /* if reached this point, error found */
        !          1017:                axl_error_new (-2, "Parse error while reading a node being opened", stream, error);
        !          1018:                axl_stream_free (stream);
        !          1019:                return axl_false;
        !          1020: 
        !          1021:        } /* end while */
        !          1022:        
        !          1023:        /* node properly parsed  */
        !          1024:        return axl_true;
        !          1025: }
        !          1026: 
        !          1027: /** 
        !          1028:  * @internal
        !          1029:  * @brief Perform the close node operation.
        !          1030:  *
        !          1031:  */
        !          1032: axl_bool __axl_doc_parse_close_node (axlStream * stream, axlDoc * doc, axlNode ** _node, axlError ** error)
        !          1033: {
        !          1034:        char    * string;
        !          1035:        int       result_size = -1;
        !          1036:        axlNode * node;
        !          1037: 
        !          1038:        /* get the node being closed to check to the current parent */
        !          1039:        string = axl_stream_get_until_ref (stream, NULL, NULL, axl_true, &result_size, 1, ">");
        !          1040:        if (string == NULL) {
        !          1041:                axl_error_new (-1, "An error was found while closing the xml node", stream, error);
        !          1042:                axl_stream_free (stream);
        !          1043:                return axl_false;
        !          1044:        }
        !          1045: 
        !          1046:        /* check for optional white space inside the trailing result */
        !          1047:        if (axl_stream_is_white_space (string + result_size - 1)) {
        !          1048:                /* nullify to remove the optional white spaces */
        !          1049:                string [result_size - 1] = 0;
        !          1050:        } /* end if */
        !          1051: 
        !          1052:        /* get current parent node */
        !          1053:        node   = axl_stack_peek (doc->parentNode);
        !          1054:        if (node == NULL) {
        !          1055:                axl_error_new (-1, "Found that the stack doesn't have any node opened, this means either an libaxl error or the xml being read is closing a node not opened",
        !          1056:                               stream, error);
        !          1057:                axl_stream_free (stream);
        !          1058:                return axl_false;
        !          1059:        }
        !          1060:        
        !          1061:        /* check current axl node name against closed string */
        !          1062:        if (axl_cmp (axl_node_get_name (node), string)) { 
        !          1063: 
        !          1064:                /* ok, axl node to be closed is the one expected */
        !          1065:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "closing xml node, that matched with parent opened");
        !          1066: 
        !          1067:                return axl_true;
        !          1068:        }
        !          1069: 
        !          1070:        /* seems that the node being closed doesn't match */
        !          1071:        __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "xml node names to be closed doesn't matched (%s != %s), current node stack status:",
        !          1072:                 axl_node_get_name (node), string);
        !          1073: 
        !          1074:        node = axl_stack_pop (doc->parentNode);
        !          1075:        while (node != NULL) {
        !          1076:                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "<%s>", axl_node_get_name (node));
        !          1077:                node = axl_stack_pop (doc->parentNode);
        !          1078:        }
        !          1079: 
        !          1080:        axl_error_new (-1, "An error was found while closing the opened xml node, parent opened and xml node being closed doesn't match",
        !          1081:                       stream, error);
        !          1082:        axl_stream_free (stream);
        !          1083: 
        !          1084:        return axl_false;
        !          1085: }
        !          1086: 
        !          1087: /** 
        !          1088:  * @internal
        !          1089:  * 
        !          1090:  * Internal function which works as a common base for all functions
        !          1091:  * that parse XML documents from different inputs.
        !          1092:  */
        !          1093: axlDoc * __axl_doc_parse_common (const char * entity, int entity_size, 
        !          1094:                                  const char * file_path, int fd_handle, 
        !          1095:                                 axlError ** error)
        !          1096: {
        !          1097:        axlStream * stream        = NULL;
        !          1098:        axlDoc    * doc           = NULL;
        !          1099:        axlNode   * node          = NULL;
        !          1100:        char      * string        = NULL;
        !          1101:        int         index;
        !          1102:        axl_bool    is_empty      = axl_false;
        !          1103:        
        !          1104:        /* create the xml stream using provided data */
        !          1105:        stream         = axl_stream_new (entity, entity_size, file_path, fd_handle, error);
        !          1106:        axl_return_val_if_fail (stream, NULL);
        !          1107: 
        !          1108:        /* create a document reference */
        !          1109:        doc            = __axl_doc_new (axl_true);
        !          1110:        axl_stream_link (stream, doc, (axlDestroyFunc) axl_doc_free);
        !          1111: 
        !          1112:        /* detect transitional entity codification to configure built
        !          1113:         * decoder (only if defined handler found) */
        !          1114:        if (detect_codification_func) {
        !          1115:                if (! detect_codification_func (stream, &doc->detected_encoding, detect_codification_data, error)) {
        !          1116:                        axl_stream_free (stream);
        !          1117:                        return NULL; 
        !          1118:                }
        !          1119:        } /* end if */
        !          1120: 
        !          1121:        /* parse initial xml header */
        !          1122:        if (!__axl_doc_parse_xml_header (stream, doc, error))
        !          1123:                return NULL;
        !          1124: 
        !          1125:        /* signal that this document have processed its header */
        !          1126:        doc->headerProcess = axl_true;
        !          1127:        
        !          1128:        /* parse the rest of the document, setting as parent NULL
        !          1129:         * because still no parent is found. */
        !          1130:        if (!__axl_doc_parse_node (stream, doc, &node, &is_empty, error))
        !          1131:                return NULL;
        !          1132: 
        !          1133:        /* if the node returned is not empty */
        !          1134:        if (! is_empty) {
        !          1135: 
        !          1136:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "the first node ready, have content, reading it");
        !          1137: 
        !          1138:                /* while the stream have data */
        !          1139:                while (axl_stream_remains (stream)) {
        !          1140: 
        !          1141:                        /* get current index */
        !          1142:                        index = axl_stream_get_index (stream);
        !          1143: 
        !          1144:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "current index: %d (global: %d)", index,
        !          1145:                                   axl_stream_get_global_index (stream));
        !          1146:                        
        !          1147:                        /* get rid from spaces according to the
        !          1148:                         * xml:space configuration */
        !          1149:                        if (! axl_binary_stack_peek (doc->xmlPreserve)) {
        !          1150:                                AXL_CONSUME_SPACES(stream);
        !          1151:                        } /* end if */
        !          1152: 
        !          1153:                        /* consume a possible comment and process instructions */
        !          1154:                        if (axl_stream_peek (stream, "<?", 2) > 0 || axl_stream_peek (stream, "<!--", 4) > 0) {
        !          1155:                                if (! axl_doc_consume_comments (doc, stream, error))
        !          1156:                                        return NULL;
        !          1157:                                
        !          1158:                                /* continue on the next index */
        !          1159:                                continue;
        !          1160:                        } /* end if */
        !          1161:                        
        !          1162:                        if ((axl_stream_peek (stream, "</", 2) > 0)) {
        !          1163:                                /* accept previous peek */
        !          1164:                                axl_stream_accept (stream);
        !          1165: 
        !          1166:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a node termination signal");
        !          1167: 
        !          1168:                                /* seems that a node is being closed */
        !          1169:                                if (! __axl_doc_parse_close_node (stream, doc, &node, error))
        !          1170:                                        return NULL;
        !          1171: 
        !          1172:                                /* because the xml node have been
        !          1173:                                 * closed, make the parent to be the
        !          1174:                                 * previous one */
        !          1175:                                axl_stack_pop (doc->parentNode);
        !          1176: 
        !          1177:                                /* get the new parent */
        !          1178:                                node = axl_stack_peek (doc->parentNode);
        !          1179: 
        !          1180:                                /* restore previous xml:space value */
        !          1181:                                axl_binary_stack_pop (doc->xmlPreserve);
        !          1182: 
        !          1183:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "node properly closed, current parent node stack size: %d, parent=<%s>",
        !          1184:                                           axl_stack_size (doc->parentNode), (node != NULL) ? axl_node_get_name (node) : "--no parent--");
        !          1185: 
        !          1186:                                if (axl_stack_size (doc->parentNode) > 0)
        !          1187:                                        continue;
        !          1188:                                break;
        !          1189:                        } /* end if */
        !          1190: 
        !          1191:                        /* check here for CDATA section. This is done
        !          1192:                         * here because the following checking could
        !          1193:                         * be mixed because they starts with the same:
        !          1194:                         * < */
        !          1195:                        if ((axl_stream_peek (stream, "<![CDATA[", 9) > 0)) {
        !          1196:                                /* accet previous peek */
        !          1197:                                axl_stream_accept (stream);
        !          1198: 
        !          1199:                                /* found CDATA section, get current content */
        !          1200:                                axl_stream_set_buffer_alloc (stream, (axlStreamAlloc)__axl_doc_alloc, doc);
        !          1201:                                string = axl_stream_get_until (stream, NULL, NULL, axl_true, 1, "]]>");
        !          1202:                                axl_stream_set_buffer_alloc (stream, NULL, NULL);
        !          1203:                                if (string == NULL) {
        !          1204:                                        axl_error_new (-1, "Unable to get CDATA content. There was an error.", stream, error);
        !          1205:                                        axl_stream_free (stream);
        !          1206:                                        return NULL;
        !          1207:                                }
        !          1208: 
        !          1209:                                /* nullify internal reference to the
        !          1210:                                 * string_aux so we can use that
        !          1211:                                 * memory allocated as our
        !          1212:                                 * reference */
        !          1213:                                axl_stream_nullify (stream, LAST_CHUNK);
        !          1214: 
        !          1215:                                /* set current data */
        !          1216:                                /* axl_node_set_content_ref (node, string, -1);  */
        !          1217:                                axl_node_set_cdata_content_from_factory (doc->content_factory, node, string, -1);
        !          1218:                                continue;
        !          1219:                        } /* end if */
        !          1220: 
        !          1221: 
        !          1222:                        if ((axl_stream_peek (stream, "<", 1) > 0)) {
        !          1223:                                /* accept previous peek */
        !          1224:                                axl_stream_accept (stream);
        !          1225: 
        !          1226:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a new node being opened");
        !          1227: 
        !          1228:                                /* seems that another node is being opened */
        !          1229:                                if (!__axl_doc_parse_node (stream, doc, &node, &is_empty, error))
        !          1230:                                        return NULL;
        !          1231: 
        !          1232:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "finished parsing opened node, current parent=<%s>",
        !          1233:                                           axl_node_get_name (node));
        !          1234: 
        !          1235:                                continue;
        !          1236:                        }
        !          1237:                        
        !          1238:                        /* restore index position previous to the axl
        !          1239:                         * space consuming */
        !          1240:                        if (axl_stream_get_index (stream) > index) {
        !          1241:                                axl_stream_move (stream, index);
        !          1242:                        }
        !          1243:                        
        !          1244:                        /* found node content */
        !          1245:                        axl_stream_set_buffer_alloc (stream, (axlStreamAlloc)__axl_doc_alloc, doc);
        !          1246:                        string = axl_stream_get_until (stream, NULL, NULL, axl_false, 1, "<");
        !          1247:                        axl_stream_set_buffer_alloc (stream, NULL, NULL);
        !          1248:                        
        !          1249:                        /* check for a null content found */
        !          1250:                        if (string == NULL) {
        !          1251:                                axl_error_new (-1, "an error was found while reading the xml node content", stream, error);
        !          1252:                                axl_stream_free (stream);
        !          1253:                                return NULL;
        !          1254:                        }
        !          1255: 
        !          1256:                        /* nullify internal stream reference to have
        !          1257:                         * the unique reference */
        !          1258:                        axl_stream_nullify (stream, LAST_CHUNK);
        !          1259: 
        !          1260:                        /* set current data */
        !          1261:                        /* axl_node_set_content_ref (node, string, -1); */
        !          1262:                        axl_node_set_content_from_factory (doc->content_factory, node, string, -1); 
        !          1263: 
        !          1264:                        /* keep on looping */
        !          1265:                }
        !          1266:        }
        !          1267: 
        !          1268:        /* pop axl parent */
        !          1269:        if (! axl_stack_is_empty (doc->parentNode)) {
        !          1270:                
        !          1271:                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, 
        !          1272:                           "current parent stack size shows that not all opened nodes were closed. This means that the XML document is not properly balanced (stack size: %d)",
        !          1273:                           axl_stack_size (doc->parentNode));
        !          1274: 
        !          1275:                /* notify error */
        !          1276:                axl_error_new (-1, "XML document is not balanced, still remains xml nodes", stream, error);
        !          1277:                axl_stream_free (stream);
        !          1278: 
        !          1279:                return NULL;
        !          1280:        }
        !          1281: 
        !          1282:        /* parse complete */
        !          1283:        axl_stream_unlink (stream);
        !          1284:        axl_stream_free (stream);
        !          1285: 
        !          1286:        /* clean document internal variables */
        !          1287:        __axl_doc_clean (doc);
        !          1288: 
        !          1289:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "xml document parse COMPLETED"); 
        !          1290: 
        !          1291:        return doc;
        !          1292: }
        !          1293: 
        !          1294: /** 
        !          1295:  * @brief Creates a new empty xml document, especifying options to be
        !          1296:  * used in the header.
        !          1297:  *
        !          1298:  * This function allows to create the xml document representation the
        !          1299:  * must be used to add childs to it.
        !          1300:  *
        !          1301:  * The following is a simple example that creates a xml document (\ref
        !          1302:  * axlDoc) with a single root node (\ref axlNode):
        !          1303:  * \code
        !          1304:  * // some variables 
        !          1305:  * axlDoc  * doc;
        !          1306:  * axlNode * node;
        !          1307:  *
        !          1308:  * // dump content variables
        !          1309:  * char    * content;
        !          1310:  * int       content_size;
        !          1311:  *
        !          1312:  * // create the document 
        !          1313:  * doc = axl_doc_create (NULL, NULL, axl_true);
        !          1314:  *
        !          1315:  * // create the root document node
        !          1316:  * node = axl_node_create ("root-node");
        !          1317:  * 
        !          1318:  * // configure it as the root 
        !          1319:  * axl_doc_set_root (doc, node);
        !          1320:  *
        !          1321:  * // dump pretty
        !          1322:  * axl_doc_dump_pretty (doc, &content, &content_size, 4);
        !          1323:  *
        !          1324:  * // print the content and free
        !          1325:  * printf ("document size=%d, content: %s\n", content_size, content);
        !          1326:  * axl_free (content);
        !          1327:  * \endcode
        !          1328:  * 
        !          1329:  * @param version The xml document version. This value is optional. If
        !          1330:  * NULL is used, the library will use "1.0" as version value.
        !          1331:  *
        !          1332:  * @param encoding The document encoding to be used. This value is
        !          1333:  * optional, if NULL is provided, no encoding specification will be
        !          1334:  * used.
        !          1335:  *
        !          1336:  * @param standalone Standalone configuration flag. By default, use
        !          1337:  * axl_false.
        !          1338:  * 
        !          1339:  * @return Returns a newly allocated \ref axlDoc instance that must be
        !          1340:  * deallocated by using \ref axl_doc_free.
        !          1341:  */
        !          1342: axlDoc  * axl_doc_create                   (const char     * version, 
        !          1343:                                            const char     * encoding,
        !          1344:                                            axl_bool         standalone)
        !          1345: {
        !          1346:        axlDoc * doc;
        !          1347: 
        !          1348:        /* create a new reference, without creating  */
        !          1349:        doc = __axl_doc_new (axl_false);
        !          1350:        
        !          1351:        /* save the version */
        !          1352:        if (version != NULL)
        !          1353:                doc->version  = axl_strdup (version);
        !          1354: 
        !          1355:        /* save encoding value */
        !          1356:        if (encoding != NULL)
        !          1357:                doc->encoding = axl_strdup (encoding);
        !          1358: 
        !          1359:        /* save standalone configuration */
        !          1360:        doc->standalone       = standalone;
        !          1361:        
        !          1362:        /* return the reference created */
        !          1363:        return doc;
        !          1364: }
        !          1365: 
        !          1366: /** 
        !          1367:  * @internal Returns how many bytes will hold the document provided.
        !          1368:  * 
        !          1369:  * @param doc The document to measure.
        !          1370:  *
        !          1371:  * @param pretty_print If pretty print is activated.
        !          1372:  * 
        !          1373:  * @return The number of bytes or -1 if it fails.
        !          1374:  */
        !          1375: int __axl_doc_get_flat_size_common (axlDoc * doc, axl_bool pretty_print, int tabular) 
        !          1376: {
        !          1377:        
        !          1378:        int result;
        !          1379:        axl_return_val_if_fail (doc, -1);
        !          1380: 
        !          1381:        /* count the xml header: 
        !          1382:         *
        !          1383:         * "<?xml version='1.0'" = 19 characters 
        !          1384:         * " standalone='yes'"   = 17 characters
        !          1385:         * " encoding='enc'"     = 12 characters + strlen (enc)
        !          1386:         * " ?>"                 = 3  characters
        !          1387:         *
        !          1388:         * if pretty print add: "\r\n" +2 on windows
        !          1389:         * and \n on unix.
        !          1390:         */
        !          1391:        result = 22;
        !          1392: 
        !          1393:        if (pretty_print)
        !          1394: #ifdef __AXL_OS_WIN32__
        !          1395:                result += 2;
        !          1396: #else
        !          1397:                result += 1;
        !          1398: #endif
        !          1399: 
        !          1400:        if (doc->standalone)
        !          1401:                result += 17;
        !          1402:        
        !          1403:        if (doc->encoding != NULL) {
        !          1404:                result += 12 + strlen (doc->encoding);
        !          1405:        }
        !          1406:        
        !          1407:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "xml document header size=%d",
        !          1408:                   result);
        !          1409: 
        !          1410:        /* now, count every node that the document have */
        !          1411:        result += axl_node_get_flat_size (doc->rootNode, pretty_print, 0, tabular);
        !          1412: 
        !          1413:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "xml document body size=%d",
        !          1414:                   result);
        !          1415:        
        !          1416:        /* return current result */
        !          1417:        return result;
        !          1418: }
        !          1419: 
        !          1420: /** 
        !          1421:  * @internal
        !          1422:  * Common implementation for the dumping functions.
        !          1423:  */
        !          1424: axl_bool __axl_doc_dump_common (axlDoc * doc, char ** content, int * size, axl_bool pretty_print, int tabular, axlError ** err)
        !          1425: {
        !          1426: 
        !          1427:        char * result;
        !          1428:        int    index;
        !          1429: 
        !          1430:        /* nullify before returning */
        !          1431:        if (content)
        !          1432:                *content = NULL;
        !          1433:        if (size)
        !          1434:                *size = 0;
        !          1435: 
        !          1436:        /* perform some envrironmental checks */
        !          1437:        if (doc == NULL) {
        !          1438:                axl_error_report (err, -1, "Received null doc reference to perform dump operation.");
        !          1439:                return axl_false;
        !          1440:        } else if (content == NULL) {
        !          1441:                axl_error_report (err, -2, "Received null content reference to perform dump operation. To dump the content it is required a valid memory reference to place the content.");
        !          1442:                return axl_false;
        !          1443:        } else if (size == NULL) {
        !          1444:                axl_error_report (err, -3, "Received null size reference to perform dump operation. To dump the content it is required a valid memory reference to report size");
        !          1445:                return axl_false;
        !          1446:        }
        !          1447: 
        !          1448:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "getting document size..");
        !          1449: 
        !          1450:        /* get the about of memory to allocate so the whole xml
        !          1451:         * document fit in only one memory block */
        !          1452:        (* size)    = __axl_doc_get_flat_size_common (doc, pretty_print, tabular);
        !          1453:        (* content) = NULL;
        !          1454: 
        !          1455:        /* check returned size */
        !          1456:        if ((* size) == -1) {
        !          1457:                axl_error_report (err, -4, "Failed to perform dump operation, unable to calculate document size to perform dump.");
        !          1458:                return axl_false;
        !          1459:        }
        !          1460: 
        !          1461:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "document dump size: %d", *size);
        !          1462:        
        !          1463:        /* allocate the memory block required */
        !          1464:        result = axl_new (char, (*size) + 1);
        !          1465: 
        !          1466:        /* xml document header */
        !          1467:        index = 0;
        !          1468:        memcpy (result, "<?xml version='1.0' ", 20);
        !          1469:        index = 20;
        !          1470: 
        !          1471:        /* encoding declaration */
        !          1472:        if (doc->encoding) {
        !          1473:                /* initial encoding declaration */
        !          1474:                memcpy (result + index, "encoding='", 10);
        !          1475:                index += 10;
        !          1476: 
        !          1477:                /* copy encoding content */
        !          1478:                memcpy (result + index, doc->encoding, strlen (doc->encoding));
        !          1479:                index += strlen (doc->encoding);
        !          1480: 
        !          1481:                /* encoding trailing */
        !          1482:                memcpy (result + index, "' ", 2);
        !          1483:                index += 2;
        !          1484:        }
        !          1485: 
        !          1486:        /* standalone attribute */
        !          1487:        if (doc->standalone) {
        !          1488:                memcpy (result + index, "standalone='yes' ", 17); 
        !          1489:                index += 17;
        !          1490:        }
        !          1491: 
        !          1492:        /* header trailing */
        !          1493:        memcpy (result + index, "?>", 2);
        !          1494:        index += 2;
        !          1495: 
        !          1496:        if (pretty_print) {
        !          1497: #ifdef __AXL_OS_WIN32__
        !          1498:                memcpy (result + index, "\r\n", 2);
        !          1499:                index += 2;
        !          1500: #else
        !          1501:                memcpy (result + index, "\n", 1);
        !          1502:                index += 1;
        !          1503: #endif
        !          1504:        }
        !          1505:        
        !          1506:        /* dump node information */
        !          1507:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "starting dump at: %d", index);
        !          1508:        index    = axl_node_dump_at (doc->rootNode, result, index, pretty_print, 0, tabular);
        !          1509: 
        !          1510:        /* check dump size */
        !          1511:        if (*size != index) {
        !          1512:                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "internal dump error, inconsitent size: calculated=%d != returned=%d",
        !          1513:                           *size, index);
        !          1514: 
        !          1515:                axl_error_report (err, -5, "Internal dump error, inconsistent size: calculated=%d != returned=%d",
        !          1516:                                  *size, index);
        !          1517: 
        !          1518:                /* free allocated result */
        !          1519:                axl_free (result);
        !          1520: 
        !          1521:                *size    = -1;
        !          1522:                *content = NULL;
        !          1523: 
        !          1524:                return axl_false;
        !          1525:        }
        !          1526: 
        !          1527:        /* set results */
        !          1528:        *content = result;
        !          1529:        *size    = index;
        !          1530:        
        !          1531:        return axl_true;
        !          1532: }
        !          1533: /** 
        !          1534:  * @brief Allows to get the xml representation for the provided \ref
        !          1535:  * axlDoc reference.
        !          1536:  *
        !          1537:  * Given the \ref axlDoc reference, which represents a XML document,
        !          1538:  * this function allows to get its stringify representation.
        !          1539:  * 
        !          1540:  * @param doc The \ref axlDoc to stringify
        !          1541:  *
        !          1542:  * @param content The reference where the result will be returned.
        !          1543:  *
        !          1544:  * @param size The reference where the document content size will be
        !          1545:  * returned.
        !          1546:  *
        !          1547:  * @return The function returns \ref axl_true if the dump operation was
        !          1548:  * performed. Otherwise \ref axl_false is returned.
        !          1549:  */
        !          1550: axl_bool      axl_doc_dump                     (axlDoc  * doc, 
        !          1551:                                                char   ** content, 
        !          1552:                                                int     * size)
        !          1553: {
        !          1554:        /* use common implementation */
        !          1555:        return __axl_doc_dump_common (doc, content, size, axl_false, 0, NULL);
        !          1556: }
        !          1557: 
        !          1558: 
        !          1559: /** 
        !          1560:  * @brief Allows to perform a dump operation like \ref axl_doc_dump,
        !          1561:  * but making the output to be pretty printed.
        !          1562:  * 
        !          1563:  * @param doc The \ref axlDoc reference to be dumped.
        !          1564:  *
        !          1565:  * @param content The reference that will hold the dumped information.
        !          1566:  *
        !          1567:  * @param size Result size for the dumped information.
        !          1568:  *
        !          1569:  * @param tabular The tabular size basic unit used for level
        !          1570:  * tabulation. An appropiate value could be 4.
        !          1571:  * 
        !          1572:  * @return \ref axl_true if the document was dumped, \ref axl_false if
        !          1573:  * something has failed.
        !          1574:  */
        !          1575: axl_bool      axl_doc_dump_pretty              (axlDoc  * doc,
        !          1576:                                                char   ** content,
        !          1577:                                                int     * size,
        !          1578:                                                int       tabular)
        !          1579: {
        !          1580:        /* use common implementation */
        !          1581:        return __axl_doc_dump_common (doc, content, size, axl_true, tabular, NULL);
        !          1582: }
        !          1583: 
        !          1584: /** 
        !          1585:  * @brief Allows to dump a xml document directly to the file located
        !          1586:  * at the file path.
        !          1587:  *
        !          1588:  * This function saves you the round trip to declare variables to hold
        !          1589:  * the memory, open a file, dump the content and properly close the
        !          1590:  * output file. The function works the same as \ref axl_doc_dump but
        !          1591:  * doing the extra job to transfer the xml document into a file.
        !          1592:  *
        !          1593:  * See also \ref axl_doc_dump_pretty_to_file to get a version dumps
        !          1594:  * the content doing some pretty printing operations.
        !          1595:  * 
        !          1596:  * @param doc The document to be dumped into a file.
        !          1597:  *
        !          1598:  * @param file_path The file path where the output will be placed. The
        !          1599:  * function will require to have access rights to the file (or to
        !          1600:  * create a new file if it doesnt exists). The default behaviour is to
        !          1601:  * overwrite the file found if exists. So, if you don't want to get
        !          1602:  * content overwrited, you must provide the enough code to avoid such
        !          1603:  * situations prior calling to this function.
        !          1604:  * 
        !          1605:  * @return \ref axl_true if the dump operation was ok, otherwisde \ref
        !          1606:  * axl_false is returned.
        !          1607:  */
        !          1608: axl_bool      axl_doc_dump_to_file             (axlDoc      * doc,
        !          1609:                                                const char  * file_path)
        !          1610: {
        !          1611:        char * content = NULL;
        !          1612:        int    size    = -1;
        !          1613:        int    written = -1;
        !          1614:        FILE * fd      = NULL;
        !          1615: 
        !          1616:        /* dump content and check result */
        !          1617:        if (! __axl_doc_dump_common (doc, &content, &size, axl_false, 0, NULL)) {
        !          1618:                /* no dump operation done */
        !          1619:                return axl_false;
        !          1620:        }
        !          1621: 
        !          1622:        /* open the file and check */
        !          1623: #if defined(AXL_OS_WIN32) && ! defined(__GNUC__)
        !          1624:        if (fopen_s (&fd, file_path, "w") != 0) {
        !          1625: #else
        !          1626:        if ((fd = fopen (file_path, "w")) == NULL) {
        !          1627: #endif
        !          1628:                /* failed to open the file to dump the content */
        !          1629:                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "failed to dump document due to an error on fopen() call.");
        !          1630:                axl_free (content);
        !          1631: 
        !          1632:                return axl_false;
        !          1633:        }
        !          1634: 
        !          1635:        /* dump the content */
        !          1636:        written = fwrite (content, 1, size, fd);
        !          1637: 
        !          1638:        /* free the content */
        !          1639:        axl_free (content);
        !          1640: 
        !          1641:        /* close file */
        !          1642:        fclose (fd);
        !          1643: 
        !          1644:        /* return if we have failed to dump all the content to the
        !          1645:         * file or not. */
        !          1646:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "returning that the dump was: %s (written:%d == size:%d)", 
        !          1647:                   (written == size) ? "OK" : "FAILED", 
        !          1648:                   written, size);
        !          1649:                   
        !          1650:        return (written == size);
        !          1651: }
        !          1652: 
        !          1653: /** 
        !          1654:  * @brief Allows to dump a xml document directly to the file located
        !          1655:  * at the file path, doing pretty printing operations.
        !          1656:  *
        !          1657:  * This function saves you the round trip to declare variables to hold
        !          1658:  * the memory, open a file, dump the content and properly close the
        !          1659:  * output file. The function works the same as \ref axl_doc_dump but
        !          1660:  * doing the extra job to transfer the xml document into a file.
        !          1661:  *
        !          1662:  * See also \ref axl_doc_dump_to_file to get a version dumps the
        !          1663:  * content without doing pretty printing operations.
        !          1664:  * 
        !          1665:  * @param doc The document to be dumped into a file.
        !          1666:  *
        !          1667:  * @param file_path The file path where the output will be placed. The
        !          1668:  * function will require to have access rights to the file (or to
        !          1669:  * create a new file if it doesnt exists). The default behaviour is to
        !          1670:  * overwrite the file found if exists. So, if you don't want to get
        !          1671:  * content overwrited, you must provide the enough code to avoid such
        !          1672:  * situations prior calling to this function.
        !          1673:  * 
        !          1674:  * @param tabular The amount of white spaces to introduce as tabular
        !          1675:  * for each level found inside the xml.
        !          1676:  * 
        !          1677:  * @return \ref axl_true if the dump operation was ok, otherwisde \ref
        !          1678:  * axl_false is returned.
        !          1679:  */
        !          1680: axl_bool      axl_doc_dump_pretty_to_file      (axlDoc      * doc,
        !          1681:                                                const char  * file_path,
        !          1682:                                                int           tabular)
        !          1683: {
        !          1684:        char     * content = NULL;
        !          1685:        int        size    = -1;
        !          1686:        int        written = -1;
        !          1687:        FILE     * fd      = NULL;
        !          1688:        axlError * err     = NULL;
        !          1689: 
        !          1690:        /* dump content and check result */
        !          1691:        if (! __axl_doc_dump_common (doc, &content, &size, axl_true, tabular, &err)) {
        !          1692:                /* no dump operation done */
        !          1693:                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "failed to perform dump operation. Internal error found: %s",
        !          1694:                           axl_error_get (err));
        !          1695:                axl_error_free (err);
        !          1696:                return axl_false;
        !          1697:        } /* end if */
        !          1698: 
        !          1699:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "document dumped, now transfer that content to a file");
        !          1700: 
        !          1701:        /* open the file and check */
        !          1702: #if defined(AXL_OS_WIN32) && ! defined(__GNUC__)
        !          1703:        if (fopen_s (&fd, file_path, "w") != 0) {
        !          1704: #else
        !          1705:        if ((fd = fopen (file_path, "w")) == NULL) {
        !          1706: #endif
        !          1707:                /* failed to open the file to dump the content */
        !          1708:                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "failed to dump document due to an error on fopen() call.");
        !          1709:                axl_free (content);
        !          1710: 
        !          1711:                return axl_false;
        !          1712:        }
        !          1713: 
        !          1714:        /* dump the content */
        !          1715:        written = fwrite (content, 1, size, fd);
        !          1716: 
        !          1717:        /* free the content */
        !          1718:        axl_free (content);
        !          1719: 
        !          1720:        /* close file */
        !          1721:        fclose (fd);
        !          1722: 
        !          1723:        /* return if we have failed to dump all the content to the
        !          1724:         * file or not. */
        !          1725:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "returning that the dump was: %s (written:%d == size:%d)", 
        !          1726:                   (written == size) ? "OK" : "FAILED", 
        !          1727:                   written, size);
        !          1728:        return (written == size);
        !          1729: }
        !          1730: 
        !          1731: /** 
        !          1732:  * @brief Allows to get how much will take the \ref axlDoc instance
        !          1733:  * represented as an XML document in an storage device (like memory).
        !          1734:  *
        !          1735:  * @param doc The \ref axlDoc reference that is being requested to return its size.
        !          1736:  * 
        !          1737:  * @return The size the \ref axlDoc will represent, in a
        !          1738:  * octect-counting, or -1 if fails. The function will only fail if the
        !          1739:  * provided reference is NULL.
        !          1740:  */
        !          1741: int axl_doc_get_flat_size (axlDoc * doc)
        !          1742: {
        !          1743:        /* use common implementation */
        !          1744:        return __axl_doc_get_flat_size_common (doc, axl_false, 0);
        !          1745: }
        !          1746: 
        !          1747: 
        !          1748: /** 
        !          1749:  * @brief Parse an XML entity that is hold inside the memory pointed
        !          1750:  * by <b>entity</b> and limited by <b>entity_size</b>.
        !          1751:  *
        !          1752:  * The function parses the XML document inside the memory hold inside
        !          1753:  * the given reference. The function returns an XML document,
        !          1754:  * represented by \ref axlDoc.
        !          1755:  *
        !          1756:  * The function, optionall, could report error found inside the given
        !          1757:  * \ref axlError variable. In the case the function returns a NULL
        !          1758:  * value, this variable is filled containing the a textual diagnostic
        !          1759:  * error to be showed to the user interface and an error code.
        !          1760:  *
        !          1761:  * Here is an example:
        !          1762:  * \code
        !          1763:  * // axl document representation 
        !          1764:  * axlDoc   * doc;
        !          1765:  * axlError * error;
        !          1766:  *     
        !          1767:  *
        !          1768:  * // parse the given string 
        !          1769:  * doc = axl_doc_parse ("<?xml version='1.0' ?><axldoc />", 32, &error);
        !          1770:  * if (doc == NULL) {
        !          1771:  *      printf ("Error found: %s\n", axl_error_get (error));
        !          1772:  *      axl_error_free (error);
        !          1773:  *      return axl_false;
        !          1774:  * }
        !          1775:  *
        !          1776:  * // release document parsed 
        !          1777:  * axl_doc_free (doc); 
        !          1778:  * \endcode
        !          1779:  * 
        !          1780:  * @param entity The XML document to load.
        !          1781:  *
        !          1782:  * @param entity_size The XML document size to load. If a <b>-1</b> is
        !          1783:  * provided, strlen function is used to figure out current document
        !          1784:  * size. This is not recomended while using xml documents that include
        !          1785:  * binary data, that maybe comes inside the CDATA section or because
        !          1786:  * an utf caracter used that includes the \\0 inside its value.
        !          1787:  *
        !          1788:  * @param error Optional \ref axlError reference that will be used to
        !          1789:  * report errors found while processing xml into the \ref axlDoc
        !          1790:  * instance.
        !          1791:  * 
        !          1792:  * @return A newly allocated Axl Document, that must be deallocated
        !          1793:  * using \ref axl_doc_free, when no longer needed. The function could
        !          1794:  * return NULL if the document is not loaded properly.
        !          1795:  *
        !          1796:  * In the case an error is found while procesing the document, error
        !          1797:  * variable will be filled, if defined. -1 will be returned is
        !          1798:  * received parameter are wrong. -2 will be returned if there some
        !          1799:  * error is found while processing the document.
        !          1800:  */
        !          1801: axlDoc * axl_doc_parse (const char * entity, int entity_size, axlError ** error)
        !          1802: {
        !          1803:        return __axl_doc_parse_common (entity, entity_size, NULL, -1, error);
        !          1804: }
        !          1805: 
        !          1806: /** 
        !          1807:  * @internal
        !          1808:  * 
        !          1809:  * Allows to get current file size, in bytes, of the provided file
        !          1810:  * located at the given file path.
        !          1811:  */
        !          1812: int __axl_doc_get_file_size (char * file_path)
        !          1813: {
        !          1814:        struct stat buf;
        !          1815: 
        !          1816:        axl_return_val_if_fail (file_path, -1);
        !          1817:        
        !          1818:        /* clear the memory hold */
        !          1819:        memset (&buf, 0, sizeof (struct stat));
        !          1820: 
        !          1821:        /* return current file size */
        !          1822:        if (stat ((const char *) file_path, &buf) < 0)
        !          1823:                return -1;
        !          1824:        
        !          1825:        /* return the file size */
        !          1826:        return buf.st_size;
        !          1827:        
        !          1828: }
        !          1829: 
        !          1830: /** 
        !          1831:  * @brief Allows to parse an xml document from the given file path
        !          1832:  * location.
        !          1833:  *
        !          1834:  * This function works the same way like \ref axl_doc_parse and \ref
        !          1835:  * axl_doc_parse_strings, but using as an input, the selected file
        !          1836:  * provided by the path. In fact, all this function, use the same xml
        !          1837:  * parse engine. The advantage of this function is that it is more
        !          1838:  * efficient while reading huge xml files. 
        !          1839:  *
        !          1840:  * Here is an example:
        !          1841:  * \code
        !          1842:  * axlDoc   * doc = NULL;
        !          1843:  * axlError * error = NULL;
        !          1844:  *
        !          1845:  * // parse the provide file
        !          1846:  * doc = axl_doc_parse_from_file ("test.xml", &error);
        !          1847:  * if (doc == NULL) {
        !          1848:  *    // check error found
        !          1849:  *    printf ("ERROR: (code: %d) %s\n",
        !          1850:  *            axl_error_get_code (error),
        !          1851:  *            axl_error_get (error));
        !          1852:  *    axl_error_free (error);
        !          1853:  *    return -1;
        !          1854:  * }
        !          1855:  *
        !          1856:  * // do some stuff with the readed document
        !          1857:  * 
        !          1858:  * // release it once no longer needed
        !          1859:  * axl_doc_free (doc);
        !          1860:  * \endcode
        !          1861:  * 
        !          1862:  * @param file_path The file path to report.
        !          1863:  *
        !          1864:  * @param error The \ref axlError where errors found will be reported.
        !          1865:  * 
        !          1866:  * @return 
        !          1867:  */
        !          1868: axlDoc  * axl_doc_parse_from_file          (const char * file_path,
        !          1869:                                            axlError  ** error)
        !          1870: {
        !          1871:        return __axl_doc_parse_common (NULL, -1, file_path, -1, error);
        !          1872: }
        !          1873: 
        !          1874: 
        !          1875: /** 
        !          1876:  * @brief Allows to parse an xml document that is provided as a set of
        !          1877:  * strings ended by a NULL reference.
        !          1878:  *
        !          1879:  * This function works the same way like \ref axl_doc_parse function,
        !          1880:  * but allowing to provide a set of strings. Here is an example:
        !          1881:  * 
        !          1882:  * \code
        !          1883:  * // a document reference
        !          1884:  * axlDoc   * doc;
        !          1885:  *
        !          1886:  * // note that the error is optional, and, if provided, it is not
        !          1887:  * // required to initialize it.
        !          1888:  * axlError * error;
        !          1889:  * 
        !          1890:  * // parse the following set of strings
        !          1891:  * doc = axl_doc_parse_strings (&error, 
        !          1892:  *                              "<?xml version='1.0' standalone='yes' ?>",
        !          1893:  *                              "<complex>",
        !          1894:  *                              "  <data>",
        !          1895:  *                              "     <row>",
        !          1896:  *                              "       <td>",
        !          1897:  *                              "          <value attr='10'/>
        !          1898:  *                              "       </td>",
        !          1899:  *                              "     </row>",
        !          1900:  *                              "  </data>",
        !          1901:  *                              "</complex>",
        !          1902:  *                              NULL); // last null reference 
        !          1903:  * // check for an error
        !          1904:  * if (doc == NULL) {
        !          1905:  *      printf ("There was an error while parsing the document: (code: %d) %s\n",
        !          1906:  *              axl_error_get_code (error), axl_error_get (error));
        !          1907:  *      axl_error_free (error);
        !          1908:  * }
        !          1909:  * \endcode
        !          1910:  * 
        !          1911:  * @param error An optional \ref axlError reference where a textual
        !          1912:  * diagnostic will be provided.
        !          1913:  * 
        !          1914:  * @return A newly created \ref axlDoc reference that must be
        !          1915:  * deallocated by using \ref axl_doc_free when no longer needed.
        !          1916:  */
        !          1917: axlDoc  * axl_doc_parse_strings            (axlError ** error,
        !          1918:                                            ...)
        !          1919: {
        !          1920:        axlDoc   * doc;
        !          1921:        va_list    args;
        !          1922:        char     * string     = NULL;
        !          1923:        char     * stream     = NULL;
        !          1924:        char     * stream_aux = NULL;
        !          1925:        
        !          1926:        /* check incoming data */
        !          1927:        axl_return_val_if_fail (error, NULL);
        !          1928:        
        !          1929:        /* open the stdargs */
        !          1930:        va_start (args, error);
        !          1931:        
        !          1932:        while ((string = va_arg (args, char *)) != NULL) {
        !          1933:                stream_aux = stream;
        !          1934:                stream = axl_stream_concat (stream, string);
        !          1935:                if (stream_aux != NULL) {
        !          1936:                        axl_free (stream_aux);
        !          1937:                        stream_aux = NULL;
        !          1938:                }
        !          1939:        }
        !          1940: 
        !          1941:        /* close the stdargs */
        !          1942:        va_end (args);
        !          1943: 
        !          1944:        /* check that we have received, at least, an string
        !          1945:         * parseable */
        !          1946:        if (stream == NULL)
        !          1947:                return NULL;
        !          1948: 
        !          1949:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "string to parse: %s", stream);
        !          1950: 
        !          1951:        /* parse the string */
        !          1952:        doc = axl_doc_parse (stream, -1, error);
        !          1953: 
        !          1954:        /* free the stream */
        !          1955:        axl_free (stream);
        !          1956: 
        !          1957:        return doc;
        !          1958: }
        !          1959: 
        !          1960: /** 
        !          1961:  * @internal 
        !          1962:  * 
        !          1963:  * Internal support function which checks the provided child and its
        !          1964:  * childs are equal.
        !          1965:  */
        !          1966: axl_bool __axl_doc_are_equal (axlNode * node, axlNode * node2, axl_bool trimmed, axlError ** error)
        !          1967: {
        !          1968:        int       iterator;
        !          1969:        int       length;
        !          1970:        int       length2;
        !          1971: 
        !          1972:        axlItem * child;
        !          1973:        axlItem * child2;
        !          1974:        
        !          1975:        /* check if parent nodes are equal */
        !          1976:        if (! axl_node_are_equal (node, node2))
        !          1977:                return axl_false;
        !          1978: 
        !          1979:        /* iterate over all childs inside the node */
        !          1980:        iterator = 0;
        !          1981:        length   = axl_node_get_child_num (node);
        !          1982:        length2  = axl_node_get_child_num (node2);
        !          1983: 
        !          1984:        if (length != length2) {
        !          1985:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "child number differs, documents aren't equal");
        !          1986:                axl_error_report (error, -1,  "child number differs, documents aren't equal");
        !          1987:                return axl_false;
        !          1988:        }
        !          1989: 
        !          1990:        /* get the first item inside the node */
        !          1991:        child  = axl_item_get_first_child (node);
        !          1992:        child2 = axl_item_get_first_child (node2);
        !          1993: 
        !          1994:        /* for each item child found in both nodes */
        !          1995:        while (child != NULL && child2 != NULL) {
        !          1996:                
        !          1997:                if (child == NULL)  {
        !          1998:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "child from the first document is null..");
        !          1999:                        axl_error_report (error, -1, "child from the first document is null..");
        !          2000:                }
        !          2001: 
        !          2002:                if (child2 == NULL) {
        !          2003:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "child from the second document is null..");
        !          2004:                        axl_error_report (error, -1,  "child from the second document is null..");
        !          2005:                }
        !          2006: 
        !          2007:                /* check if these nodes are also equal */
        !          2008:                if (! axl_item_are_equal_full (child, child2, trimmed, error)) {
        !          2009:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "items  aren't equal, document is not equal");
        !          2010:                        return axl_false;
        !          2011:                }
        !          2012: 
        !          2013:                /* check its childs in the case the axl item is
        !          2014:                 * representing an item node */
        !          2015:                if (axl_item_get_type (child) == ITEM_NODE) {
        !          2016:                        /* get a reference */
        !          2017:                        node  = axl_item_get_data (child);
        !          2018:                        node2 = axl_item_get_data (child2);
        !          2019: 
        !          2020:                        if (! __axl_doc_are_equal (node, node2, trimmed, error)) {
        !          2021:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "nodes <%s> and <%s> aren't equal, document is not equal", 
        !          2022:                                           axl_node_get_name (node), axl_node_get_name (node2));
        !          2023:                                return axl_false;
        !          2024:                        } /* end if */
        !          2025:                }
        !          2026: 
        !          2027:                /* get a referece to the next childs to check */
        !          2028:                child  = axl_item_get_next (child);
        !          2029:                child2 = axl_item_get_next (child2);
        !          2030:                
        !          2031:        } /* end while */
        !          2032: 
        !          2033:        /* the nodes recieved are equal */
        !          2034:        return (child == NULL && child2 == NULL);
        !          2035: }
        !          2036: 
        !          2037: /** 
        !          2038:  * @internal Common implementation for equal documents.
        !          2039:  */
        !          2040: axl_bool      axl_doc_are_equal_common (axlDoc    * doc,
        !          2041:                                        axlDoc    * doc2,
        !          2042:                                        axl_bool    trimmed,
        !          2043:                                        axlError ** error)
        !          2044: {
        !          2045:        axlNode * node;
        !          2046:        axlNode * node2;
        !          2047: 
        !          2048:        /* check first reference */
        !          2049:        if (doc == NULL) {
        !          2050:                axl_error_report (error, -1, "Documents differs because first document reference is null");
        !          2051:                return axl_false;
        !          2052:        }
        !          2053:        /* check second reference */
        !          2054:        if (doc2 == NULL) {
        !          2055:                axl_error_report (error, -1, "Documents differs because second document reference is null");
        !          2056:                return axl_false;
        !          2057:        }
        !          2058: 
        !          2059:        /* first, check the document root */
        !          2060:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "checking that both documents are equal");
        !          2061: 
        !          2062:        node  = axl_doc_get_root (doc);
        !          2063:        if (node == NULL) {
        !          2064:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "document(a) doesn't have document root ..");
        !          2065:        }
        !          2066:        node2 = axl_doc_get_root (doc2);
        !          2067:        if (node2 == NULL) {
        !          2068:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "document(b) doesn't have document root ..");
        !          2069:        }
        !          2070: 
        !          2071:        /* call to common implemenation, activating triming */
        !          2072:        return __axl_doc_are_equal (node, node2, trimmed, error);
        !          2073: }
        !          2074: 
        !          2075: /** 
        !          2076:  * @brief Allows to perform a document equal check against order,
        !          2077:  * relaxing the checking done to contet found inside nodes.
        !          2078:  *
        !          2079:  * This function works the same as \ref axl_doc_are_equal but
        !          2080:  * considering that two content are equal no matter which is the
        !          2081:  * number of white spaces (in the W3C, ' ', \\t, \\r and \\n) are
        !          2082:  * found starting and ending the content.
        !          2083:  *
        !          2084:  * Under this approach the both document aren't exactly the same, but
        !          2085:  * usually, white spaces found starting and ending content have no
        !          2086:  * meaning for the application processing xml. In the case you want a
        !          2087:  * fully equal document checking you must \ref axl_doc_are_equal
        !          2088:  *
        !          2089:  * @param doc The document to check.
        !          2090:  * @param doc2 The second document to check
        !          2091:  * 
        !          2092:  * @return \ref axl_true if both documents are equal in the sense
        !          2093:  * described, otherwise \ref axl_false is returned.
        !          2094:  */
        !          2095: axl_bool      axl_doc_are_equal_trimmed        (axlDoc * doc,
        !          2096:                                                axlDoc * doc2)
        !          2097: {
        !          2098:        /* call to common implemenation, activating triming */
        !          2099:        return axl_doc_are_equal_common (doc, doc2, axl_true, NULL);
        !          2100: }
        !          2101: 
        !          2102: /** 
        !          2103:  * @brief Allows to check if the provided two references represents
        !          2104:  * equivalent xml documents.
        !          2105:  *
        !          2106:  * There is an alternative document checking function (\ref
        !          2107:  * axl_doc_are_equal_trimmed) which considered that content found
        !          2108:  * inside a xml node is equal if they share the same information
        !          2109:  * without considering white spaces found starting and ending both
        !          2110:  * elements being checked.
        !          2111:  *
        !          2112:  * This function considers that two documents are equal only and only
        !          2113:  * if all nodes, attributes and content found is exactly, byte by
        !          2114:  * byte, as found in the other document.
        !          2115:  * 
        !          2116:  * @param doc The first XML document to check.
        !          2117:  * @param doc2 The second XML document to check.
        !          2118:  * 
        !          2119:  * @return axl_true if both documents represents the same document,
        !          2120:  * axl_false if not.
        !          2121:  */
        !          2122: axl_bool      axl_doc_are_equal                (axlDoc * doc, 
        !          2123:                                                axlDoc * doc2)
        !          2124: {
        !          2125:        /* call to common implemenation, activating triming */
        !          2126:        return axl_doc_are_equal_common (doc, doc2, axl_true, NULL);
        !          2127: }
        !          2128: 
        !          2129: /** 
        !          2130:  * @brief Allows to check if the provided two references represents
        !          2131:  * equivalent xml documents.
        !          2132:  *
        !          2133:  * There is an alternative document checking function (\ref
        !          2134:  * axl_doc_are_equal_trimmed) which considered that content found
        !          2135:  * inside a xml node is equal if they share the same information
        !          2136:  * without considering white spaces found starting and ending both
        !          2137:  * elements being checked.
        !          2138:  *
        !          2139:  * This function considers that two documents are equal only and only
        !          2140:  * if all nodes, attributes and content found is exactly, byte by
        !          2141:  * byte, as found in the other document.
        !          2142:  * 
        !          2143:  * @param doc The first XML document to check.
        !          2144:  *
        !          2145:  * @param doc2 The second XML document to check.
        !          2146:  *
        !          2147:  * @param trimmed Allows to configure if node content must be trimmed
        !          2148:  * before checking them (\ref axl_doc_are_equal_trimmed).
        !          2149:  *
        !          2150:  * @param error An optional reference to an \ref axlError node where
        !          2151:  * difference information will be reported.
        !          2152:  * 
        !          2153:  * @return axl_true if both documents represents the same document,
        !          2154:  * axl_false if not.
        !          2155:  */
        !          2156: axl_bool      axl_doc_are_equal_full           (axlDoc    * doc, 
        !          2157:                                                axlDoc    * doc2,
        !          2158:                                                axl_bool    trimmed,
        !          2159:                                                axlError ** error)
        !          2160: {
        !          2161:        /* call to common implemenation, activating triming */
        !          2162:        return axl_doc_are_equal_common (doc, doc2, trimmed, error);
        !          2163: }
        !          2164: 
        !          2165: 
        !          2166: 
        !          2167: 
        !          2168: /** 
        !          2169:  * @brief Allows to get current root node for the given xml document,
        !          2170:  * represented by the \ref axlDoc instance.
        !          2171:  *
        !          2172:  * Every XML document has a very first node, which enclose all childs
        !          2173:  * found inside the document, that is called the root node. This xml
        !          2174:  * node, 
        !          2175:  *
        !          2176:  * This function couldn't return NULL because every well opened xml
        !          2177:  * document, always have a root node. However, the function could
        !          2178:  * return a NULL value if the document received is a null reference.
        !          2179:  * 
        !          2180:  * @param doc The xml document (\ref axlDoc) where the root node will
        !          2181:  * be returned. 
        !          2182:  * 
        !          2183:  * @return The root node (\ref axlNode) or NULL if fails.
        !          2184:  */
        !          2185: axlNode * axl_doc_get_root                 (axlDoc * doc)
        !          2186: {
        !          2187:        axl_return_val_if_fail (doc, NULL);
        !          2188:        
        !          2189:        /* return current root node */
        !          2190:        return doc->rootNode;
        !          2191: }
        !          2192: 
        !          2193: /** 
        !          2194:  * @internal
        !          2195:  *
        !          2196:  * @brief An always return 1 to make the list to store elements append
        !          2197:  * at the end.
        !          2198:  */
        !          2199: int __axl_doc_get_are_equal (axlPointer a, axlPointer b)
        !          2200: {
        !          2201:        return 1;
        !          2202: }
        !          2203: 
        !          2204: /** 
        !          2205:  * @brief Allows to get a particular node (or list of nodes) that are
        !          2206:  * located at a selected path.
        !          2207:  *
        !          2208:  * Providing a path, the function lookups for nodes stored on the
        !          2209:  * selected location inside the provided document. The path provided
        !          2210:  * doesn't follow the XPath extension. 
        !          2211:  *
        !          2212:  * Taking as a reference for the xml to be explained on the following
        !          2213:  * rules:
        !          2214:  * \code
        !          2215:  * <complex>
        !          2216:  *     <data>
        !          2217:  *       <node>
        !          2218:  *          <row>10</row>
        !          2219:  *       </node>
        !          2220:  *     </data>
        !          2221:  * </complex>
        !          2222:  * \endcode
        !          2223:  *
        !          2224:  *
        !          2225:  * Here is how the path works:
        !          2226:  * 
        !          2227:  * - If provided a "/", the root node is returned. This is same than
        !          2228:  * provided the root node name, like "/complex", when it is expected
        !          2229:  * to find as root node &lt;complex>. However, providing a particular
        !          2230:  * node to search allows to get ensure that the root node is the one
        !          2231:  * looked up.
        !          2232:  *
        !          2233:  * - To select nodes inside the first root node, in a generic way,
        !          2234:  * without providing details about the root node name, you could use
        !          2235:  * "//\*". This will provide all nodes that are found inside the root
        !          2236:  * node, whatever it is called. If it is required to get all nodes,
        !          2237:  * inside the root node, ensuring that the root one is called
        !          2238:  * "complex" you should use: "/complex/\*"
        !          2239:  *
        !          2240:  * - If it is required to get a selected node inside the root node,
        !          2241:  * that is called in a particular way you can use: //data. Again, if
        !          2242:  * it is required to ensure that a particular node exists, from the
        !          2243:  * top level down the leaf node, it will required to write something
        !          2244:  * like: "/complex/data". 
        !          2245:  *
        !          2246:  * - Remember that is totally different to query for "/complex/data"
        !          2247:  * than "/complex/data/\*". The first one, returns the node, or nodes,
        !          2248:  * called <b>data</b> that are inside the root node called
        !          2249:  * <b>complex</b>, while the second one says: return all nodes inside
        !          2250:  * the node <b>data</b> that is inside the root node called
        !          2251:  * <b>complex</b>
        !          2252:  *
        !          2253:  * Finally, keep in mind that this function only returns nodes. To get
        !          2254:  * node content, attributes or anything else, you'll have to get the
        !          2255:  * node first and then operate with it.
        !          2256:  *
        !          2257:  *
        !          2258:  *
        !          2259:  * @param doc The \ref axlDoc reference where the lookup will be
        !          2260:  * performed.
        !          2261:  *
        !          2262:  * @param path_to A path to the node (nodes) that are inside the path
        !          2263:  * especifyied.
        !          2264:  * 
        !          2265:  * @return A list of nodes (\ref axlNode) if the case something is
        !          2266:  * found or NULL if fails to find something at the given path. If the
        !          2267:  * path is right but no node match with it or there is no node, the
        !          2268:  * function will return NULL reference rather a list with no
        !          2269:  * nodes. Returned value must be deallocated by using \ref
        !          2270:  * axl_list_free.
        !          2271:  */
        !          2272: axlList * axl_doc_get_list                  (axlDoc * doc, const char * path_to)
        !          2273: {
        !          2274:        axlList  * nodes;
        !          2275:        axlNode  * node     = NULL;
        !          2276:        int        iterator = 0;
        !          2277:        char    ** paths    = 0;
        !          2278:        
        !          2279: 
        !          2280:        axl_return_val_if_fail (doc, NULL);
        !          2281:        axl_return_val_if_fail (path_to, NULL);
        !          2282:        axl_return_val_if_fail (path_to[0] == '/', NULL);
        !          2283: 
        !          2284:        /* create the axl list */
        !          2285:        nodes = axl_list_new (__axl_doc_get_are_equal, NULL);
        !          2286:        
        !          2287:        /* split paths */
        !          2288:        paths = axl_stream_split (path_to, 1, "/");
        !          2289:        axl_return_val_if_fail (paths, nodes);
        !          2290: 
        !          2291:        /* get a reference to the root node */
        !          2292:        node = doc->rootNode;
        !          2293: 
        !          2294:        /* basic case, check for the root node */
        !          2295:        if (strlen (paths[1]) != 0) {
        !          2296:                /* check the node is the one requested */
        !          2297:                if (! NODE_CMP_NAME (node, paths[1])) {
        !          2298:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "requested root node = %s wasn't found, current root %s", paths[1],
        !          2299:                                   axl_node_get_name (doc->rootNode));
        !          2300:                        axl_list_free (nodes);
        !          2301:                        axl_stream_freev (paths);
        !          2302:                        return NULL;
        !          2303:                }
        !          2304:        }
        !          2305: 
        !          2306:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found node: %s for path=%s", paths[1], path_to);
        !          2307: 
        !          2308:        /* now the general case */
        !          2309:        iterator = 2;
        !          2310:        while ((paths[iterator] != NULL) && (strlen (paths[iterator]) > 0)) {
        !          2311:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "checking path item %s", paths[iterator]);
        !          2312:                
        !          2313:                /* check that the last path is used */
        !          2314:                if (axl_cmp (paths[iterator], "*") && 
        !          2315:                    (axl_stream_strv_num (paths) != iterator + 1)) {
        !          2316:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "using the '*' at that path different from the last one.", paths[iterator]);
        !          2317:                        axl_list_free (nodes);
        !          2318:                        axl_stream_freev (paths);
        !          2319:                        return NULL;
        !          2320:                }
        !          2321: 
        !          2322:                /* get a reference to the node searched */
        !          2323:                node = axl_node_get_child_called (node, paths[iterator]);
        !          2324:                if (node == NULL) {
        !          2325:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "the node located at %s wasn't found.", path_to);
        !          2326: 
        !          2327:                        axl_list_free (nodes);
        !          2328:                        axl_stream_freev (paths);
        !          2329:                        return NULL;
        !          2330:                }
        !          2331:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found node: %s", paths[iterator]);
        !          2332: 
        !          2333:                /* update iterator value */
        !          2334:                iterator++;
        !          2335:        }
        !          2336: 
        !          2337:        /* add the node found */
        !          2338:        axl_list_add (nodes, node);
        !          2339: 
        !          2340:        /* free paths */
        !          2341:        axl_stream_freev (paths);
        !          2342: 
        !          2343:        /* return the node found */
        !          2344:        return nodes;
        !          2345: }
        !          2346: 
        !          2347: /** 
        !          2348:  * @brief Allows to return only one node for the selected path.
        !          2349:  *
        !          2350:  * This function works the same way like \ref axl_doc_get_list but
        !          2351:  * extracting the first node reference found inside the list returned
        !          2352:  * by the previous function, and returning it.
        !          2353:  *
        !          2354:  * Many times, a path is selected because it is know that under that
        !          2355:  * location couldn't be more than one element. However, using \ref
        !          2356:  * axl_doc_get_list function makes this task really anoying because
        !          2357:  * you have to get the list, extract the node, from the list, and
        !          2358:  * releasing the list reference to actually get access to the node
        !          2359:  * looked up.
        !          2360:  *
        !          2361:  * This function allows you to get access to the node stored on the
        !          2362:  * selected location, and, if a path that provides several nodes is
        !          2363:  * returned, only the first node found on that list is returned.
        !          2364:  * 
        !          2365:  * @param doc The \ref axlDoc document where the node will be returned.
        !          2366:  * @param path_to A path to the node to get.
        !          2367:  * 
        !          2368:  * @return A reference to a \ref axlNode instace, or NULL if
        !          2369:  * fails. Returned reference must not be deallocated.
        !          2370:  */
        !          2371: axlNode * axl_doc_get                      (axlDoc * doc, const char * path_to)
        !          2372: {
        !          2373:        axlList * list = NULL;
        !          2374:        axlNode * node = NULL;
        !          2375:        
        !          2376:        axl_return_val_if_fail (doc, NULL);
        !          2377:        axl_return_val_if_fail (path_to, NULL);
        !          2378: 
        !          2379:        /* get the list of nodes */
        !          2380:        list = axl_doc_get_list (doc, path_to);
        !          2381:        if (list == NULL)
        !          2382:                return NULL;
        !          2383:        
        !          2384:        /* get the node requested */
        !          2385:        if (axl_list_length (list) > 0)
        !          2386:                node = axl_list_get_nth (list, 0);
        !          2387: 
        !          2388:        axl_list_free (list);
        !          2389:        return node;
        !          2390:        
        !          2391: }
        !          2392: 
        !          2393: /** 
        !          2394:  * @brief Allows to get the node content for the final node provided
        !          2395:  * by the path.
        !          2396:  * 
        !          2397:  * @param doc The (\ref axlDoc) xml document where the content will be
        !          2398:  * looked up.
        !          2399:  *
        !          2400:  * @param path_to Path to the node where the content will be returned.
        !          2401:  *
        !          2402:  * @param content_size An optional reference to a variable to store
        !          2403:  * the size of the content returned. If the function receives NULL,
        !          2404:  * the content size will not be returned.
        !          2405:  * 
        !          2406:  * @return A reference to the content that the node have or NULL if
        !          2407:  * fails. The function could fail either because the node doesn't have
        !          2408:  * content or because the node identified by the path doesn't
        !          2409:  * exist. The result returned must not be deallocated.
        !          2410:  */
        !          2411: const char    * axl_doc_get_content_at     (axlDoc     * doc,
        !          2412:                                            const char * path_to,
        !          2413:                                            int        * content_size)
        !          2414: {
        !          2415: 
        !          2416:        axlNode * node;
        !          2417: 
        !          2418:        /* get the node reference */
        !          2419:        node = axl_doc_get (doc, path_to);
        !          2420:        axl_return_val_if_fail (node, NULL);
        !          2421: 
        !          2422:        /* return the content requested */
        !          2423:        return axl_node_get_content (node, content_size);
        !          2424:        
        !          2425: }
        !          2426: 
        !          2427: /** 
        !          2428:  * @brief Gets current axl Document encoding.
        !          2429:  * 
        !          2430:  * @param doc The document where the encoding will be retrieved.
        !          2431:  * 
        !          2432:  * @return A valid \ref axlDoc reference. NULL is returned in the case
        !          2433:  * a NULL \ref axlDoc reference is received. The value returned by
        !          2434:  * this function must not be deallocated.
        !          2435:  */
        !          2436: const char * axl_doc_get_encoding (axlDoc * doc)
        !          2437: {
        !          2438:        /* check parameter received */
        !          2439:        axl_return_val_if_fail (doc, NULL);
        !          2440:        
        !          2441:        return (doc->encoding != NULL) ? doc->encoding : "";
        !          2442: }
        !          2443: 
        !          2444: /** 
        !          2445:  * @brief Allows to get current standalone configuration for the given
        !          2446:  * axlDoc document.
        !          2447:  * 
        !          2448:  * @param doc The \ref axlDoc document where the standalone value will
        !          2449:  * be retreived.
        !          2450:  * 
        !          2451:  * @return \ref axl_true if the standalone configuration, found inside
        !          2452:  * the xml header is set to AXL_TRUE. Otherwise \ref axl_false is
        !          2453:  * returned. Keep in mind that the function will return an \ref
        !          2454:  * axl_false value if a null reference is received.
        !          2455:  */
        !          2456: axl_bool     axl_doc_get_standalone (axlDoc * doc)
        !          2457: {
        !          2458:        axl_return_val_if_fail (doc, axl_false);
        !          2459: 
        !          2460:        /* return current configuration */
        !          2461:        return doc->standalone;
        !          2462: }
        !          2463: 
        !          2464: /** 
        !          2465:  * @brief Allows to configure the document root for the given \ref
        !          2466:  * axlDoc instance.
        !          2467:  *
        !          2468:  * Every xml document has a xml node root. This is the first node,
        !          2469:  * that holds all childs. This function allows to configure that xml
        !          2470:  * document root. See also \ref axl_doc_get_root.
        !          2471:  *
        !          2472:  * Remember that previous document root will not be deallocated so,
        !          2473:  * the user space must take care about previous reference.
        !          2474:  *
        !          2475:  * @param doc The \ref axlDoc where the document root will be
        !          2476:  * configured.
        !          2477:  *
        !          2478:  * @param root The \ref axlNode used to configure the new document
        !          2479:  * root. The reference received can be null. In this case, it is
        !          2480:  * considered that the root node is being unset.
        !          2481:  */
        !          2482: void    axl_doc_set_root (axlDoc * doc, axlNode * root)
        !          2483: {
        !          2484:        axl_return_if_fail (doc);
        !          2485: 
        !          2486:        /* set the new root */
        !          2487:        doc->rootNode = root;
        !          2488: 
        !          2489:        /* if the reference received is null, just return */
        !          2490:        if (root == NULL)
        !          2491:                return;
        !          2492: 
        !          2493:        /* set a refeference to the document root */
        !          2494:        axl_node_set_doc (root, doc);
        !          2495: 
        !          2496:        return;
        !          2497: }
        !          2498: 
        !          2499: /** 
        !          2500:  * @internal
        !          2501:  *
        !          2502:  * @brief Allows to set the given axlNode to be child of the current
        !          2503:  * parent.
        !          2504:  *
        !          2505:  * @param doc The \ref axlDoc reference where the \ref axlNode will be
        !          2506:  * configured.
        !          2507:  *
        !          2508:  * @param node The \ref axlNode reference to set as a child for the
        !          2509:  * parent node.
        !          2510:  */
        !          2511: void     axl_doc_set_child_current_parent (axlDoc * doc, axlNode * node)
        !          2512: {
        !          2513:        axlNode * parent;
        !          2514: 
        !          2515:        /* perform some environment checks */
        !          2516:        axl_return_if_fail (doc);
        !          2517:        axl_return_if_fail (node);
        !          2518:        
        !          2519:        parent = axl_stack_peek (doc->parentNode);
        !          2520:        axl_return_if_fail (parent);
        !          2521: 
        !          2522:        /* set the child for the current parent */
        !          2523:        axl_node_set_child (parent, node);
        !          2524: 
        !          2525:        /* set the new parent */
        !          2526:        axl_stack_push (doc->parentNode, node);
        !          2527: 
        !          2528:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "pushed a new parent into the stack <%s>, current status after operation: %d",
        !          2529:                   axl_node_get_name (node), axl_stack_size (doc->parentNode));
        !          2530:        
        !          2531:        return;
        !          2532: }
        !          2533: 
        !          2534: /** 
        !          2535:  * @internal Allows to make current \ref axlDoc to pop current parent
        !          2536:  * node, making the new parent node the previously opened.
        !          2537:  *
        !          2538:  * This API is deprecated (internal function used in the past).
        !          2539:  * 
        !          2540:  * @param doc The \ref axlDoc where the pop operation will be
        !          2541:  * performed.
        !          2542:  */
        !          2543: void     axl_doc_pop_current_parent       (axlDoc * doc)
        !          2544: {
        !          2545:        return;
        !          2546: }
        !          2547: 
        !          2548: /** 
        !          2549:  * @brief Allows to configure a PI target, with its content, on the given \ref axlDoc.
        !          2550:  *
        !          2551:  * A PI is a process instruction that is passed to the
        !          2552:  * application. This process instruction has a target name, which
        !          2553:  * acording to the standard is the application which should receive
        !          2554:  * the target content and an optional target content associated.
        !          2555:  *
        !          2556:  * This function allows to configure (add) a new PI item inside the
        !          2557:  * given xml document (\ref axlDoc). The PI content is optional. If
        !          2558:  * provided NULL, the PI will only contain as information the PI
        !          2559:  * target.
        !          2560:  *
        !          2561:  * Here is how a process instruction is used inside a xml document:
        !          2562:  * \code
        !          2563:  * <?xml version='1.0'>
        !          2564:  * <?launch "some command" ?>
        !          2565:  * <complex>
        !          2566:  *    <?data "some data" ?>
        !          2567:  *    <?data "more data" ?>
        !          2568:  *    <data>
        !          2569:  *       <row attr="20" />
        !          2570:  *    </data>
        !          2571:  * </complex>
        !          2572:  * \endcode
        !          2573:  *
        !          2574:  * Previous example shows how to use PI (process instructions) from
        !          2575:  * outside the xml root node (<b>complex</b>, and also how it is used
        !          2576:  * from inside a xml node definition <b>complex</b>. 
        !          2577:  *
        !          2578:  * As you can see, PI elements could be used as many times as you want
        !          2579:  * and places allowed to do so are just right before begining with the
        !          2580:  * root node and inside xml node definitions.
        !          2581:  * 
        !          2582:  * @param doc The axlDocument where the PI will be added.
        !          2583:  * @param target The PI target name.
        !          2584:  * @param content The PI content (optional value).
        !          2585:  */
        !          2586: void      axl_doc_add_pi_target            (axlDoc * doc, 
        !          2587:                                            char * target, 
        !          2588:                                            char * content)
        !          2589: {
        !          2590:        axlPI * pi;
        !          2591: 
        !          2592:        /* perform some environmental checks */
        !          2593:        axl_return_if_fail (doc);
        !          2594:        axl_return_if_fail (target);
        !          2595: 
        !          2596:        /* create the PI element */
        !          2597:        pi = axl_pi_create (target, content);
        !          2598: 
        !          2599:        /* add the PI */
        !          2600:        axl_list_add (doc->piTargets, pi);
        !          2601: 
        !          2602:        return;
        !          2603: }
        !          2604: 
        !          2605: /** 
        !          2606:  * @brief Allows to check if the provided Processing instruction
        !          2607:  * target is defined on the given xml document (\ref axlDoc).
        !          2608:  *
        !          2609:  * Processing instruction are a way to configure the xml document with
        !          2610:  * processing information to instruct the application level that is
        !          2611:  * going to consume the XML information.
        !          2612:  *
        !          2613:  * @param doc The document where the processing instruction will be read.
        !          2614:  *
        !          2615:  * @param pi_target The process instruction name.
        !          2616:  * 
        !          2617:  * @return axl_true is the processing instruction is defined,
        !          2618:  * otherwise axl_false is returned.
        !          2619:  */
        !          2620: axl_bool      axl_doc_has_pi_target            (axlDoc * doc, char * pi_target)
        !          2621: {
        !          2622:        axlPI * pi;
        !          2623:        int     iterator = 0;
        !          2624:        int     length   = 0;
        !          2625: 
        !          2626:        
        !          2627:        axl_return_val_if_fail (doc,       axl_false);
        !          2628:        axl_return_val_if_fail (pi_target, axl_false);
        !          2629: 
        !          2630:        /* get the length for the items inserted */
        !          2631:        length = axl_list_length (doc->piTargets);
        !          2632:        while (iterator < length) {
        !          2633:                /* for each item inserted */
        !          2634:                pi = axl_list_get_nth (doc->piTargets, iterator);
        !          2635:                /* only check the first ocurrency */
        !          2636:                if (axl_cmp (pi->name, pi_target))
        !          2637:                        return axl_true;
        !          2638: 
        !          2639:                iterator++;
        !          2640:        }
        !          2641:        
        !          2642:        return axl_false;
        !          2643: }
        !          2644: 
        !          2645: /** 
        !          2646:  * @brief Allows to get current processing instruction content.
        !          2647:  * 
        !          2648:  * @param doc The document where the processing instruction is placed.
        !          2649:  *
        !          2650:  * @param pi_target The processing instruction target to get current
        !          2651:  * content.
        !          2652:  * 
        !          2653:  * @return An internal reference to the process instruction target
        !          2654:  * content. Value returned mustn't be deallocated
        !          2655:  */
        !          2656: char    * axl_doc_get_pi_target_content    (axlDoc * doc, char * pi_target)
        !          2657: {
        !          2658:        axlPI * pi;
        !          2659:        int     iterator = 0;
        !          2660:        int     length   = 0;
        !          2661: 
        !          2662:        axl_return_val_if_fail (doc,       NULL);
        !          2663:        axl_return_val_if_fail (pi_target, NULL);
        !          2664: 
        !          2665:        /* get the length for the items inserted */
        !          2666:        length = axl_list_length (doc->piTargets);
        !          2667:        while (iterator < length) {
        !          2668:                /* for each item inserted */
        !          2669:                pi = axl_list_get_nth (doc->piTargets, iterator);
        !          2670:                /* only check the first ocurrency */
        !          2671:                if (axl_cmp (pi->name, pi_target))
        !          2672:                        return pi->content;
        !          2673: 
        !          2674:                iterator++;
        !          2675:        }
        !          2676: 
        !          2677:        return NULL;
        !          2678: }
        !          2679: 
        !          2680: /** 
        !          2681:  * @brief Allows to get a list which contains \ref axlPI nodes,
        !          2682:  * representing all process instruction that the document has.
        !          2683:  *
        !          2684:  * While using PI, you can use the following functions to get PI
        !          2685:  * information:
        !          2686:  * 
        !          2687:  *  - \ref axl_doc_has_pi_target
        !          2688:  *  - \ref axl_doc_get_pi_target_content
        !          2689:  *
        !          2690:  * However, this function will return first ocurrency for PI found
        !          2691:  * inside the xml document. If you don't use repeated PI elements, you
        !          2692:  * won't find problems, but, if you need to iterate ever all PI found
        !          2693:  * or you are using repeated PI, you can use this function as follows
        !          2694:  * to get current pi elements:
        !          2695:  * \code
        !          2696:  * void show_all_pi (axlDoc * doc) 
        !          2697:  * {
        !          2698:  *      int       iterator;
        !          2699:  *      axlPI   * pi;
        !          2700:  *      axlList * PIs;
        !          2701:  *
        !          2702:  *      // get all PI target that the document has
        !          2703:  *      PIs      = axl_doc_get_pi_target_list (doc);
        !          2704:  *      iterator = 0;
        !          2705:  *
        !          2706:  *      while (iterator < axl_list_length (PIs)) {
        !          2707:  *            // get next pi stored 
        !          2708:  *            pi = axl_list_get_nth (PIs, iterator);
        !          2709:  *
        !          2710:  *            // do some stuff 
        !          2711:  *            printf ("PI found target name=%s, content=%s\n",
        !          2712:  *                    axl_pi_get_name (pi),
        !          2713:  *                    axl_pi_get_content (pi));
        !          2714:  *            
        !          2715:  *            // update the iterator
        !          2716:  *            iterator++;
        !          2717:  *      }
        !          2718:  *      return;
        !          2719:  * }
        !          2720:  * \endcode
        !          2721:  * 
        !          2722:  * @param doc The xml document (\ref axlDoc) where the process
        !          2723:  * instruction will be returned.
        !          2724:  * 
        !          2725:  * @return A reference to the list of processing instruction that the
        !          2726:  * xml document (\ref axlDoc) has.
        !          2727:  */
        !          2728: axlList * axl_doc_get_pi_target_list       (axlDoc * doc)
        !          2729: {
        !          2730:        axl_return_val_if_fail (doc,       NULL);
        !          2731: 
        !          2732:        return doc->piTargets;
        !          2733: }
        !          2734: 
        !          2735: /** 
        !          2736:  *
        !          2737:  * @brief Allows to create a new \ref axlPI element. 
        !          2738:  * 
        !          2739:  * @param name The PI target name.
        !          2740:  * @param content The PI content.
        !          2741:  * 
        !          2742:  * @return A newly allocated \ref axlPI element.
        !          2743:  */
        !          2744: axlPI * axl_pi_create (char * name, char * content)
        !          2745: {
        !          2746:        axlPI * pi;
        !          2747: 
        !          2748:        /* create the PI */
        !          2749:        pi          = axl_new (axlPI, 1);
        !          2750:        pi->name    = axl_strdup (name);
        !          2751:        
        !          2752:        /* copy the content if defined */
        !          2753:        if (content != NULL)
        !          2754:                pi->content = axl_strdup (content);
        !          2755: 
        !          2756:        return pi;
        !          2757: }
        !          2758: 
        !          2759: /** 
        !          2760:  * @brief Returns a newly allocated copy representing the same value
        !          2761:  * as the provided \ref axlPI reference.
        !          2762:  * 
        !          2763:  * @param pi The pi reference received.
        !          2764:  * 
        !          2765:  * @return A reference to the \ref axlPI element or null if it fails.
        !          2766:  */
        !          2767: axlPI   * axl_pi_copy                      (axlPI  * pi)
        !          2768: {
        !          2769:        axlPI * _pi;
        !          2770: 
        !          2771:        axl_return_val_if_fail (pi, NULL);
        !          2772: 
        !          2773:        /* create the PI */
        !          2774:        _pi          = axl_new (axlPI, 1);
        !          2775:        _pi->name    = axl_strdup (pi->name);
        !          2776:        
        !          2777:        /* copy the content if defined */
        !          2778:        if (pi->content != NULL)
        !          2779:                _pi->content = axl_strdup (pi->content);
        !          2780: 
        !          2781:        return _pi;
        !          2782: }
        !          2783: 
        !          2784: /** 
        !          2785:  * @brief Allows to check if both provided process instructions are
        !          2786:  * equal.
        !          2787:  * 
        !          2788:  * @param pi First process instruction to check.
        !          2789:  * @param pi2 Second process instructions to check.
        !          2790:  * 
        !          2791:  * @return \ref axl_true if both process instructions are equal. If some
        !          2792:  * of parameters received are NULL, the function will always return
        !          2793:  * \ref axl_false.
        !          2794:  */
        !          2795: axl_bool      axl_pi_are_equal                 (axlPI * pi, 
        !          2796:                                                axlPI * pi2)
        !          2797: {
        !          2798:        /* basic null reference check */
        !          2799:        axl_return_val_if_fail (pi, axl_false);
        !          2800:        axl_return_val_if_fail (pi2, axl_false);
        !          2801: 
        !          2802:        /* check internal data */
        !          2803:        if (! axl_cmp (pi->name, pi2->name))
        !          2804:                return axl_false;
        !          2805: 
        !          2806:        /* final check, both content must be equal */
        !          2807:        return axl_cmp (pi->content, pi2->content);
        !          2808: }
        !          2809: 
        !          2810: /** 
        !          2811:  * @brief Allows to get current pi name from the given \ref axlPI
        !          2812:  * reference.
        !          2813:  *
        !          2814:  * @param pi The PI reference where the name will returned.
        !          2815:  * 
        !          2816:  * @return A string representing the PI name. Returned value shouldn't
        !          2817:  * be deallocated.
        !          2818:  */
        !          2819: char    * axl_pi_get_name                  (axlPI  * pi)
        !          2820: {
        !          2821:        axl_return_val_if_fail (pi, NULL);
        !          2822: 
        !          2823:        /* return current PI name */
        !          2824:        return pi->name;
        !          2825: }
        !          2826: 
        !          2827: /** 
        !          2828:  * @brief Allows to get current optinal PI content.
        !          2829:  * 
        !          2830:  * @param pi The PI where the content will be returned.
        !          2831:  * 
        !          2832:  * @return A string representing the PI content. This value could be
        !          2833:  * NULL because it is optional to be defined. Returned value must not
        !          2834:  * be deallocated.
        !          2835:  */
        !          2836: char    * axl_pi_get_content               (axlPI  * pi)
        !          2837: {
        !          2838:        axl_return_val_if_fail (pi, NULL);
        !          2839:        
        !          2840:        /* return current PI content */
        !          2841:        return pi->content;
        !          2842: }
        !          2843: 
        !          2844: /** 
        !          2845:  * @brief Deallocates memory used by the \ref axlPI target.
        !          2846:  * 
        !          2847:  * @param pi The target to destroy.
        !          2848:  */
        !          2849: void axl_pi_free (axlPI * pi)
        !          2850: {
        !          2851:        if (pi == NULL)
        !          2852:                return;
        !          2853: 
        !          2854:        /* free PI target */
        !          2855:        axl_free (pi->name);
        !          2856:        axl_free (pi->content);
        !          2857:        axl_free (pi);
        !          2858:        return;
        !          2859: }
        !          2860: 
        !          2861: /** 
        !          2862:  * @internal Allows to get the number of bytes that the process
        !          2863:  * instruction will take.
        !          2864:  * 
        !          2865:  * @param pi The process instruction.
        !          2866:  * 
        !          2867:  * @return A size or -1 if it fails.
        !          2868:  */
        !          2869: int       axl_pi_get_size                  (axlPI  * pi)
        !          2870: {
        !          2871:        axl_return_val_if_fail (pi, -1);
        !          2872: 
        !          2873:        /* <?name content?> */
        !          2874:        return strlen (pi->name) + strlen (pi->content) + 5;
        !          2875: }
        !          2876: 
        !          2877: /** 
        !          2878:  * @internal
        !          2879:  *
        !          2880:  * Common implementation for \ref axl_doc_iterate and \ref axl_doc_iterate2.
        !          2881:  */
        !          2882: axl_bool __axl_doc_iterate_common (axlDoc            * doc, 
        !          2883:                                   axlNode           * root,
        !          2884:                                   AxlIterationMode    mode, 
        !          2885:                                   axlIterationFunc    func, 
        !          2886:                                   axlIterationFunc2   func2, 
        !          2887:                                   axlPointer          ptr, 
        !          2888:                                   axlPointer          ptr2)
        !          2889: {
        !          2890:        int        iterator;
        !          2891:        axl_bool   was_removed = axl_false;
        !          2892: 
        !          2893:        axlNode  * node;
        !          2894:        axlNode  * nodeAux;
        !          2895: 
        !          2896:        axlList  * pending;
        !          2897: 
        !          2898:        /* check first node */
        !          2899:        axl_return_val_if_fail (root, axl_false);
        !          2900: 
        !          2901:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "notifying first node inside the iteration");
        !          2902: 
        !          2903:        /* notify first node found we pass in a null value because it
        !          2904:           doesn't have a * parent. */
        !          2905:        if (func && ! func (root, NULL, doc, &was_removed, ptr))
        !          2906:                return axl_false;
        !          2907:        if (func2 && ! func2 (root, NULL, doc, &was_removed, ptr, ptr2)) 
        !          2908:                return axl_false;
        !          2909: 
        !          2910:        /* if the root node was removed, don't continue */
        !          2911:        if (was_removed)
        !          2912:                return axl_false;
        !          2913: 
        !          2914:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "continuing with next nodes");
        !          2915:        
        !          2916:        /* get childs */
        !          2917:        pending  = axl_node_get_childs (root);
        !          2918: 
        !          2919:        /* for each pending node */
        !          2920:        while (axl_list_length (pending) > 0) {
        !          2921: 
        !          2922:                /* get the first node inside the pending list */
        !          2923:                node = axl_list_get_first (pending);
        !          2924: 
        !          2925:                /* remove the node node from the pending list and add
        !          2926:                 * all childs */
        !          2927:                axl_list_remove_first (pending);
        !          2928: 
        !          2929:                /* notify node found */
        !          2930:                was_removed = axl_false;
        !          2931:                if (func && ! func (node, axl_node_get_parent (node), doc, &was_removed, ptr)) {
        !          2932:                        axl_list_free (pending);
        !          2933:                        return axl_false;
        !          2934:                }
        !          2935: 
        !          2936:                /* notify node found */
        !          2937:                if (func2 && ! func2 (node, axl_node_get_parent (node), doc, &was_removed, ptr, ptr2)) {
        !          2938:                        axl_list_free (pending);
        !          2939:                        return axl_false;
        !          2940:                }
        !          2941: 
        !          2942:                /* add all its childs */
        !          2943:                if (!was_removed && axl_node_have_childs (node)) {
        !          2944:                        
        !          2945:                        /* get first child */
        !          2946:                        nodeAux = axl_node_get_first_child (node);
        !          2947: 
        !          2948:                        /* get all items of the next level and add
        !          2949:                         * them properly */
        !          2950:                        iterator = 0;
        !          2951:                        while (nodeAux != NULL) {
        !          2952: 
        !          2953:                                /* add to the pending list */
        !          2954:                                switch (mode) {
        !          2955:                                case DEEP_ITERATION:
        !          2956:                                        /* add the element */
        !          2957:                                        axl_list_add_at (pending, nodeAux, iterator);
        !          2958:                                        
        !          2959:                                        /* update the iterator */
        !          2960:                                        iterator++;
        !          2961:                                        break;
        !          2962: 
        !          2963:                                case WIDE_ITERATION:
        !          2964:                                        /* add to the pending list */
        !          2965:                                        axl_list_add (pending, nodeAux);
        !          2966:                                        break;
        !          2967:                                } /* end switch */
        !          2968:        
        !          2969: 
        !          2970:                                /* update to the next */
        !          2971:                                nodeAux = axl_node_get_next (nodeAux);
        !          2972:                                
        !          2973:                        } /* end while */
        !          2974:                } /* end if */
        !          2975: 
        !          2976:                
        !          2977:        } /* end while */
        !          2978: 
        !          2979:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "terminated iteration process, deallocating list: %d",
        !          2980:                   axl_list_length (pending));
        !          2981:        
        !          2982:        axl_list_free (pending);
        !          2983:        
        !          2984:        /* iteration performed completely */
        !          2985:        return axl_true;
        !          2986: }
        !          2987: 
        !          2988: /** 
        !          2989:  * @brief Allows to perform an iteration over the documented provided,
        !          2990:  * visiting all nodes inside it.
        !          2991:  *
        !          2992:  * The function allows to configure the iteration module using \ref
        !          2993:  * AxlIterationMode (mode variable) and providing a callback function
        !          2994:  * that will be called for each node found (\ref axlIterationFunc).
        !          2995:  *
        !          2996:  * The function, optionall, allows to provide a user pointer that will
        !          2997:  * be passed to the callback function. See documentation for the
        !          2998:  * callback and the iteration module for more details.
        !          2999:  *
        !          3000:  * Here is an example:
        !          3001:  * \code
        !          3002:  * void perform_iteration (axlDoc * doc)
        !          3003:  * {
        !          3004:  *     // call to iterate
        !          3005:  *     axl_doc_iterate (doc, 
        !          3006:  *                      // visit childs before brothers
        !          3007:  *                      DEEP_ITERATION, 
        !          3008:  *                      // the func to execute: see below
        !          3009:  *                      show_node_found, 
        !          3010:  *                      // optional user pointer
        !          3011:  *                      NULL);
        !          3012:  * }
        !          3013:  *
        !          3014:  * axl_bool show_node_found (axlNode * node, axlNode * parent,
        !          3015:  *                       axlDoc  * doc, axl_bool * was_removed, 
        !          3016:  *                       axlPointer ptr)
        !          3017:  * {
        !          3018:  *      // Show node found 
        !          3019:  *      printf ("Node found: %s\n", axl_node_get_name (node));
        !          3020:  *
        !          3021:  *      // If the node is removed inside the iteration
        !          3022:  *      // using axl_node_remove or axl_node_replace, you
        !          3023:  *      // must notify the iteration system using was_removed
        !          3024:  *      // as follow: (* was_removed) = axl_true;
        !          3025:  *      //
        !          3026:  *      // If you don't remove anything, you don't need to do
        !          3027:  *      // anything especial with was_removed.
        !          3028:  *
        !          3029:  *      // don't stop iteration
        !          3030:  *      return axl_true;
        !          3031:  * }
        !          3032:  * \endcode
        !          3033:  *
        !          3034:  * See also alternative APIs:
        !          3035:  * 
        !          3036:  *   - \ref axl_doc_iterate_full
        !          3037:  *   - \ref axl_doc_iterate_full_from
        !          3038:  * 
        !          3039:  * @param doc The xml document that will be iterated.
        !          3040:  *
        !          3041:  * @param mode The iterarion type to be performed.
        !          3042:  *
        !          3043:  * @param func The function to be called for each node found.
        !          3044:  *
        !          3045:  * @param ptr An user defined pointer that will be passed to the
        !          3046:  * callback function.
        !          3047:  *
        !          3048:  * @return The function returns \ref axl_true if the iteration was
        !          3049:  * performed over all nodes or \ref axl_false it it was stoped by the
        !          3050:  * iteration function (by returning \ref axl_false to stop the
        !          3051:  * iteration). The function also axl_false if the parameters provided doc
        !          3052:  * or func are not defined.
        !          3053:  */
        !          3054: axl_bool      axl_doc_iterate                  (axlDoc           * doc,
        !          3055:                                                AxlIterationMode   mode,
        !          3056:                                                axlIterationFunc   func,
        !          3057:                                                axlPointer         ptr)
        !          3058: {
        !          3059:        axlNode * root;
        !          3060: 
        !          3061:        /* check basic data */
        !          3062:        axl_return_val_if_fail (doc, axl_false);
        !          3063:        axl_return_val_if_fail (func, axl_false);
        !          3064: 
        !          3065:        /* get the root node where the iteration will start */
        !          3066:        root = axl_doc_get_root (doc);
        !          3067: 
        !          3068:        /* call to common implementation */
        !          3069:        return __axl_doc_iterate_common (doc, root, mode, func, NULL, ptr, NULL);
        !          3070: 
        !          3071: }
        !          3072: 
        !          3073: 
        !          3074: /** 
        !          3075:  * @brief Allows to perform an iteration over the documented provided,
        !          3076:  * visiting all nodes inside it (with two user defined pointers support).
        !          3077:  *
        !          3078:  * The function allows to configure the iteration module using \ref
        !          3079:  * AxlIterationMode (mode variable) and providing a callback function
        !          3080:  * that will be called for each node found (\ref axlIterationFunc).
        !          3081:  *
        !          3082:  * The function, optionall, allows to provide two user pointer that will
        !          3083:  * be passed to the callback function. See documentation for the
        !          3084:  * callback and the iteration module for more details. See also \ref axl_doc_iterate.
        !          3085:  *
        !          3086:  * 
        !          3087:  * @param doc The xml document that will be iterated.
        !          3088:  *
        !          3089:  * @param mode The iterarion type to be performed.
        !          3090:  *
        !          3091:  * @param func The function to be called for each node found.
        !          3092:  *
        !          3093:  * @param ptr An user defined pointer that will be passed to the
        !          3094:  * callback function.
        !          3095:  *
        !          3096:  * @param ptr2 Second user defined pointer that will be passed to the
        !          3097:  * callback function.
        !          3098:  * 
        !          3099:  *
        !          3100:  * @return The function returns \ref axl_true if the iteration was
        !          3101:  * performed over all nodes or \ref axl_false it it was stoped by the
        !          3102:  * iteration function (by returning \ref axl_false to stop the
        !          3103:  * iteration). The function also axl_false if the parameters provided doc
        !          3104:  * or func are not defined.
        !          3105:  */
        !          3106: axl_bool      axl_doc_iterate_full             (axlDoc            * doc,
        !          3107:                                                AxlIterationMode    mode,
        !          3108:                                                axlIterationFunc2   func,
        !          3109:                                                axlPointer          ptr,
        !          3110:                                                axlPointer          ptr2)
        !          3111: 
        !          3112: {
        !          3113:        axlNode * root;
        !          3114: 
        !          3115:        /* check basic data */
        !          3116:        axl_return_val_if_fail (doc, axl_false);
        !          3117:        axl_return_val_if_fail (func, axl_false);
        !          3118: 
        !          3119:        /* get the root node where the iteration will start */
        !          3120:        root = axl_doc_get_root (doc);
        !          3121:        
        !          3122:        /* call to common implementation */
        !          3123:        return __axl_doc_iterate_common (doc, root, mode, NULL, func, ptr, ptr2);
        !          3124: }
        !          3125: 
        !          3126: /** 
        !          3127:  * @brief Allows to perform a iteration operation but configuring
        !          3128:  * where to start, discarding the rest content.
        !          3129:  *
        !          3130:  * See \ref axl_doc_iterate and \ref axl_doc_iterate_full for more
        !          3131:  * details. This function works the same like previous but, unlike
        !          3132:  * previous, this function doesn't use the default starting point: the
        !          3133:  * root node (\ref axl_doc_get_root). The function allows to configure
        !          3134:  * the node where to start the iteration operation. 
        !          3135:  *
        !          3136:  * This function is equivalent to \ref axl_doc_iterate_full calling if
        !          3137:  * it use the root node document as value for <b>starting_from</b>.
        !          3138:  * 
        !          3139:  * @param doc The xml document that will be iterated.
        !          3140:  *
        !          3141:  * @param starting_from The \ref axlNode where the operation will
        !          3142:  * start, discarding all content from ascending nodes, previous
        !          3143:  * siblings and following sibligins. From a iteration perspective, the
        !          3144:  * iteration opeeration.
        !          3145:  *
        !          3146:  * @param mode The iterarion type to be performed.
        !          3147:  *
        !          3148:  * @param func The function to be called for each node found.
        !          3149:  *
        !          3150:  * @param ptr An user defined pointer that will be passed to the
        !          3151:  * callback function.
        !          3152:  *
        !          3153:  * @param ptr2 Second user defined pointer that will be passed to the
        !          3154:  * callback function.
        !          3155:  * 
        !          3156:  *
        !          3157:  * @return The function returns \ref axl_true if the iteration was
        !          3158:  * performed over all nodes or \ref axl_false it it was stoped by the
        !          3159:  * iteration function (by returning \ref axl_false to stop the
        !          3160:  * iteration). The function also axl_false if the parameters provided doc
        !          3161:  * or func are not defined.
        !          3162:  */
        !          3163: axl_bool      axl_doc_iterate_full_from        (axlDoc           * doc,
        !          3164:                                                axlNode          * starting_from,
        !          3165:                                                AxlIterationMode   mode,
        !          3166:                                                axlIterationFunc2  func,
        !          3167:                                                axlPointer         ptr,
        !          3168:                                                axlPointer         ptr2)
        !          3169: {
        !          3170:        /* check basic data */
        !          3171:        axl_return_val_if_fail (doc, axl_false);
        !          3172:        axl_return_val_if_fail (func, axl_false);
        !          3173: 
        !          3174:        /* call to common implementation */
        !          3175:        return __axl_doc_iterate_common (doc, starting_from, mode, NULL, func, ptr, ptr2);
        !          3176: }
        !          3177: 
        !          3178: 
        !          3179: /** 
        !          3180:  * @brief Releases memory allocated by the \ref axlDoc object.
        !          3181:  * 
        !          3182:  * @param doc The \ref axlDoc object to unref.
        !          3183:  */
        !          3184: void     axl_doc_free         (axlDoc * doc)
        !          3185: {
        !          3186:        /* do not complain if an axlDoc reference is received */
        !          3187:        if (doc == NULL)
        !          3188:                return;
        !          3189: 
        !          3190:        /* free first root node */
        !          3191:        if (doc->rootNode != NULL)
        !          3192:                axl_node_free (doc->rootNode);
        !          3193: 
        !          3194:        /* free node hierarchy */
        !          3195:        if (doc->parentNode != NULL)
        !          3196:                axl_stack_free (doc->parentNode);
        !          3197: 
        !          3198:        /* free xml:space hierarchy */
        !          3199:        if (doc->xmlPreserve != NULL)
        !          3200:                axl_binary_stack_free (doc->xmlPreserve);
        !          3201: 
        !          3202:        /* free item factory */
        !          3203:        if (doc->item_factory != NULL)
        !          3204:                axl_factory_free (doc->item_factory);
        !          3205: 
        !          3206:        /* free content holding nodes factory */
        !          3207:        if (doc->content_factory != NULL)
        !          3208:                axl_factory_free (doc->content_factory);
        !          3209: 
        !          3210:        /* free attribute holding factory */
        !          3211:        if (doc->attr_factory != NULL)
        !          3212:                axl_factory_free (doc->attr_factory);
        !          3213: 
        !          3214:        /* free node factory */
        !          3215:        if (doc->node_factory != NULL)
        !          3216:                axl_factory_free (doc->node_factory);
        !          3217: 
        !          3218:        if (doc->str_factory != NULL)
        !          3219:                axl_string_factory_free (doc->str_factory);
        !          3220: 
        !          3221:        /* free pi targets read */
        !          3222:        if (doc->piTargets != NULL)
        !          3223:                axl_list_free (doc->piTargets);
        !          3224: 
        !          3225:        /* free enconding allocated */
        !          3226:        axl_free (doc->encoding);
        !          3227:        axl_free (doc->encoding_found);
        !          3228:        
        !          3229:        /* free allocated version value */
        !          3230:        axl_free (doc->version);
        !          3231: 
        !          3232:        /* free document allocated */
        !          3233:        axl_free (doc);
        !          3234: 
        !          3235:        return;
        !          3236: }
        !          3237: 
        !          3238: /** 
        !          3239:  * @internal
        !          3240:  *
        !          3241:  * @brief Allows to consume comments found while reading xml files.
        !          3242:  * 
        !          3243:  * @param stream The axlStream where the comment is spected to be read.
        !          3244:  *
        !          3245:  * @param error An optional axlError where problem will be reported.
        !          3246:  */
        !          3247: axl_bool      axl_doc_consume_comments         (axlDoc * doc, axlStream * stream, axlError ** error)
        !          3248: {
        !          3249: 
        !          3250:        axl_bool     found_item;
        !          3251:        char       * content;
        !          3252:        int          size;
        !          3253: 
        !          3254:        /* get current parent node */
        !          3255:        axlNode * parent = (doc != NULL) ? axl_stack_peek (doc->parentNode) : NULL;
        !          3256: 
        !          3257:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "checking for comemnts");
        !          3258: 
        !          3259:        /* know, try to read comments a process instructions.  Do this
        !          3260:         * until both fails. Do this until one of them find
        !          3261:         * something. */
        !          3262:        do {
        !          3263:                /* flag the loop to end, and only end if both,
        !          3264:                 * comments matching and PI matching fails. */
        !          3265:                found_item = axl_false;
        !          3266:                
        !          3267:                /* get rid from spaces */
        !          3268:                AXL_CONSUME_SPACES(stream);
        !          3269: 
        !          3270:                /* check for comments */
        !          3271:                if (axl_stream_inspect (stream, "<!--", 4) > 0) {
        !          3272: 
        !          3273:                        /* get comment content */
        !          3274:                        content = axl_stream_get_until_ref (stream, NULL, NULL, axl_true, &size, 1, "-->");
        !          3275:                        if (content == NULL) {
        !          3276:                                axl_error_new (-1, "detected an opened comment but not found the comment ending",
        !          3277:                                               stream, error);
        !          3278:                                axl_stream_free (stream);
        !          3279:                                return axl_false;
        !          3280:                        } 
        !          3281: 
        !          3282:                        /* store it */
        !          3283:                        if (parent != NULL)
        !          3284:                                axl_node_set_comment (parent, content, size);
        !          3285:                        
        !          3286:                        /* flag that we have found a comment */
        !          3287:                        found_item = axl_true;
        !          3288:                }
        !          3289:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "now see for process instructions");
        !          3290:        
        !          3291:                /* get rid from spaces */
        !          3292:                AXL_CONSUME_SPACES(stream);
        !          3293: 
        !          3294:                /* check for PI, only once the xml header have been processed */
        !          3295:                if ((doc != NULL) && doc->headerProcess && (axl_stream_peek (stream, "<?", 2) > 0)) {
        !          3296:                        
        !          3297:                        if (! axl_doc_consume_pi (doc, axl_stack_peek (doc->parentNode), stream, error))
        !          3298:                                return axl_false;
        !          3299:                        found_item = axl_true;
        !          3300:                }
        !          3301:                
        !          3302:                /* do not consume spaces if an item was found because
        !          3303:                 * it is done again at the begin of the loop */
        !          3304:                if (! found_item) {
        !          3305:                        /* get rid from spaces */
        !          3306:                        AXL_CONSUME_SPACES(stream);
        !          3307:                }
        !          3308:                
        !          3309:                /* check to break-the-loop */
        !          3310:        }while (found_item);
        !          3311: 
        !          3312:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "comments and pi parsed");
        !          3313: 
        !          3314:        /* axl_true value */
        !          3315:        return axl_true;
        !          3316: }
        !          3317: 
        !          3318: /** 
        !          3319:  * @internal
        !          3320:  *
        !          3321:  * @brie Consumes Processing intructions that are directed to the
        !          3322:  * application ans configuration or processing instructions.
        !          3323:  * 
        !          3324:  * @param doc The document there the information will be placed.
        !          3325:  * 
        !          3326:  * @param stream The stream where the data is being read.
        !          3327:  *
        !          3328:  * @param error An optional axlError where the information will be
        !          3329:  * reported.
        !          3330:  * 
        !          3331:  * @return axl_true if not error was found, otherwise AXL_FASLSE is
        !          3332:  * returned.
        !          3333:  */
        !          3334: axl_bool      axl_doc_consume_pi (axlDoc * doc, axlNode * node, 
        !          3335:                                  axlStream * stream, axlError ** error)
        !          3336: {
        !          3337:        char  * string_aux;
        !          3338:        char  * string_aux2;
        !          3339:        int     matched_chunk;
        !          3340:        
        !          3341:        
        !          3342:        /* check if a PI target was found */
        !          3343: 
        !          3344:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "calling to consume PI..");
        !          3345: 
        !          3346: 
        !          3347:        if (axl_stream_peek (stream, "<?", 2) > 0) {
        !          3348: 
        !          3349:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a process instruction initialization");
        !          3350: 
        !          3351:                /* found a pi target initialization */
        !          3352:                axl_stream_accept (stream);
        !          3353:                
        !          3354:                string_aux = axl_stream_get_until (stream, NULL, &matched_chunk, axl_true, 3, 
        !          3355:                                                   " ?>", "?>", " ");
        !          3356:                /* check error reported */
        !          3357:                if (string_aux == NULL) {
        !          3358:                        axl_error_new (-1, "Found a error while reading the PI target name", stream, error);
        !          3359:                        axl_stream_free (stream);
        !          3360:                        return axl_false;
        !          3361:                }
        !          3362: 
        !          3363:                /* check that the reserved xml word is not used for the PI target */
        !          3364:                string_aux2 = axl_strdup (string_aux);
        !          3365:                if (axl_cmp (axl_stream_to_lower (string_aux2), "xml")) {
        !          3366:                        axl_free (string_aux2);
        !          3367:                        axl_error_new (-1, "Using a reserved PI target name (xml), not allowed", stream, error);
        !          3368:                        axl_stream_free (stream);
        !          3369:                        return axl_false;
        !          3370:                }
        !          3371:                axl_free (string_aux2);
        !          3372: 
        !          3373: 
        !          3374:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found PI target name: %s (terminator matched: %d)", 
        !          3375:                           string_aux, matched_chunk);
        !          3376: 
        !          3377:                /* check which was the matched string */
        !          3378:                if (matched_chunk == 0 || matched_chunk == 1) {
        !          3379:                        /* seems that the PI target doesn't have more data associated, craete and return */
        !          3380:                        if (node != NULL) {
        !          3381:                                axl_node_add_pi_target (node, string_aux, NULL);
        !          3382:                                return axl_true;
        !          3383:                        }
        !          3384:                        
        !          3385:                        if (doc != NULL)
        !          3386:                                axl_doc_add_pi_target (doc, string_aux, NULL);
        !          3387:                        return axl_true;
        !          3388:                }
        !          3389: 
        !          3390:                /* seems that we have additional content to be read */
        !          3391:                if (matched_chunk == 2) {
        !          3392:                        /* make a local copy for the PI target name
        !          3393:                         * read previously */
        !          3394:                        string_aux  = axl_strdup (string_aux);
        !          3395:                        
        !          3396:                        /* get the PI content */
        !          3397:                        string_aux2 = axl_stream_get_until (stream, NULL, NULL, axl_true, 2, " ?>", "?>");
        !          3398: 
        !          3399:                        /* check error reported */
        !          3400:                        if (string_aux2 == NULL) {
        !          3401:                                axl_free (string_aux);
        !          3402:                                axl_error_new (-1, "Found a error while reading the PI content", stream, error);
        !          3403:                                axl_stream_free (stream);
        !          3404:                                return axl_false;
        !          3405:                        }
        !          3406: 
        !          3407:                        /* check the destination for the pi */                  
        !          3408:                        if (node != NULL) {
        !          3409:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "PI processing finished, adding PI (node) and its content");
        !          3410: 
        !          3411:                                axl_node_add_pi_target (node, string_aux, string_aux2);
        !          3412:                                axl_free (string_aux);
        !          3413:                                return axl_true;
        !          3414:                        }
        !          3415: 
        !          3416: 
        !          3417:                        if (doc != NULL) {
        !          3418:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "PI processing finished, adding PI (doc) and its content");
        !          3419:                                axl_doc_add_pi_target (doc, string_aux, string_aux2);
        !          3420:                                axl_free (string_aux);
        !          3421:                                return axl_true;
        !          3422:                        }
        !          3423: 
        !          3424:                }
        !          3425: 
        !          3426:                /* check error reported */
        !          3427:                axl_error_new (-1, "Found a error while reading the PI target name, unable to find PI terminator ?>", stream, error);
        !          3428:                axl_stream_free (stream);
        !          3429:                return axl_false;
        !          3430:        }
        !          3431: 
        !          3432:        
        !          3433:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "PI processing finished");
        !          3434: 
        !          3435: 
        !          3436:        return axl_true;
        !          3437: }
        !          3438: 
        !          3439: /** 
        !          3440:  * @internal Function that allows to get axlFactory associated to
        !          3441:  * the provided document.
        !          3442:  * 
        !          3443:  * @param doc The axl document that is requested to return its item
        !          3444:  * factory.
        !          3445:  * 
        !          3446:  * @return An internal reference to the item factory. Do not dealloc.
        !          3447:  */
        !          3448: axlFactory * axl_doc_get_item_factory  (axlDoc * doc)
        !          3449: {
        !          3450:        return doc->item_factory;
        !          3451: }
        !          3452: 
        !          3453: /** 
        !          3454:  * @brief Allows to configure a handler that implements document
        !          3455:  * detection and in such cases reconfigure \ref axlStream to act an a
        !          3456:  * proper manner.
        !          3457:  * 
        !          3458:  * @param func The function to be configured.
        !          3459:  *
        !          3460:  * @param user_data User defined data to be provide to the function.
        !          3461:  *
        !          3462:  * @return A reference to the previously configured function.
        !          3463:  */
        !          3464: axlDocDetectCodification axl_doc_set_detect_codification_func (axlDocDetectCodification func, 
        !          3465:                                                               axlPointer user_data)
        !          3466: {
        !          3467:        axlDocDetectCodification previous;
        !          3468:        
        !          3469:        /* configure handler and user defined pointer */
        !          3470:        previous                 = detect_codification_func;
        !          3471:        detect_codification_func = func;
        !          3472:        detect_codification_data = user_data;
        !          3473: 
        !          3474:        return previous;
        !          3475: }
        !          3476: 
        !          3477: /** 
        !          3478:  * @brief Allows to configure the handler used to finally configure
        !          3479:  * codification to be used for a particular \ref axlStream.
        !          3480:  * 
        !          3481:  * @param func The function to be called to configure codification.
        !          3482:  *
        !          3483:  * @param user_data A reference to user defined data to be passed to
        !          3484:  * the function.
        !          3485:  * 
        !          3486:  * @return A refernece to the previous handler configured.
        !          3487:  */
        !          3488: axlDocConfigureCodification axl_doc_set_configure_codification_func (axlDocConfigureCodification func, 
        !          3489:                                                                     axlPointer user_data)
        !          3490: {
        !          3491:        axlDocConfigureCodification previous;
        !          3492:        
        !          3493:        /* configure handler and user defined pointer */
        !          3494:        previous                    = configure_codification_func;
        !          3495:        configure_codification_func = func;
        !          3496:        configure_codification_data = user_data;
        !          3497: 
        !          3498:        return previous;
        !          3499: }
        !          3500: 
        !          3501: /* @} */

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