xml/libxml2libs/src/libxml2/libxml2_xmlreader.c
changeset 0 e35f40988205
equal deleted inserted replaced
-1:000000000000 0:e35f40988205
       
     1 /*
       
     2  * libxml2_xmlreader.c: implements the xmlTextReader streaming node API
       
     3  *
       
     4  * NOTE:
       
     5  *   XmlTextReader.Normalization Property won't be supported, since
       
     6  *     it makes the parser non compliant to the XML recommendation
       
     7  *
       
     8  * See Copyright for the status of this software.
       
     9  *
       
    10  * daniel@veillard.com
       
    11  * Portion Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. 
       
    12  */
       
    13 
       
    14 /*
       
    15  * TODOs:
       
    16  *   - XML Schemas validation
       
    17  *   - setting(s) for NoBlanks
       
    18  *   - performances and tuning ...
       
    19  */
       
    20 #define IN_LIBXML
       
    21 
       
    22 #include "xmlenglibxml.h"
       
    23 
       
    24 #ifdef LIBXML_READER_ENABLED
       
    25 
       
    26 #include <string.h> /* for memset() only ! */
       
    27 #include <stdarg.h>
       
    28 
       
    29 #ifdef HAVE_CTYPE_H
       
    30 #include <ctype.h>
       
    31 #endif
       
    32 
       
    33 #ifdef HAVE_STDLIB_H
       
    34 #include <stdlib.h>
       
    35 #endif
       
    36 
       
    37 #include <stdapis/libxml2/libxml2_globals.h>
       
    38 #include "libxml2_xmlreader.h"
       
    39 #include <stdapis/libxml2/libxml2_parserinternals.h>
       
    40 #include <stdapis/libxml2/libxml2_uri.h>
       
    41 
       
    42 /* #define DEBUG_CALLBACKS */
       
    43 /* #define DEBUG_READER */
       
    44 
       
    45 /**
       
    46  * 
       
    47  *
       
    48  * macro to flag unimplemented blocks
       
    49  */
       
    50 #define TODO                                                            \
       
    51      xmlGenericError(xmlGenericErrorContext,                             \
       
    52              EMBED_ERRTXT("Unimplemented block at %s:%d\n"),                             \
       
    53              __FILE__, __LINE__);
       
    54 
       
    55 #ifdef DEBUG_READER
       
    56 #define DUMP_READER xmlTextReaderDebug(reader);
       
    57 #else
       
    58 #define DUMP_READER
       
    59 #endif
       
    60 
       
    61 #define CHUNK_SIZE 512
       
    62 /************************************************************************
       
    63  *                                                                      *
       
    64  *  The parser: maps the Text Reader API on top of the existing         *
       
    65  *      parsing routines building a tree                                *
       
    66  *                                                                      *
       
    67  ************************************************************************/
       
    68 
       
    69 #define XML_TEXTREADER_INPUT    1
       
    70 #define XML_TEXTREADER_CTXT     2
       
    71 
       
    72 // struct _xmlTextReader was moved to header file
       
    73 
       
    74 #define NODE_IS_EMPTY       0x1
       
    75 #define NODE_IS_PRESERVED   0x2
       
    76 #define NODE_IS_SPRESERVED  0x4
       
    77 
       
    78 /**
       
    79  * CONSTSTR:
       
    80  *
       
    81  * Macro used to return an interned string
       
    82  */
       
    83 #define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1)
       
    84 #define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str))
       
    85 
       
    86 static int xmlTextReaderReadTree(xmlTextReaderPtr reader);
       
    87 static int xmlTextReaderNextTree(xmlTextReaderPtr reader);
       
    88 
       
    89 /************************************************************************
       
    90  *                                                                      *
       
    91  *  Our own version of the freeing routines as we recycle nodes         *
       
    92  *                                                                      *
       
    93  ************************************************************************/
       
    94 /**
       
    95  * DICT_FREE:
       
    96  * @param str a string
       
    97  *
       
    98  * Free a string if it is not owned by the "dict" dictionnary in the
       
    99  * current scope
       
   100  */
       
   101 #define DICT_FREE(str)                                      \
       
   102     if ((str) && ((!dict) ||                                \
       
   103         (xmlDictOwns(dict, (const xmlChar *)(str)) == 0)))  \
       
   104         xmlFree((char *)(str));
       
   105 
       
   106 static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);
       
   107 static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
       
   108 
       
   109 /**
       
   110  * xmlFreeID:
       
   111  * @param not A id
       
   112  *
       
   113  * Deallocate the memory used by an id definition
       
   114  */
       
   115 static void
       
   116 xmlFreeID(xmlIDPtr id) {
       
   117     xmlDictPtr dict = NULL;
       
   118 
       
   119     if (id == NULL) return;
       
   120 
       
   121     if (id->doc != NULL)
       
   122         dict = id->doc->dict;
       
   123 
       
   124     if (id->value != NULL)
       
   125         DICT_FREE(id->value)
       
   126     xmlFree(id);
       
   127 }
       
   128 
       
   129 /**
       
   130  * xmlTextReaderRemoveID:
       
   131  * @param doc the document
       
   132  * @param attr the attribute
       
   133  *
       
   134  * Remove the given attribute from the ID table maintained internally.
       
   135  *
       
   136  * Returns -1 if the lookup failed and 0 otherwise
       
   137  */
       
   138 static int
       
   139 xmlTextReaderRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
       
   140     xmlIDTablePtr table;
       
   141     xmlIDPtr id;
       
   142     xmlChar *ID;
       
   143 
       
   144     if (!doc || !attr)
       
   145         return(-1);
       
   146     table = (xmlIDTablePtr) doc->ids;
       
   147     if (table == NULL)
       
   148         return(-1);
       
   149 
       
   150     if (attr == NULL)
       
   151         return(-1);
       
   152     ID = xmlNodeListGetString(doc, attr->children, 1);
       
   153     if (ID == NULL)
       
   154         return(-1);
       
   155     id = xmlHashLookup(table, ID);
       
   156     xmlFree(ID);
       
   157     if (id == NULL || id->attr != attr) {
       
   158         return(-1);
       
   159     }
       
   160     id->name = attr->name;
       
   161     id->attr = NULL;
       
   162     return(0);
       
   163 }
       
   164 
       
   165 /**
       
   166  * xmlTextReaderFreeProp:
       
   167  * @param reader the xmlTextReaderPtr used
       
   168  * @param cur the node
       
   169  *
       
   170  * Free a node.
       
   171  */
       
   172 static void
       
   173 xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
       
   174     xmlDictPtr dict;
       
   175     LOAD_GS_SAFE_ATTR(cur)
       
   176 
       
   177     dict = reader->ctxt->dict;
       
   178     if (cur == NULL) return;
       
   179 
       
   180     if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
       
   181         xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
       
   182 
       
   183     /* Check for ID removal -> leading to invalid references ! */
       
   184     if ((cur->parent != NULL) && (cur->parent->doc != NULL) &&
       
   185         ((cur->parent->doc->intSubset != NULL) ||
       
   186          (cur->parent->doc->extSubset != NULL))) {
       
   187         if (xmlIsID(cur->parent->doc, cur->parent, cur))
       
   188             xmlTextReaderRemoveID(cur->parent->doc, cur);
       
   189     }
       
   190     if (cur->children != NULL)
       
   191         xmlTextReaderFreeNodeList(reader, cur->children);
       
   192 
       
   193     DICT_FREE(cur->name);
       
   194     if ((reader != NULL) && (reader->ctxt != NULL) &&
       
   195         (reader->ctxt->freeAttrsNr < 100))
       
   196     {
       
   197         cur->next = reader->ctxt->freeAttrs;
       
   198         reader->ctxt->freeAttrs = cur;
       
   199         reader->ctxt->freeAttrsNr++;
       
   200     } else {
       
   201         xmlFree(cur);
       
   202     }
       
   203 }
       
   204 
       
   205 /**
       
   206  * xmlTextReaderFreePropList:
       
   207  * @param reader the xmlTextReaderPtr used
       
   208  * @param cur the first property in the list
       
   209  *
       
   210  * Free a property and all its siblings, all the children are freed too.
       
   211  */
       
   212 static void
       
   213 xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
       
   214     xmlAttrPtr next;
       
   215     //if (cur == NULL) return;
       
   216     while (cur) {
       
   217         next = cur->next;
       
   218         xmlTextReaderFreeProp(reader, cur);
       
   219         cur = next;
       
   220     }
       
   221 }
       
   222 
       
   223 /**
       
   224  * xmlTextReaderFreeNodeList:
       
   225  * @param reader the xmlTextReaderPtr used
       
   226  * @param cur the first node in the list
       
   227  *
       
   228  * Free a node and all its siblings, this is a recursive behaviour, all
       
   229  * the children are freed too.
       
   230  */
       
   231 static void
       
   232 xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
       
   233     xmlNodePtr next;
       
   234     xmlDictPtr dict;
       
   235     LOAD_GS_SAFE_NODE(cur)
       
   236 
       
   237     dict = reader->ctxt->dict;
       
   238     if (cur == NULL)
       
   239         return;
       
   240     if (cur->type == XML_NAMESPACE_DECL) {
       
   241         xmlFreeNsList((xmlNsPtr) cur);
       
   242         return;
       
   243     }
       
   244     if ((cur->type == XML_DOCUMENT_NODE) ||
       
   245         (cur->type == XML_HTML_DOCUMENT_NODE))
       
   246     {
       
   247         xmlFreeDoc((xmlDocPtr) cur);
       
   248         return;
       
   249     }
       
   250     while (cur)
       
   251     {
       
   252         next = cur->next;
       
   253         /* unroll to speed up freeing the document */
       
   254         if (cur->type != XML_DTD_NODE)
       
   255         {
       
   256             if ((cur->children != NULL) &&
       
   257                (cur->type != XML_ENTITY_REF_NODE))
       
   258             {
       
   259                 if (cur->children->parent == cur)
       
   260                     xmlTextReaderFreeNodeList(reader, cur->children);
       
   261                 cur->children = NULL;
       
   262             }
       
   263 
       
   264             if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
       
   265                 xmlDeregisterNodeDefaultValue(cur);
       
   266 
       
   267             if (((cur->type == XML_ELEMENT_NODE) ||
       
   268                 (cur->type == XML_XINCLUDE_START) ||
       
   269                 (cur->type == XML_XINCLUDE_END)) &&
       
   270                 (cur->properties != NULL))
       
   271             {
       
   272                 xmlTextReaderFreePropList(reader, cur->properties);
       
   273             }
       
   274             if ((cur->type != XML_ELEMENT_NODE) &&
       
   275                 (cur->type != XML_XINCLUDE_START) &&
       
   276                 (cur->type != XML_XINCLUDE_END) &&
       
   277                 (cur->type != XML_ENTITY_REF_NODE))
       
   278             {
       
   279                 DICT_FREE(cur->content);
       
   280             }
       
   281             if (((cur->type == XML_ELEMENT_NODE)  ||
       
   282                 (cur->type == XML_XINCLUDE_START) ||
       
   283                 (cur->type == XML_XINCLUDE_END)) &&
       
   284                 (cur->nsDef != NULL))
       
   285             {
       
   286                 xmlFreeNsList(cur->nsDef);
       
   287             }
       
   288             /*
       
   289              * we don't free element names here they are interned now
       
   290              */
       
   291             if ((cur->type != XML_TEXT_NODE) &&
       
   292                 (cur->type != XML_COMMENT_NODE))
       
   293             {
       
   294                 DICT_FREE(cur->name);
       
   295             }
       
   296             if (((cur->type == XML_ELEMENT_NODE) ||
       
   297                 (cur->type == XML_TEXT_NODE)) &&
       
   298                 (reader != NULL) && (reader->ctxt != NULL) &&
       
   299                 (reader->ctxt->freeElemsNr < 100))
       
   300             {
       
   301                 cur->next = reader->ctxt->freeElems;
       
   302                 reader->ctxt->freeElems = cur;
       
   303                 reader->ctxt->freeElemsNr++;
       
   304             }
       
   305             else
       
   306             {
       
   307                 xmlFree(cur);
       
   308             }
       
   309         } // if (cur->type != XML_DTD_NODE)
       
   310         cur = next;
       
   311     } // while (cur)
       
   312 }
       
   313 
       
   314 /**
       
   315  * xmlTextReaderFreeNode:
       
   316  * @param reader the xmlTextReaderPtr used
       
   317  * @param cur the node
       
   318  *
       
   319  * Free a node, this is a recursive behaviour, all the children are freed too.
       
   320  * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
       
   321  */
       
   322 static void
       
   323 xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
       
   324     xmlDictPtr dict;
       
   325     LOAD_GS_SAFE_NODE(cur)
       
   326 
       
   327     dict = reader->ctxt->dict;
       
   328     if (cur->type == XML_DTD_NODE) {
       
   329         xmlFreeDtd((xmlDtdPtr) cur);
       
   330         return;
       
   331     }
       
   332     if (cur->type == XML_NAMESPACE_DECL) {
       
   333         xmlFreeNs((xmlNsPtr) cur);
       
   334         return;
       
   335     }
       
   336     if (cur->type == XML_ATTRIBUTE_NODE) {
       
   337         xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
       
   338         return;
       
   339     }
       
   340 
       
   341     if (cur->children && cur->type != XML_ENTITY_REF_NODE) {
       
   342         if (cur->children->parent == cur)
       
   343             xmlTextReaderFreeNodeList(reader, cur->children);
       
   344         cur->children = NULL;
       
   345     }
       
   346 
       
   347     if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
       
   348         xmlDeregisterNodeDefaultValue(cur);
       
   349 
       
   350     if (((cur->type == XML_ELEMENT_NODE) ||
       
   351         (cur->type == XML_XINCLUDE_START) ||
       
   352         (cur->type == XML_XINCLUDE_END)) &&
       
   353         (cur->properties != NULL))
       
   354     {
       
   355         xmlTextReaderFreePropList(reader, cur->properties);
       
   356     }
       
   357     if ((cur->content != (xmlChar *) &(cur->properties)) &&
       
   358         (cur->type != XML_ELEMENT_NODE)                  &&
       
   359         (cur->type != XML_XINCLUDE_START)                &&
       
   360         (cur->type != XML_XINCLUDE_END)                  &&
       
   361         (cur->type != XML_ENTITY_REF_NODE))
       
   362     {
       
   363         DICT_FREE(cur->content);
       
   364     }
       
   365     if (((cur->type == XML_ELEMENT_NODE)   ||
       
   366          (cur->type == XML_XINCLUDE_START) ||
       
   367          (cur->type == XML_XINCLUDE_END))
       
   368         &&
       
   369         (cur->nsDef != NULL))
       
   370     {
       
   371         xmlFreeNsList(cur->nsDef);
       
   372     }
       
   373     /*
       
   374      * we don't free names here they are interned now
       
   375      */
       
   376     if ((cur->type != XML_TEXT_NODE) &&
       
   377         (cur->type != XML_COMMENT_NODE))
       
   378     {
       
   379         DICT_FREE(cur->name);
       
   380     }
       
   381     if (((cur->type == XML_ELEMENT_NODE) ||
       
   382         (cur->type == XML_TEXT_NODE)) &&
       
   383         (reader != NULL) && (reader->ctxt != NULL) &&
       
   384         (reader->ctxt->freeElemsNr < 100))
       
   385     {
       
   386         cur->next = reader->ctxt->freeElems;
       
   387         reader->ctxt->freeElems = cur;
       
   388         reader->ctxt->freeElemsNr++;
       
   389     }
       
   390     else
       
   391     {
       
   392         xmlFree(cur);
       
   393     }
       
   394 }
       
   395 
       
   396 /**
       
   397  * xmlTextReaderFreeIDTable:
       
   398  * @param table An id table
       
   399  *
       
   400  * Deallocate the memory used by an ID hash table.
       
   401  */
       
   402 static void
       
   403 xmlTextReaderFreeIDTable(xmlIDTablePtr table) {
       
   404     xmlHashFree(table, (xmlHashDeallocator) xmlFreeID);
       
   405 }
       
   406 
       
   407 /**
       
   408  * xmlTextReaderFreeDoc:
       
   409  * @param reader the xmlTextReaderPtr used
       
   410  * @param cur pointer to the document
       
   411  *
       
   412  * Free up all the structures used by a document, tree included.
       
   413  */
       
   414 static void
       
   415 xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
       
   416     xmlDtdPtr extSubset, intSubset;
       
   417     LOAD_GS_SAFE_DOC(cur)
       
   418 
       
   419     if (cur == NULL) return;
       
   420 
       
   421     if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
       
   422         xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
       
   423 
       
   424     /*
       
   425      * Do this before freeing the children list to avoid ID lookups
       
   426      */
       
   427     if (cur->ids != NULL)
       
   428         xmlTextReaderFreeIDTable((xmlIDTablePtr) cur->ids);
       
   429     cur->ids = NULL;
       
   430     if (cur->refs != NULL)
       
   431         xmlFreeRefTable((xmlRefTablePtr) cur->refs);
       
   432     cur->refs = NULL;
       
   433     extSubset = cur->extSubset;
       
   434     intSubset = cur->intSubset;
       
   435     if (intSubset == extSubset)
       
   436         extSubset = NULL;
       
   437     if (extSubset != NULL) {
       
   438         xmlUnlinkNode((xmlNodePtr) cur->extSubset);
       
   439         cur->extSubset = NULL;
       
   440         xmlFreeDtd(extSubset);
       
   441     }
       
   442     if (intSubset != NULL) {
       
   443         xmlUnlinkNode((xmlNodePtr) cur->intSubset);
       
   444         cur->intSubset = NULL;
       
   445         xmlFreeDtd(intSubset);
       
   446     }
       
   447 
       
   448     if (cur->children != NULL)
       
   449         xmlTextReaderFreeNodeList(reader, cur->children);
       
   450     if (cur->version != NULL)
       
   451         xmlFree((char *) cur->version);
       
   452     if (cur->name != NULL)
       
   453         xmlFree((char *) cur->name);
       
   454     if (cur->encoding != NULL)
       
   455         xmlFree((char *) cur->encoding);
       
   456     if (cur->oldNs != NULL)
       
   457         xmlFreeNsList(cur->oldNs);
       
   458     if (cur->URL != NULL)
       
   459         xmlFree((char *) cur->URL);
       
   460     if (cur->dict != NULL)
       
   461         xmlDictFree(cur->dict);
       
   462 
       
   463     xmlFree(cur);
       
   464 }
       
   465 
       
   466 /************************************************************************
       
   467  *                                                                      *
       
   468  *          The reader core parser                                      *
       
   469  *                                                                      *
       
   470  ************************************************************************/
       
   471 #ifdef DEBUG_READER
       
   472 static void
       
   473 xmlTextReaderDebug(xmlTextReaderPtr reader) {
       
   474     if ((reader == NULL) || (reader->ctxt == NULL)) {
       
   475         fprintf(stderr, "xmlTextReader NULL\n");
       
   476         return;
       
   477     }
       
   478     fprintf(stderr, "xmlTextReader: state %d depth %d ",
       
   479             reader->state, reader->depth);
       
   480     if (reader->node == NULL) {
       
   481         fprintf(stderr, "node = NULL\n");
       
   482     } else {
       
   483         fprintf(stderr, "node %s\n", reader->node->name);
       
   484     }
       
   485     fprintf(stderr, "  input: base %d, cur %d, depth %d: ",
       
   486             reader->base, reader->cur, reader->ctxt->nodeNr);
       
   487     if (reader->input->buffer == NULL) {
       
   488         fprintf(stderr, "buffer is NULL\n");
       
   489     } else {
       
   490 #ifdef LIBXML_DEBUG_ENABLED
       
   491         xmlDebugDumpString(stderr,
       
   492                 &reader->input->buffer->content[reader->cur]);
       
   493 #endif
       
   494         fprintf(stderr, "\n");
       
   495     }
       
   496 }
       
   497 #endif
       
   498 
       
   499 /**
       
   500  * xmlTextReaderEntPush:
       
   501  * @param reader the xmlTextReaderPtr used
       
   502  * @param value the entity reference node
       
   503  *
       
   504  * Pushes a new entity reference node on top of the entities stack
       
   505  *
       
   506  * Returns 0 in case of error, the index in the stack otherwise
       
   507  */
       
   508 static int
       
   509 xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
       
   510 {
       
   511     if (reader->entMax <= 0) {
       
   512         int size = 10;
       
   513         reader->entMax = 0;
       
   514         reader->entTab = (xmlNodePtr*) xmlMalloc(size * sizeof(reader->entTab[0]));
       
   515         if (!reader->entTab)
       
   516             goto OOM_exit;
       
   517         reader->entMax = size;
       
   518     }
       
   519     if (reader->entNr >= reader->entMax) {
       
   520         xmlNodePtr* tmp;
       
   521         reader->entMax *= 2;
       
   522         tmp = (xmlNodePtr*)xmlRealloc(reader->entTab, // DONE: Fix xmlRealloc
       
   523                                       reader->entMax * sizeof(reader->entTab[0]));
       
   524         if (!tmp) {
       
   525             reader->entMax /= 2;
       
   526 OOM_exit:
       
   527             xmlGenericError(xmlGenericErrorContext, EMBED_ERRTXT("Memory (re)allocation failed !\n"));
       
   528             return (0);
       
   529         }
       
   530         reader->entTab = tmp;
       
   531     }
       
   532     reader->entTab[reader->entNr] = value;
       
   533     reader->ent = value;
       
   534     return (reader->entNr++);
       
   535 }
       
   536 
       
   537 /**
       
   538  * xmlTextReaderEntPop:
       
   539  * @param reader the xmlTextReaderPtr used
       
   540  *
       
   541  * Pops the top element entity from the entities stack
       
   542  *
       
   543  * Returns the entity just removed
       
   544  */
       
   545 static xmlNodePtr
       
   546 xmlTextReaderEntPop(xmlTextReaderPtr reader)
       
   547 {
       
   548     xmlNodePtr ret;
       
   549 
       
   550     if (reader->entNr <= 0)
       
   551         return NULL;
       
   552     reader->entNr--;
       
   553     if (reader->entNr > 0)
       
   554         reader->ent = reader->entTab[reader->entNr - 1];
       
   555     else
       
   556         reader->ent = NULL;
       
   557     ret = reader->entTab[reader->entNr];
       
   558     reader->entTab[reader->entNr] = NULL;
       
   559     return (ret);
       
   560 }
       
   561 
       
   562 /**
       
   563  * xmlTextReaderStartElement:
       
   564  * @param ctx the user data (XML parser context)
       
   565  * @param fullname The element name, including namespace prefix
       
   566  * @param atts An array of name/value attributes pairs, NULL terminated
       
   567  *
       
   568  * called when an opening tag has been processed.
       
   569  */
       
   570 static void
       
   571 xmlTextReaderStartElement(void* ctx, const xmlChar* fullname, const xmlChar** atts)
       
   572 {
       
   573     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
       
   574     xmlTextReaderPtr reader = ctxt->_private;
       
   575 
       
   576 #ifdef DEBUG_CALLBACKS
       
   577     printf("xmlTextReaderStartElement(%s)\n", fullname);
       
   578 #endif
       
   579     if ((reader != NULL) && (reader->startElement != NULL)) {
       
   580         reader->startElement(ctx, fullname, atts);
       
   581         if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
       
   582             (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
       
   583             (ctxt->input->cur[1] == '>'))
       
   584         {
       
   585             ctxt->node->extra = NODE_IS_EMPTY;
       
   586         }
       
   587     }
       
   588     if (reader != NULL)
       
   589         reader->state = XML_TEXTREADER_ELEMENT;
       
   590 }
       
   591 
       
   592 /**
       
   593  * xmlTextReaderEndElement:
       
   594  * @param ctx the user data (XML parser context)
       
   595  * @param fullname The element name, including namespace prefix
       
   596  *
       
   597  * called when an ending tag has been processed.
       
   598  */
       
   599 static void
       
   600 xmlTextReaderEndElement(void *ctx, const xmlChar *fullname)
       
   601 {
       
   602     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
       
   603     xmlTextReaderPtr reader = ctxt->_private;
       
   604 
       
   605 #ifdef DEBUG_CALLBACKS
       
   606     printf("xmlTextReaderEndElement(%s)\n", fullname);
       
   607 #endif
       
   608     if ((reader != NULL) && (reader->endElement != NULL)) {
       
   609         reader->endElement(ctx, fullname);
       
   610     }
       
   611 }
       
   612 
       
   613 /**
       
   614  * xmlTextReaderStartElementNs:
       
   615  * @param ctx the user data (XML parser context)
       
   616  * @param localname the local name of the element
       
   617  * @param prefix the element namespace prefix if available
       
   618  * @param URI the element namespace name if available
       
   619  * @param nb_namespaces number of namespace definitions on that node
       
   620  * @param namespaces pointer to the array of prefix/URI pairs namespace definitions
       
   621  * @param nb_attributes the number of attributes on that node
       
   622  * nb_defaulted:  the number of defaulted attributes.
       
   623  * @param attributes pointer to the array of (localname/prefix/URI/value/end)
       
   624  *               attribute values.
       
   625  *
       
   626  * called when an opening tag has been processed.
       
   627  */
       
   628 static void
       
   629 xmlTextReaderStartElementNs(void *ctx,
       
   630               const xmlChar *localname,
       
   631               const xmlChar *prefix,
       
   632               const xmlChar *URI,
       
   633               int nb_namespaces,
       
   634               const xmlChar **namespaces,
       
   635               int nb_attributes,
       
   636               int nb_defaulted,
       
   637               const xmlChar **attributes)
       
   638 {
       
   639     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
       
   640     xmlTextReaderPtr reader = ctxt->_private;
       
   641 
       
   642 #ifdef DEBUG_CALLBACKS
       
   643     printf("xmlTextReaderStartElementNs(%s)\n", localname);
       
   644 #endif
       
   645     if ((reader != NULL) && (reader->startElementNs != NULL))
       
   646     {
       
   647         reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
       
   648                            namespaces, nb_attributes, nb_defaulted,
       
   649                            attributes);
       
   650         if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
       
   651             (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
       
   652             (ctxt->input->cur[1] == '>'))
       
   653         {
       
   654             ctxt->node->extra = NODE_IS_EMPTY;
       
   655         }
       
   656     }
       
   657     if (reader != NULL)
       
   658         reader->state = XML_TEXTREADER_ELEMENT;
       
   659 }
       
   660 
       
   661 /**
       
   662  * xmlTextReaderEndElementNs:
       
   663  * @param ctx the user data (XML parser context)
       
   664  * @param localname the local name of the element
       
   665  * @param prefix the element namespace prefix if available
       
   666  * @param URI the element namespace name if available
       
   667  *
       
   668  * called when an ending tag has been processed.
       
   669  */
       
   670 static void
       
   671 xmlTextReaderEndElementNs(void *ctx,
       
   672                           const xmlChar * localname,
       
   673                           const xmlChar * prefix,
       
   674                           const xmlChar * URI)
       
   675 {
       
   676     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
       
   677     xmlTextReaderPtr reader = ctxt->_private;
       
   678 
       
   679 #ifdef DEBUG_CALLBACKS
       
   680     printf("xmlTextReaderEndElementNs(%s)\n", localname);
       
   681 #endif
       
   682     if ((reader != NULL) && (reader->endElementNs != NULL)) {
       
   683         reader->endElementNs(ctx, localname, prefix, URI);
       
   684     }
       
   685 }
       
   686 
       
   687 
       
   688 /**
       
   689  * xmlTextReaderCharacters:
       
   690  * @param ctx the user data (XML parser context)
       
   691  * @param ch a xmlChar string
       
   692  * @param len the number of xmlChar
       
   693  *
       
   694  * receiving some chars from the parser.
       
   695  */
       
   696 static void
       
   697 xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
       
   698 {
       
   699     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
       
   700     xmlTextReaderPtr reader = ctxt->_private;
       
   701 
       
   702 #ifdef DEBUG_CALLBACKS
       
   703     printf("xmlTextReaderCharacters()\n");
       
   704 #endif
       
   705     if ((reader != NULL) && (reader->characters != NULL)) {
       
   706         reader->characters(ctx, ch, len);
       
   707     }
       
   708 }
       
   709 
       
   710 /**
       
   711  * xmlTextReaderCDataBlock:
       
   712  * @param ctx the user data (XML parser context)
       
   713  * @param value The pcdata content
       
   714  * @param len the block length
       
   715  *
       
   716  * called when a pcdata block has been parsed
       
   717  */
       
   718 static void
       
   719 xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
       
   720 {
       
   721     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
       
   722     xmlTextReaderPtr reader = ctxt->_private;
       
   723 
       
   724 #ifdef DEBUG_CALLBACKS
       
   725     printf("xmlTextReaderCDataBlock()\n");
       
   726 #endif
       
   727     if ((reader != NULL) && (reader->cdataBlock != NULL)) {
       
   728         reader->cdataBlock(ctx, ch, len);
       
   729     }
       
   730 }
       
   731 
       
   732 /**
       
   733  * xmlTextReaderPushData:
       
   734  * @param reader the xmlTextReaderPtr used
       
   735  *
       
   736  * Push data down the progressive parser until a significant callback
       
   737  * got raised.
       
   738  *
       
   739  * Returns -1 in case of failure, 0 otherwise
       
   740  */
       
   741 static int
       
   742 xmlTextReaderPushData(xmlTextReaderPtr reader) {
       
   743     xmlBufferPtr inbuf;
       
   744     int val, s;
       
   745     xmlTextReaderState oldstate;
       
   746 
       
   747     if ((reader->input == NULL) || (reader->input->buffer == NULL))
       
   748         return(-1);
       
   749 
       
   750     oldstate = reader->state;
       
   751     reader->state = XML_TEXTREADER_NONE;
       
   752     inbuf = reader->input->buffer;
       
   753 
       
   754     while (reader->state == XML_TEXTREADER_NONE)
       
   755     {
       
   756         if (inbuf->use < reader->cur + CHUNK_SIZE)
       
   757         {
       
   758             /*
       
   759              * Refill the buffer unless we are at the end of the stream
       
   760              */
       
   761             if (reader->mode != XML_TEXTREADER_MODE_EOF)
       
   762             {
       
   763                 val = xmlParserInputBufferRead(reader->input, 4096);
       
   764                 if ((val == 0) &&
       
   765                     (inbuf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
       
   766                     if (inbuf->use == reader->cur) {
       
   767                         reader->mode = XML_TEXTREADER_MODE_EOF;
       
   768                         reader->state = oldstate;
       
   769                     }
       
   770                 } else if (val < 0) {
       
   771                     reader->mode = XML_TEXTREADER_MODE_EOF;
       
   772                     reader->state = oldstate;
       
   773                     if ((oldstate != XML_TEXTREADER_START) ||
       
   774                         (reader->ctxt->myDoc != NULL))
       
   775                         return(val);
       
   776                 } else if (val == 0) {
       
   777                     /* mark the end of the stream and process the remains */
       
   778                     reader->mode = XML_TEXTREADER_MODE_EOF;
       
   779                     break;
       
   780                 }
       
   781             } else
       
   782               break;
       
   783         }
       
   784         /*
       
   785          * parse by block of CHUNK_SIZE bytes, various tests show that
       
   786          * it's the best tradeoff at least on a 1.2GH Duron
       
   787          */
       
   788         if (inbuf->use >= reader->cur + CHUNK_SIZE)
       
   789         {
       
   790             val = xmlParseChunk(reader->ctxt,
       
   791                       (const char *) &inbuf->content[reader->cur],
       
   792                       CHUNK_SIZE, 0);
       
   793             reader->cur += CHUNK_SIZE;
       
   794             if ((val != 0) || (reader->ctxt->wellFormed == 0))
       
   795                 return(-1);
       
   796         } else {
       
   797             s = inbuf->use - reader->cur;
       
   798             val = xmlParseChunk(reader->ctxt,
       
   799                         (const char*) &inbuf->content[reader->cur],
       
   800                         s, 0);
       
   801             reader->cur += s;
       
   802             if ((val != 0) || (reader->ctxt->wellFormed == 0))
       
   803                 return(-1);
       
   804             break;
       
   805         }
       
   806     } // reader->state == XML_TEXTREADER_NONE
       
   807 
       
   808     /*
       
   809      * Discard the consumed input when needed and possible
       
   810      */
       
   811     if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE)
       
   812     {
       
   813         if (inbuf->alloc != XML_BUFFER_ALLOC_IMMUTABLE)
       
   814         {
       
   815             if ((reader->cur >= 4096) &&
       
   816                 (inbuf->use - reader->cur <= CHUNK_SIZE))
       
   817             {
       
   818                 val = xmlBufferShrink(inbuf, reader->cur);
       
   819                 if (val >= 0) {
       
   820                     reader->cur -= val;
       
   821                 }
       
   822             }
       
   823         }
       
   824     }
       
   825 
       
   826     /*
       
   827      * At the end of the stream signal that the work is done to the Push
       
   828      * parser.
       
   829      */
       
   830     else if (reader->mode == XML_TEXTREADER_MODE_EOF)
       
   831     {
       
   832         if (reader->mode != XML_TEXTREADER_DONE)
       
   833         {
       
   834             s = inbuf->use - reader->cur;
       
   835             val = xmlParseChunk(reader->ctxt,
       
   836                 (const char *) &inbuf->content[reader->cur],
       
   837                 s, 1);
       
   838             reader->cur = inbuf->use;
       
   839             reader->mode = XML_TEXTREADER_DONE;
       
   840             if ((val != 0) || (reader->ctxt->wellFormed == 0))
       
   841                 return(-1);
       
   842         }
       
   843     }
       
   844     reader->state = oldstate;
       
   845     return(0);
       
   846 }
       
   847 
       
   848 #ifdef LIBXML_REGEXP_ENABLED
       
   849 /**
       
   850  * xmlTextReaderValidatePush:
       
   851  * @param reader the xmlTextReaderPtr used
       
   852  *
       
   853  * Push the current node for validation
       
   854  */
       
   855 static void
       
   856 xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
       
   857     xmlNodePtr node = reader->node;
       
   858 
       
   859 #ifdef LIBXML_VALID_ENABLED
       
   860     if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
       
   861         (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
       
   862         if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
       
   863             reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
       
   864                                     reader->ctxt->myDoc, node, node->name);
       
   865         } else {
       
   866             
       
   867             xmlChar *qname;
       
   868 
       
   869             qname = xmlStrdup(node->ns->prefix);
       
   870             qname = xmlStrcat(qname, BAD_CAST ":");
       
   871             qname = xmlStrcat(qname, node->name);
       
   872             reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
       
   873                                     reader->ctxt->myDoc, node, qname);
       
   874             if (qname != NULL)
       
   875                 xmlFree(qname);
       
   876         }
       
   877     }
       
   878 #endif /* LIBXML_VALID_ENABLED */
       
   879 #ifdef LIBXML_SCHEMAS_ENABLED
       
   880     if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
       
   881                (reader->rngValidCtxt != NULL)) {
       
   882         int ret;
       
   883 
       
   884         if (reader->rngFullNode != NULL) return;
       
   885         ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
       
   886                                             reader->ctxt->myDoc,
       
   887                                             node);
       
   888         if (ret == 0) {
       
   889             /*
       
   890              * this element requires a full tree
       
   891              */
       
   892             node = xmlTextReaderExpand(reader);
       
   893             if (node == NULL) {
       
   894 printf(EMBED_ERRTXT("Expand failed !\n"));
       
   895                 ret = -1;
       
   896             } else {
       
   897                 ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
       
   898                                                     reader->ctxt->myDoc,
       
   899                                                     node);
       
   900                 reader->rngFullNode = node;
       
   901             }
       
   902         }
       
   903         if (ret != 1)
       
   904             reader->rngValidErrors++;
       
   905     }
       
   906 #endif
       
   907 }
       
   908 
       
   909 /**
       
   910  * xmlTextReaderValidateCData:
       
   911  * @param reader the xmlTextReaderPtr used
       
   912  * @param data pointer to the CData
       
   913  * @param len lenght of the CData block in bytes.
       
   914  *
       
   915  * Push some CData for validation
       
   916  */
       
   917 static void
       
   918 xmlTextReaderValidateCData(xmlTextReaderPtr reader,
       
   919                            const xmlChar *data, int len) {
       
   920 #ifdef LIBXML_VALID_ENABLED
       
   921     if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
       
   922         (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
       
   923         reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
       
   924                                                     data, len);
       
   925     }
       
   926 #endif /* LIBXML_VALID_ENABLED */
       
   927 #ifdef LIBXML_SCHEMAS_ENABLED
       
   928     if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
       
   929                (reader->rngValidCtxt != NULL)) {
       
   930         int ret;
       
   931 
       
   932         if (reader->rngFullNode != NULL) return;
       
   933         ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
       
   934         if (ret != 1)
       
   935             reader->rngValidErrors++;
       
   936     }
       
   937 #endif
       
   938 }
       
   939 
       
   940 /**
       
   941  * xmlTextReaderValidatePop:
       
   942  * @param reader the xmlTextReaderPtr used
       
   943  *
       
   944  * Pop the current node from validation
       
   945  */
       
   946 static void
       
   947 xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
       
   948     xmlNodePtr node = reader->node;
       
   949 
       
   950 #ifdef LIBXML_VALID_ENABLED
       
   951     if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
       
   952         (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
       
   953         if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
       
   954             reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
       
   955                                     reader->ctxt->myDoc, node, node->name);
       
   956         } else {
       
   957             
       
   958             xmlChar *qname;
       
   959 
       
   960             qname = xmlStrdup(node->ns->prefix);
       
   961             qname = xmlStrcat(qname, BAD_CAST ":");
       
   962             qname = xmlStrcat(qname, node->name);
       
   963             reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
       
   964                                     reader->ctxt->myDoc, node, qname);
       
   965             if (qname != NULL)
       
   966                 xmlFree(qname);
       
   967         }
       
   968     }
       
   969 #endif /* LIBXML_VALID_ENABLED */
       
   970 #ifdef LIBXML_SCHEMAS_ENABLED
       
   971     if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
       
   972                (reader->rngValidCtxt != NULL)) {
       
   973         int ret;
       
   974 
       
   975         if (reader->rngFullNode != NULL) {
       
   976             if (node == reader->rngFullNode)
       
   977                 reader->rngFullNode = NULL;
       
   978             return;
       
   979         }
       
   980         ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
       
   981                                            reader->ctxt->myDoc,
       
   982                                            node);
       
   983         if (ret != 1)
       
   984             reader->rngValidErrors++;
       
   985     }
       
   986 #endif
       
   987 }
       
   988 
       
   989 /**
       
   990  * xmlTextReaderValidateEntity:
       
   991  * @param reader the xmlTextReaderPtr used
       
   992  *
       
   993  * Handle the validation when an entity reference is encountered and
       
   994  * entity substitution is not activated. As a result the parser interface
       
   995  * must walk through the entity and do the validation calls
       
   996  */
       
   997 static void
       
   998 xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
       
   999     xmlNodePtr oldnode = reader->node;
       
  1000     xmlNodePtr node = reader->node;
       
  1001     xmlParserCtxtPtr ctxt = reader->ctxt;
       
  1002 
       
  1003     do {
       
  1004         if (node->type == XML_ENTITY_REF_NODE) {
       
  1005             /*
       
  1006              * Case where the underlying tree is not availble, lookup the entity
       
  1007              * and walk it.
       
  1008              */
       
  1009             if ((node->children == NULL) && (ctxt->sax != NULL) &&
       
  1010                 (ctxt->sax->getEntity != NULL)) {
       
  1011                 node->children = (xmlNodePtr)
       
  1012                     ctxt->sax->getEntity(ctxt, node->name);
       
  1013             }
       
  1014 
       
  1015             if ((node->children != NULL) &&
       
  1016                 (node->children->type == XML_ENTITY_DECL) &&
       
  1017                 (node->children->children != NULL)) {
       
  1018                 xmlTextReaderEntPush(reader, node);
       
  1019                 node = node->children->children;
       
  1020                 continue;
       
  1021             } else {
       
  1022                 /*
       
  1023                  * The error has probably be raised already.
       
  1024                  */
       
  1025                 if (node == oldnode)
       
  1026                     break;
       
  1027                 node = node->next;
       
  1028             }
       
  1029 #ifdef LIBXML_REGEXP_ENABLED
       
  1030         } else if (node->type == XML_ELEMENT_NODE) {
       
  1031             reader->node = node;
       
  1032             xmlTextReaderValidatePush(reader);
       
  1033         } else if ((node->type == XML_TEXT_NODE) ||
       
  1034                    (node->type == XML_CDATA_SECTION_NODE)) {
       
  1035             xmlTextReaderValidateCData(reader, node->content,
       
  1036                                        xmlStrlen(node->content));
       
  1037 #endif
       
  1038         }
       
  1039 
       
  1040         /*
       
  1041          * go to next node
       
  1042          */
       
  1043         if (node->children != NULL) {
       
  1044             node = node->children;
       
  1045             continue;
       
  1046         } else if (node->type == XML_ELEMENT_NODE) {
       
  1047             xmlTextReaderValidatePop(reader);
       
  1048         }
       
  1049         if (node->next != NULL) {
       
  1050             node = node->next;
       
  1051             continue;
       
  1052         }
       
  1053         do {
       
  1054             node = node->parent;
       
  1055             if (node->type == XML_ELEMENT_NODE) {
       
  1056                 xmlNodePtr tmp;
       
  1057                 if (reader->entNr == 0) {
       
  1058                     while ((tmp = node->last) != NULL) {
       
  1059                         if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
       
  1060                             xmlUnlinkNode(tmp);
       
  1061                             xmlTextReaderFreeNode(reader, tmp);
       
  1062                         } else
       
  1063                             break;
       
  1064                     }
       
  1065                 }
       
  1066                 reader->node = node;
       
  1067                 xmlTextReaderValidatePop(reader);
       
  1068             }
       
  1069             if ((node->type == XML_ENTITY_DECL) &&
       
  1070                 (reader->ent != NULL) && (reader->ent->children == node)) {
       
  1071                 node = xmlTextReaderEntPop(reader);
       
  1072             }
       
  1073             if (node == oldnode)
       
  1074                 break;
       
  1075             if (node->next != NULL) {
       
  1076                 node = node->next;
       
  1077                 break;
       
  1078             }
       
  1079         } while ((node != NULL) && (node != oldnode));
       
  1080     } while ((node != NULL) && (node != oldnode));
       
  1081     reader->node = oldnode;
       
  1082 }
       
  1083 #endif /* LIBXML_REGEXP_ENABLED */
       
  1084 
       
  1085 
       
  1086 /**
       
  1087  * xmlTextReaderGetSuccessor:
       
  1088  * @param cur the current node
       
  1089  *
       
  1090  * Get the successor of a node if available.
       
  1091  *
       
  1092  * Returns the successor node or NULL
       
  1093  */
       
  1094 static xmlNodePtr
       
  1095 xmlTextReaderGetSuccessor(xmlNodePtr cur)
       
  1096 {
       
  1097     if (cur == NULL)
       
  1098         return(NULL) ; /* ERROR */
       
  1099     if (cur->next != NULL)
       
  1100         return(cur->next) ;
       
  1101     do {
       
  1102         cur = cur->parent;
       
  1103         if (cur == NULL)
       
  1104             return(NULL);
       
  1105         if (cur->next != NULL)
       
  1106             return(cur->next);
       
  1107     } while (cur != NULL);
       
  1108     return(cur);
       
  1109 }
       
  1110 
       
  1111 /**
       
  1112  * xmlTextReaderDoExpand:
       
  1113  * @param reader the xmlTextReaderPtr used
       
  1114  *
       
  1115  * Makes sure that the current node is fully read as well as all its
       
  1116  * descendant. It means the full DOM subtree must be available at the
       
  1117  * end of the call.
       
  1118  *
       
  1119  * Returns 1 if the node was expanded successfully, 0 if there is no more
       
  1120  *          nodes to read, or -1 in case of error
       
  1121  */
       
  1122 static int
       
  1123 xmlTextReaderDoExpand(xmlTextReaderPtr reader)
       
  1124 {
       
  1125     int val;
       
  1126 
       
  1127     if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
       
  1128         return(-1);
       
  1129 
       
  1130     do {
       
  1131         if (reader->ctxt->instate == XML_PARSER_EOF)
       
  1132             return(1);
       
  1133         if (xmlTextReaderGetSuccessor(reader->node) != NULL)
       
  1134             return(1);
       
  1135         if (reader->ctxt->nodeNr < reader->depth)
       
  1136             return(1);
       
  1137         if (reader->mode == XML_TEXTREADER_MODE_EOF)
       
  1138             return(1);
       
  1139         val = xmlTextReaderPushData(reader);
       
  1140         if (val < 0)
       
  1141             return(-1);
       
  1142     } while(reader->mode != XML_TEXTREADER_MODE_EOF);
       
  1143     return(1);
       
  1144 }
       
  1145 
       
  1146 /**
       
  1147  * xmlTextReaderCollectSiblings:
       
  1148  * @param node the first child
       
  1149  *
       
  1150  *  Traverse depth-first through all sibling nodes and their children
       
  1151  *  nodes and concatenate their content. This is an auxiliary function
       
  1152  *  to xmlTextReaderReadString.
       
  1153  *
       
  1154  *  Returns a string containing the content, or NULL in case of error.
       
  1155  */
       
  1156 static xmlChar *
       
  1157 xmlTextReaderCollectSiblings(xmlNodePtr node)
       
  1158 {
       
  1159     xmlBufferPtr buffer;
       
  1160     xmlChar *ret;
       
  1161 
       
  1162     buffer = xmlBufferCreate();
       
  1163     if (buffer == NULL)
       
  1164        return NULL;
       
  1165 
       
  1166     for ( ; node != NULL; node = node->next) {
       
  1167        switch (node->type) {
       
  1168        case XML_TEXT_NODE:
       
  1169        case XML_CDATA_SECTION_NODE:
       
  1170            xmlBufferCat(buffer, node->content);
       
  1171            break;
       
  1172        case XML_ELEMENT_NODE: {
       
  1173            xmlChar *tmp;
       
  1174 
       
  1175        tmp = xmlTextReaderCollectSiblings(node->children);
       
  1176            xmlBufferCat(buffer, tmp);
       
  1177        xmlFree(tmp);
       
  1178        break;
       
  1179        }
       
  1180        default:
       
  1181            break;
       
  1182        }
       
  1183     }
       
  1184     ret = buffer->content;
       
  1185     buffer->content = NULL;
       
  1186     xmlBufferFree(buffer);
       
  1187     return(ret);
       
  1188 }
       
  1189 
       
  1190 /**
       
  1191  * xmlTextReaderRead:
       
  1192  * @param reader the xmlTextReaderPtr used
       
  1193  *
       
  1194  *  Moves the position of the current instance to the next node in
       
  1195  *  the stream, exposing its properties.
       
  1196  *
       
  1197  *  Returns 1 if the node was read successfully, 0 if there is no more
       
  1198  *          nodes to read, or -1 in case of error
       
  1199  */
       
  1200 XMLPUBFUNEXPORT int
       
  1201 xmlTextReaderRead(xmlTextReaderPtr reader)
       
  1202 {
       
  1203     int val, olddepth = 0;
       
  1204     xmlTextReaderState oldstate = XML_TEXTREADER_START;
       
  1205     xmlNodePtr oldnode = NULL;
       
  1206 
       
  1207 
       
  1208     if (reader == NULL)
       
  1209         return(-1);
       
  1210     reader->curnode = NULL;
       
  1211     if (reader->doc != NULL)
       
  1212         return(xmlTextReaderReadTree(reader));
       
  1213     if (reader->ctxt == NULL)
       
  1214         return(-1);
       
  1215     if (reader->ctxt->wellFormed != 1)
       
  1216         return(-1);
       
  1217 
       
  1218 #ifdef DEBUG_READER
       
  1219     fprintf(stderr, "\nREAD ");
       
  1220     DUMP_READER
       
  1221 #endif
       
  1222     if (reader->mode == XML_TEXTREADER_MODE_INITIAL)
       
  1223     {
       
  1224         reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
       
  1225         /*
       
  1226          * Initial state
       
  1227          */
       
  1228         do {
       
  1229             val = xmlTextReaderPushData(reader);
       
  1230             if (val < 0)
       
  1231                 return(-1);
       
  1232         } while ((reader->ctxt->node == NULL) &&
       
  1233                  ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
       
  1234                   (reader->mode != XML_TEXTREADER_DONE)));
       
  1235 
       
  1236         if (reader->ctxt->node == NULL) {
       
  1237             if (reader->ctxt->myDoc != NULL) {
       
  1238                 reader->node = reader->ctxt->myDoc->children;
       
  1239             }
       
  1240             if (reader->node == NULL)
       
  1241                 return(-1);
       
  1242             reader->state = XML_TEXTREADER_ELEMENT;
       
  1243         } else {
       
  1244             if (reader->ctxt->myDoc != NULL) {
       
  1245                 reader->node = reader->ctxt->myDoc->children;
       
  1246             }
       
  1247             if (reader->node == NULL)
       
  1248                 reader->node = reader->ctxt->nodeTab[0];
       
  1249             reader->state = XML_TEXTREADER_ELEMENT;
       
  1250         }
       
  1251         reader->depth = 0;
       
  1252         
       
  1253         //reader->ctxt->parseMode = XML_PARSE_READER;
       
  1254         goto node_found;
       
  1255     }
       
  1256 
       
  1257     oldstate = reader->state;
       
  1258     olddepth = reader->ctxt->nodeNr;
       
  1259     oldnode = reader->node;
       
  1260 
       
  1261 get_next_node:
       
  1262     if (reader->node == NULL) {
       
  1263         if (reader->mode == XML_TEXTREADER_DONE)
       
  1264             return(0);
       
  1265         else
       
  1266             return(-1);
       
  1267     }
       
  1268 
       
  1269     /*
       
  1270      * If we are not backtracking on ancestors or examined nodes,
       
  1271      * that the parser didn't finished or that we arent at the end
       
  1272      * of stream, continue processing.
       
  1273      */
       
  1274     while (
       
  1275         reader->node
       
  1276         &&
       
  1277         !reader->node->next
       
  1278         &&
       
  1279         reader->ctxt->nodeNr == olddepth
       
  1280         &&
       
  1281           (
       
  1282             (oldstate == XML_TEXTREADER_BACKTRACK)       ||
       
  1283             (reader->node->children == NULL)             ||
       
  1284             (reader->node->type == XML_ENTITY_REF_NODE)
       
  1285             ||
       
  1286               (
       
  1287                 (reader->node->children != NULL) &&
       
  1288                 (reader->node->children->type == XML_TEXT_NODE) &&
       
  1289                 (reader->node->children->next == NULL)
       
  1290                )
       
  1291             ||
       
  1292             (reader->node->type == XML_DTD_NODE) ||
       
  1293             (reader->node->type == XML_DOCUMENT_NODE) ||
       
  1294             (reader->node->type == XML_HTML_DOCUMENT_NODE)
       
  1295           )
       
  1296         &&
       
  1297           (
       
  1298             (reader->ctxt->node == NULL) ||
       
  1299             (reader->ctxt->node == reader->node) ||
       
  1300             (reader->ctxt->node == reader->node->parent)
       
  1301           )
       
  1302         &&
       
  1303        (reader->ctxt->instate != XML_PARSER_EOF))
       
  1304     {
       
  1305         val = xmlTextReaderPushData(reader);
       
  1306         if (val < 0)
       
  1307             return(-1);
       
  1308         if (reader->node == NULL)
       
  1309             goto node_end;
       
  1310     } // while
       
  1311 
       
  1312     if (oldstate != XML_TEXTREADER_BACKTRACK)
       
  1313     {
       
  1314         if ((reader->node->children != NULL) &&
       
  1315             (reader->node->type != XML_ENTITY_REF_NODE) &&
       
  1316             (reader->node->type != XML_XINCLUDE_START) &&
       
  1317             (reader->node->type != XML_DTD_NODE))
       
  1318         {
       
  1319             reader->node = reader->node->children;
       
  1320             reader->depth++;
       
  1321             reader->state = XML_TEXTREADER_ELEMENT;
       
  1322             goto node_found;
       
  1323         }
       
  1324     }
       
  1325 
       
  1326     if (reader->node->next)
       
  1327     {
       
  1328         if ((oldstate == XML_TEXTREADER_ELEMENT) &&
       
  1329             (reader->node->type == XML_ELEMENT_NODE) &&
       
  1330             (reader->node->children == NULL) &&
       
  1331             ((reader->node->extra & NODE_IS_EMPTY) == 0)
       
  1332 #ifdef LIBXML_XINCLUDE_ENABLED
       
  1333             && (reader->in_xinclude <= 0)
       
  1334 #endif
       
  1335         )
       
  1336         {
       
  1337             reader->state = XML_TEXTREADER_END;
       
  1338             goto node_found;
       
  1339         }
       
  1340 #ifdef LIBXML_REGEXP_ENABLED
       
  1341         if ((reader->validate) &&
       
  1342             (reader->node->type == XML_ELEMENT_NODE))
       
  1343         {
       
  1344             xmlTextReaderValidatePop(reader);
       
  1345         }
       
  1346 #endif /* LIBXML_REGEXP_ENABLED */
       
  1347         if ((reader->preserves > 0) &&
       
  1348             (reader->node->extra & NODE_IS_SPRESERVED))
       
  1349         {
       
  1350             reader->preserves--;
       
  1351         }
       
  1352         reader->node = reader->node->next;
       
  1353         reader->state = XML_TEXTREADER_ELEMENT;
       
  1354 
       
  1355         /*
       
  1356          * Cleanup of the old node
       
  1357          */
       
  1358         if ((reader->preserves == 0) &&
       
  1359 #ifdef LIBXML_XINCLUDE_ENABLED
       
  1360             (reader->in_xinclude == 0) &&
       
  1361 #endif
       
  1362             (reader->entNr == 0) &&
       
  1363             (reader->node->prev != NULL) &&
       
  1364             (reader->node->prev->type != XML_DTD_NODE) &&
       
  1365             (reader->entNr == 0))
       
  1366         {
       
  1367             xmlNodePtr tmp = reader->node->prev;
       
  1368             if ((tmp->extra & NODE_IS_PRESERVED) == 0)
       
  1369             {
       
  1370                 xmlUnlinkNode(tmp);
       
  1371                 xmlTextReaderFreeNode(reader, tmp);
       
  1372             }
       
  1373         }
       
  1374 
       
  1375         goto node_found;
       
  1376     } // if (reader->node->next)
       
  1377 
       
  1378     if ((oldstate == XML_TEXTREADER_ELEMENT) &&
       
  1379         (reader->node->type == XML_ELEMENT_NODE) &&
       
  1380         (reader->node->children == NULL) &&
       
  1381         ((reader->node->extra & NODE_IS_EMPTY) == 0))
       
  1382     {
       
  1383         reader->state = XML_TEXTREADER_END;
       
  1384         goto node_found;
       
  1385     }
       
  1386 #ifdef LIBXML_REGEXP_ENABLED
       
  1387     if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE))
       
  1388     {
       
  1389         xmlTextReaderValidatePop(reader);
       
  1390     }
       
  1391 #endif /* LIBXML_REGEXP_ENABLED */
       
  1392     if ((reader->preserves > 0) &&
       
  1393         (reader->node->extra & NODE_IS_SPRESERVED))
       
  1394     {
       
  1395         reader->preserves--;
       
  1396     }
       
  1397     reader->node = reader->node->parent;
       
  1398     if ((reader->node == NULL) ||
       
  1399         (reader->node->type == XML_DOCUMENT_NODE) ||
       
  1400 #ifdef LIBXML_DOCB_ENABLED
       
  1401         (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
       
  1402 #endif
       
  1403         (reader->node->type == XML_HTML_DOCUMENT_NODE))
       
  1404     {
       
  1405         if (reader->mode != XML_TEXTREADER_DONE)
       
  1406         {
       
  1407             val = xmlParseChunk(reader->ctxt, "", 0, 1);
       
  1408             reader->mode = XML_TEXTREADER_DONE;
       
  1409         if (val != 0)
       
  1410             return(-1);
       
  1411         }
       
  1412         reader->node = NULL;
       
  1413         reader->depth = -1;
       
  1414 
       
  1415         /*
       
  1416          * Cleanup of the old node
       
  1417          */
       
  1418         if ((reader->preserves == 0) &&
       
  1419 #ifdef LIBXML_XINCLUDE_ENABLED
       
  1420             (reader->in_xinclude == 0) &&
       
  1421 #endif
       
  1422             (reader->entNr == 0) &&
       
  1423             (oldnode->type != XML_DTD_NODE) &&
       
  1424             ((oldnode->extra & NODE_IS_PRESERVED) == 0) &&
       
  1425             (reader->entNr == 0))
       
  1426         {
       
  1427             xmlUnlinkNode(oldnode);
       
  1428             xmlTextReaderFreeNode(reader, oldnode);
       
  1429         }
       
  1430 
       
  1431         goto node_end;
       
  1432     }
       
  1433 
       
  1434     if ((reader->preserves == 0) &&
       
  1435 #ifdef LIBXML_XINCLUDE_ENABLED
       
  1436         (reader->in_xinclude == 0) &&
       
  1437 #endif
       
  1438         (reader->entNr == 0) &&
       
  1439         (reader->node->last != NULL) &&
       
  1440         ((reader->node->last->extra & NODE_IS_PRESERVED) == 0))
       
  1441     {
       
  1442         xmlNodePtr tmp = reader->node->last;
       
  1443         xmlUnlinkNode(tmp);
       
  1444         xmlTextReaderFreeNode(reader, tmp);
       
  1445     }
       
  1446     reader->depth--;
       
  1447     reader->state = XML_TEXTREADER_BACKTRACK;
       
  1448 
       
  1449 node_found:
       
  1450     DUMP_READER
       
  1451 
       
  1452     /*
       
  1453      * If we are in the middle of a piece of CDATA make sure it's finished
       
  1454      */
       
  1455     if ((reader->node != NULL) &&
       
  1456         (reader->node->next == NULL) &&
       
  1457          ((reader->node->type == XML_TEXT_NODE) ||
       
  1458           (reader->node->type == XML_CDATA_SECTION_NODE)))
       
  1459     {
       
  1460         if (xmlTextReaderExpand(reader) == NULL) return -1;
       
  1461     }
       
  1462 
       
  1463 #ifdef LIBXML_XINCLUDE_ENABLED
       
  1464     /*
       
  1465      * Handle XInclude if asked for
       
  1466      */
       
  1467     if ((reader->xinclude) && (reader->node != NULL) &&
       
  1468         (reader->node->type == XML_ELEMENT_NODE) &&
       
  1469         (reader->node->ns != NULL) &&
       
  1470         ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
       
  1471         (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS))))
       
  1472     {
       
  1473         if (reader->xincctxt == NULL) {
       
  1474             reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
       
  1475             xmlXIncludeSetFlags(reader->xincctxt,
       
  1476                             reader->parserFlags);
       
  1477 
       
  1478 //                            reader->parserFlags & (~XML_PARSE_NOXINCNODE));
       
  1479         }
       
  1480         /*
       
  1481          * expand that node and process it
       
  1482          */
       
  1483         if (xmlTextReaderExpand(reader) == NULL)
       
  1484             return -1;
       
  1485         xmlXIncludeProcessNode(reader->xincctxt, reader->node);  
       
  1486     }
       
  1487 
       
  1488     if (reader->node->type == XML_XINCLUDE_START) {
       
  1489         reader->in_xinclude++;
       
  1490         goto get_next_node;
       
  1491     }
       
  1492 
       
  1493     if (reader->node->type == XML_XINCLUDE_END) {
       
  1494         reader->in_xinclude--;
       
  1495         goto get_next_node;
       
  1496     }
       
  1497 #endif
       
  1498     /*
       
  1499      * Handle entities enter and exit when in entity replacement mode
       
  1500      */
       
  1501     if ((reader->node != NULL) &&
       
  1502         (reader->node->type == XML_ENTITY_REF_NODE) &&
       
  1503         (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1))
       
  1504     {
       
  1505         /*
       
  1506          * Case where the underlying tree is not availble, lookup the entity
       
  1507          * and walk it.
       
  1508          */
       
  1509         if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
       
  1510             (reader->ctxt->sax->getEntity != NULL))
       
  1511         {
       
  1512             reader->node->children = (xmlNodePtr)
       
  1513             reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
       
  1514         }
       
  1515 
       
  1516         if ((reader->node->children != NULL) &&
       
  1517             (reader->node->children->type == XML_ENTITY_DECL) &&
       
  1518             (reader->node->children->children != NULL))
       
  1519         {
       
  1520             xmlTextReaderEntPush(reader, reader->node);
       
  1521             reader->node = reader->node->children->children;
       
  1522         }
       
  1523     }
       
  1524 #ifdef LIBXML_REGEXP_ENABLED
       
  1525     else if ((reader->node != NULL) &&
       
  1526            (reader->node->type == XML_ENTITY_REF_NODE) &&
       
  1527            (reader->ctxt != NULL) && (reader->validate))
       
  1528     {
       
  1529     xmlTextReaderValidateEntity(reader);
       
  1530     }
       
  1531 #endif /* LIBXML_REGEXP_ENABLED */
       
  1532 
       
  1533     if ((reader->node != NULL) &&
       
  1534         (reader->node->type == XML_ENTITY_DECL) &&
       
  1535         (reader->ent != NULL) && (reader->ent->children == reader->node))
       
  1536     {
       
  1537         reader->node = xmlTextReaderEntPop(reader);
       
  1538         reader->depth++;
       
  1539         goto get_next_node;
       
  1540     }
       
  1541 #ifdef LIBXML_REGEXP_ENABLED
       
  1542     if ((reader->validate) && (reader->node != NULL))
       
  1543     {
       
  1544         xmlNodePtr node = reader->node;
       
  1545 
       
  1546         if ((node->type == XML_ELEMENT_NODE) &&
       
  1547            ((reader->state != XML_TEXTREADER_END) &&
       
  1548            (reader->state != XML_TEXTREADER_BACKTRACK)))
       
  1549         {
       
  1550             xmlTextReaderValidatePush(reader);
       
  1551         }
       
  1552         else if ((node->type == XML_TEXT_NODE) ||
       
  1553            (node->type == XML_CDATA_SECTION_NODE))
       
  1554         {
       
  1555            xmlTextReaderValidateCData(reader, node->content, xmlStrlen(node->content));
       
  1556         }
       
  1557     }
       
  1558 #endif /* LIBXML_REGEXP_ENABLED */
       
  1559 
       
  1560 #ifdef LIBXML_PATTERN_ENABLED
       
  1561     if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
       
  1562         (reader->state != XML_TEXTREADER_BACKTRACK))
       
  1563     {
       
  1564         int i;
       
  1565         for (i = 0;i < reader->patternNr;i++)
       
  1566         {
       
  1567              if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1)
       
  1568              {
       
  1569                  xmlTextReaderPreserve(reader);
       
  1570                  break;
       
  1571              }
       
  1572         }
       
  1573     }
       
  1574 #endif /* LIBXML_PATTERN_ENABLED */
       
  1575 #ifdef LIBXML_SCHEMAS_ENABLED
       
  1576     if ((reader->validate == XML_TEXTREADER_VALIDATE_XSD) &&
       
  1577         (reader->xsdValidErrors == 0) &&
       
  1578     (reader->xsdValidCtxt != NULL)) {
       
  1579     reader->xsdValidErrors = !xmlSchemaIsValid(reader->xsdValidCtxt);
       
  1580     }
       
  1581 #endif /* LIBXML_PATTERN_ENABLED */
       
  1582     return(1);
       
  1583 
       
  1584 node_end:
       
  1585     reader->mode = XML_TEXTREADER_DONE;
       
  1586     return(0);
       
  1587 }
       
  1588 
       
  1589 /**
       
  1590  * xmlTextReaderReadState:
       
  1591  * @param reader the xmlTextReaderPtr used
       
  1592  *
       
  1593  * Gets the read state of the reader.
       
  1594  *
       
  1595  * Returns the state value, or -1 in case of error
       
  1596  */
       
  1597 XMLPUBFUNEXPORT int
       
  1598 xmlTextReaderReadState(xmlTextReaderPtr reader)
       
  1599 {
       
  1600     if (reader == NULL)
       
  1601         return(-1);
       
  1602     return(reader->mode);
       
  1603 }
       
  1604 
       
  1605 /**
       
  1606  * xmlTextReaderExpand:
       
  1607  * @param reader the xmlTextReaderPtr used
       
  1608  *
       
  1609  * Reads the contents of the current node and the full subtree. It then makes
       
  1610  * the subtree available until the next xmlTextReaderRead() call
       
  1611  *
       
  1612  * Returns a node pointer valid until the next xmlTextReaderRead() call
       
  1613  *         or NULL in case of error.
       
  1614  */
       
  1615 XMLPUBFUNEXPORT xmlNodePtr
       
  1616 xmlTextReaderExpand(xmlTextReaderPtr reader)
       
  1617 {
       
  1618     if ((reader == NULL) || (reader->node == NULL))
       
  1619         return(NULL);
       
  1620     if (reader->doc != NULL)
       
  1621         return(reader->node);
       
  1622     if (reader->ctxt == NULL)
       
  1623         return(NULL);
       
  1624     if (xmlTextReaderDoExpand(reader) < 0)
       
  1625         return(NULL);
       
  1626     return(reader->node);
       
  1627 }
       
  1628 
       
  1629 /**
       
  1630  * xmlTextReaderNext:
       
  1631  * @param reader the xmlTextReaderPtr used
       
  1632  *
       
  1633  * Skip to the node following the current one in document order while
       
  1634  * avoiding the subtree if any.
       
  1635  *
       
  1636  * Returns 1 if the node was read successfully, 0 if there is no more
       
  1637  *          nodes to read, or -1 in case of error
       
  1638  */
       
  1639 XMLPUBFUNEXPORT int
       
  1640 xmlTextReaderNext(xmlTextReaderPtr reader) {
       
  1641     int ret;
       
  1642     xmlNodePtr cur;
       
  1643 
       
  1644     if (reader == NULL)
       
  1645         return(-1);
       
  1646     if (reader->doc != NULL)
       
  1647         return(xmlTextReaderNextTree(reader));
       
  1648     cur = reader->node;
       
  1649     if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
       
  1650         return(xmlTextReaderRead(reader));  
       
  1651     if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK)
       
  1652         return(xmlTextReaderRead(reader));  
       
  1653     if (cur->extra & NODE_IS_EMPTY)
       
  1654         return(xmlTextReaderRead(reader)); 
       
  1655     do {
       
  1656         ret = xmlTextReaderRead(reader);  
       
  1657         if (ret != 1)
       
  1658             return(ret);
       
  1659     } while (reader->node != cur);
       
  1660 
       
  1661     return(xmlTextReaderRead(reader));  
       
  1662 }
       
  1663 
       
  1664 /**
       
  1665  * xmlTextReaderReadInnerXml:
       
  1666  * @param reader the xmlTextReaderPtr used
       
  1667  *
       
  1668  * Reads the contents of the current node, including child nodes and markup.
       
  1669  *
       
  1670  * Returns a string containing the XML content, or NULL if the current node
       
  1671  *         is neither an element nor attribute, or has no child nodes. The
       
  1672  *         string must be deallocated by the caller.
       
  1673  */
       
  1674 XMLPUBFUNEXPORT xmlChar*
       
  1675 xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
       
  1676 {
       
  1677     xmlChar *resbuf;
       
  1678     xmlNodePtr node, cur_node;
       
  1679     xmlBufferPtr buff, buff2;
       
  1680     xmlDocPtr doc;
       
  1681 
       
  1682     if (xmlTextReaderExpand(reader) == NULL) {
       
  1683         return NULL;
       
  1684     }
       
  1685     doc = reader->doc;
       
  1686     buff = xmlBufferCreate();
       
  1687     for (cur_node = reader->node->children; cur_node != NULL;
       
  1688          cur_node = cur_node->next) {
       
  1689         node = xmlDocCopyNode(cur_node, doc, 1);
       
  1690         buff2 = xmlBufferCreate();
       
  1691         if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) {
       
  1692             xmlFreeNode(node);
       
  1693             xmlBufferFree(buff2);
       
  1694             xmlBufferFree(buff);
       
  1695             return NULL;
       
  1696         }
       
  1697         xmlBufferCat(buff, buff2->content);
       
  1698         xmlFreeNode(node);
       
  1699         xmlBufferFree(buff2);
       
  1700     }
       
  1701     resbuf = buff->content;
       
  1702     return resbuf;
       
  1703 }
       
  1704 
       
  1705 /**
       
  1706  * xmlTextReaderReadOuterXml:
       
  1707  * @param reader the xmlTextReaderPtr used
       
  1708  *
       
  1709  * Reads the contents of the current node, including child nodes and markup.
       
  1710  *
       
  1711  * Returns a string containing the XML content, or NULL if the current node
       
  1712  *         is neither an element nor attribute, or has no child nodes. The
       
  1713  *         string must be deallocated by the caller.
       
  1714  */
       
  1715 XMLPUBFUNEXPORT xmlChar*
       
  1716 xmlTextReaderReadOuterXml(xmlTextReaderPtr reader)
       
  1717 {
       
  1718     xmlChar *resbuf;
       
  1719     xmlNodePtr node;
       
  1720     xmlBufferPtr buff;
       
  1721     xmlDocPtr doc;
       
  1722 
       
  1723     node = reader->node;
       
  1724     doc = reader->doc;
       
  1725     if (xmlTextReaderExpand(reader) == NULL) {
       
  1726         return NULL;
       
  1727     }
       
  1728     node = xmlDocCopyNode(node, doc, 1);
       
  1729     buff = xmlBufferCreate();
       
  1730     if (xmlNodeDump(buff, doc, node, 0, 0) == -1) {
       
  1731         xmlFreeNode(node);
       
  1732         xmlBufferFree(buff);
       
  1733         return NULL;
       
  1734     }
       
  1735 
       
  1736     resbuf = buff->content;
       
  1737     buff->content = NULL;
       
  1738 
       
  1739     xmlFreeNode(node);
       
  1740     xmlBufferFree(buff);
       
  1741     return resbuf;
       
  1742 }
       
  1743 
       
  1744 /**
       
  1745  * xmlTextReaderReadString:
       
  1746  * @param reader the xmlTextReaderPtr used
       
  1747  *
       
  1748  * Reads the contents of an element or a text node as a string.
       
  1749  *
       
  1750  * Returns a string containing the contents of the Element or Text node,
       
  1751  *         or NULL if the reader is positioned on any other type of node.
       
  1752  *         The string must be deallocated by the caller.
       
  1753  */
       
  1754 XMLPUBFUNEXPORT xmlChar*
       
  1755 xmlTextReaderReadString(xmlTextReaderPtr reader)
       
  1756 {
       
  1757 	xmlNodePtr node;
       
  1758     if ((reader == NULL) || (reader->node == NULL))
       
  1759        return(NULL);
       
  1760 
       
  1761     node = (reader->curnode != NULL) ? reader->curnode : reader->node;
       
  1762     switch (node->type) {
       
  1763     case XML_TEXT_NODE:
       
  1764        if (node->content != NULL)
       
  1765            return(xmlStrdup(node->content));
       
  1766        break;
       
  1767     case XML_ELEMENT_NODE:
       
  1768     if (xmlTextReaderDoExpand(reader) != -1) {
       
  1769         return xmlTextReaderCollectSiblings(node->children);
       
  1770     }
       
  1771     case XML_ATTRIBUTE_NODE:
       
  1772     TODO
       
  1773     break;
       
  1774     default:
       
  1775        break;
       
  1776     }
       
  1777     return(NULL);
       
  1778 }
       
  1779 
       
  1780 #if 0
       
  1781 /**
       
  1782  * xmlTextReaderReadBase64:
       
  1783  * @param reader the xmlTextReaderPtr used
       
  1784  * @param array a byte array to store the content.
       
  1785  * @param offset the zero-based index into array where the method should
       
  1786  *           begin to write.
       
  1787  * @param len the number of bytes to write.
       
  1788  *
       
  1789  * Reads and decodes the Base64 encoded contents of an element and
       
  1790  * stores the result in a byte buffer.
       
  1791  *
       
  1792  * Returns the number of bytes written to array, or zero if the current
       
  1793  *         instance is not positioned on an element or -1 in case of error.
       
  1794  */
       
  1795 int
       
  1796 xmlTextReaderReadBase64(xmlTextReaderPtr reader,
       
  1797                         unsigned char *array ATTRIBUTE_UNUSED,
       
  1798                         int offset ATTRIBUTE_UNUSED,
       
  1799                         int len ATTRIBUTE_UNUSED) {
       
  1800     if ((reader == NULL) || (reader->ctxt == NULL))
       
  1801         return(-1);
       
  1802     if (reader->ctxt->wellFormed != 1)
       
  1803         return(-1);
       
  1804 
       
  1805     if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
       
  1806         return(0);
       
  1807     TODO
       
  1808     return(0);
       
  1809 }
       
  1810 
       
  1811 /**
       
  1812  * xmlTextReaderReadBinHex:
       
  1813  * @param reader the xmlTextReaderPtr used
       
  1814  * @param array a byte array to store the content.
       
  1815  * @param offset the zero-based index into array where the method should
       
  1816  *           begin to write.
       
  1817  * @param len the number of bytes to write.
       
  1818  *
       
  1819  * Reads and decodes the BinHex encoded contents of an element and
       
  1820  * stores the result in a byte buffer.
       
  1821  *
       
  1822  * Returns the number of bytes written to array, or zero if the current
       
  1823  *         instance is not positioned on an element or -1 in case of error.
       
  1824  */
       
  1825 int
       
  1826 xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
       
  1827                         unsigned char *array ATTRIBUTE_UNUSED,
       
  1828                         int offset ATTRIBUTE_UNUSED,
       
  1829                         int len ATTRIBUTE_UNUSED) {
       
  1830     if ((reader == NULL) || (reader->ctxt == NULL))
       
  1831         return(-1);
       
  1832     if (reader->ctxt->wellFormed != 1)
       
  1833         return(-1);
       
  1834 
       
  1835     if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
       
  1836         return(0);
       
  1837     TODO
       
  1838     return(0);
       
  1839 }
       
  1840 #endif
       
  1841 
       
  1842 /************************************************************************
       
  1843  *                                                                      *
       
  1844  *          Operating on a preparsed tree                               *
       
  1845  *                                                                      *
       
  1846  ************************************************************************/
       
  1847 static int
       
  1848 xmlTextReaderNextTree(xmlTextReaderPtr reader)
       
  1849 {
       
  1850     if (reader == NULL)
       
  1851         return(-1);
       
  1852 
       
  1853     if (reader->state == XML_TEXTREADER_END)
       
  1854         return(0);
       
  1855 
       
  1856     if (reader->node == NULL)
       
  1857     {
       
  1858         if (reader->doc->children == NULL)
       
  1859         {
       
  1860             reader->state = XML_TEXTREADER_END;
       
  1861             return(0);
       
  1862         }
       
  1863 
       
  1864         reader->node = reader->doc->children;
       
  1865         reader->state = XML_TEXTREADER_START;
       
  1866         return(1);
       
  1867     }
       
  1868 
       
  1869     if (reader->state != XML_TEXTREADER_BACKTRACK)
       
  1870     {
       
  1871         if (reader->node->children != 0)
       
  1872         {
       
  1873             reader->node = reader->node->children;
       
  1874             reader->depth++;
       
  1875             reader->state = XML_TEXTREADER_START;
       
  1876             return(1);
       
  1877         }
       
  1878 
       
  1879         if ((reader->node->type == XML_ELEMENT_NODE) ||
       
  1880             (reader->node->type == XML_ATTRIBUTE_NODE))
       
  1881         {
       
  1882             reader->state = XML_TEXTREADER_BACKTRACK;
       
  1883             return(1);
       
  1884         }
       
  1885     }
       
  1886 
       
  1887     if (reader->node->next != 0)
       
  1888     {
       
  1889         reader->node = reader->node->next;
       
  1890         reader->state = XML_TEXTREADER_START;
       
  1891         return(1);
       
  1892     }
       
  1893 
       
  1894     if (reader->node->parent != 0)
       
  1895     {
       
  1896         if (reader->node->parent->type == XML_DOCUMENT_NODE)
       
  1897         {
       
  1898             reader->state = XML_TEXTREADER_END;
       
  1899             return(0);
       
  1900         }
       
  1901 
       
  1902         reader->node = reader->node->parent;
       
  1903         reader->depth--;
       
  1904         reader->state = XML_TEXTREADER_BACKTRACK;
       
  1905         return(1);
       
  1906     }
       
  1907 
       
  1908     reader->state = XML_TEXTREADER_END;
       
  1909 
       
  1910     return(1);
       
  1911 }
       
  1912 
       
  1913 /**
       
  1914  * xmlTextReaderReadTree:
       
  1915  * @param reader the xmlTextReaderPtr used
       
  1916  *
       
  1917  *  Moves the position of the current instance to the next node in
       
  1918  *  the stream, exposing its properties.
       
  1919  *
       
  1920  *  Returns 1 if the node was read successfully, 0 if there is no more
       
  1921  *          nodes to read, or -1 in case of error
       
  1922  */
       
  1923 static int
       
  1924 xmlTextReaderReadTree(xmlTextReaderPtr reader)
       
  1925 {
       
  1926     if (reader->state == XML_TEXTREADER_END)
       
  1927         return(0);
       
  1928 
       
  1929 next_node:
       
  1930     if (reader->node == NULL)
       
  1931     {
       
  1932         if (reader->doc->children == NULL)
       
  1933         {
       
  1934             reader->state = XML_TEXTREADER_END;
       
  1935             return(0);
       
  1936         }
       
  1937 
       
  1938         reader->node = reader->doc->children;
       
  1939         reader->state = XML_TEXTREADER_START;
       
  1940         goto found_node;
       
  1941     }
       
  1942 
       
  1943     if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
       
  1944         (reader->node->type != XML_DTD_NODE) &&
       
  1945         (reader->node->type != XML_XINCLUDE_START) &&
       
  1946         (reader->node->type != XML_ENTITY_REF_NODE))
       
  1947     {
       
  1948         if (reader->node->children != NULL)
       
  1949         {
       
  1950             reader->node = reader->node->children;
       
  1951             reader->depth++;
       
  1952             reader->state = XML_TEXTREADER_START;
       
  1953             goto found_node;
       
  1954         }
       
  1955 
       
  1956         if (reader->node->type == XML_ATTRIBUTE_NODE)
       
  1957         {
       
  1958             reader->state = XML_TEXTREADER_BACKTRACK;
       
  1959             goto found_node;
       
  1960         }
       
  1961     }
       
  1962 
       
  1963     if (reader->node->next != NULL)
       
  1964     {
       
  1965         reader->node = reader->node->next;
       
  1966         reader->state = XML_TEXTREADER_START;
       
  1967         goto found_node;
       
  1968     }
       
  1969 
       
  1970     if (reader->node->parent != NULL)
       
  1971     {
       
  1972         if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
       
  1973             (reader->node->parent->type == XML_HTML_DOCUMENT_NODE))
       
  1974         {
       
  1975             reader->state = XML_TEXTREADER_END;
       
  1976             return(0);
       
  1977         }
       
  1978 
       
  1979         reader->node = reader->node->parent;
       
  1980         reader->depth--;
       
  1981         reader->state = XML_TEXTREADER_BACKTRACK;
       
  1982         goto found_node;
       
  1983     }
       
  1984 
       
  1985     reader->state = XML_TEXTREADER_END;
       
  1986 
       
  1987 found_node:
       
  1988     if ((reader->node->type == XML_XINCLUDE_START) ||
       
  1989         (reader->node->type == XML_XINCLUDE_END))
       
  1990     {
       
  1991         goto next_node;
       
  1992     }
       
  1993     return(1);
       
  1994 }
       
  1995 
       
  1996 /**
       
  1997  * xmlTextReaderNextSibling:
       
  1998  * @param reader the xmlTextReaderPtr used
       
  1999  *
       
  2000  * Skip to the node following the current one in document order while
       
  2001  * avoiding the subtree if any.
       
  2002  * Currently implemented only for Readers built on a document
       
  2003  *
       
  2004  * Returns 1 if the node was read successfully, 0 if there is no more
       
  2005  *          nodes to read, or -1 in case of error
       
  2006  */
       
  2007 XMLPUBFUNEXPORT int
       
  2008 xmlTextReaderNextSibling(xmlTextReaderPtr reader)
       
  2009 {
       
  2010     if (reader == NULL)
       
  2011         return(-1);
       
  2012     if (reader->doc == NULL)
       
  2013     {
       
  2014         
       
  2015         return(-1);
       
  2016     }
       
  2017 
       
  2018     if (reader->state == XML_TEXTREADER_END)
       
  2019         return(0);
       
  2020 
       
  2021     if (reader->node == NULL)
       
  2022         return(xmlTextReaderNextTree(reader));
       
  2023 
       
  2024     if (reader->node->next != NULL)
       
  2025     {
       
  2026         reader->node = reader->node->next;
       
  2027         reader->state = XML_TEXTREADER_START;
       
  2028         return(1);
       
  2029     }
       
  2030 
       
  2031     return(0);
       
  2032 }
       
  2033 
       
  2034 /************************************************************************
       
  2035  *                                                                      *
       
  2036  *          Constructor and destructors                                 *
       
  2037  *                                                                      *
       
  2038  ************************************************************************/
       
  2039 /**
       
  2040  * xmlNewTextReader:
       
  2041  * @param input the xmlParserInputBufferPtr used to read data
       
  2042  * @param URI the URI information for the source if available
       
  2043  *
       
  2044  * Create an xmlTextReader structure fed with input
       
  2045  *
       
  2046  * Returns the new xmlTextReaderPtr or NULL in case of error
       
  2047  */
       
  2048 XMLPUBFUNEXPORT xmlTextReaderPtr
       
  2049 xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI)
       
  2050 {
       
  2051     xmlTextReaderPtr ret;
       
  2052 
       
  2053     if (input == NULL)
       
  2054         return(NULL);
       
  2055     ret = (xmlTextReaderPtr) xmlMalloc(sizeof(xmlTextReader));
       
  2056     if (!ret) {
       
  2057         xmlGenericError(xmlGenericErrorContext,
       
  2058                 EMBED_ERRTXT("xmlNewTextReader : malloc failed\n"));
       
  2059         return(NULL);
       
  2060     }
       
  2061     memset(ret, 0, sizeof(xmlTextReader));
       
  2062     //ret->doc = NULL; // Here and below: after memset, setting to 0 (NULL) is not needed, so removed
       
  2063     //ret->entTab = NULL;
       
  2064     //ret->entMax = 0;
       
  2065     //ret->entNr = 0;
       
  2066     ret->input = input;
       
  2067     ret->buffer = xmlBufferCreateSize(100);
       
  2068     if (ret->buffer == NULL) {
       
  2069         xmlFree(ret);
       
  2070         xmlGenericError(xmlGenericErrorContext,
       
  2071         "xmlNewTextReader : malloc failed\n");
       
  2072         return(NULL);
       
  2073     }
       
  2074     ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
       
  2075     if (!ret->sax) {
       
  2076         xmlBufferFree(ret->buffer);
       
  2077         xmlFree(ret);
       
  2078         xmlGenericError(xmlGenericErrorContext,
       
  2079                 EMBED_ERRTXT("xmlNewTextReader : malloc failed\n"));
       
  2080         return(NULL);
       
  2081     }
       
  2082     // Set DOM's default callbacks for SAX stream, and then replace with own Reader's callbacks;
       
  2083     // DOM's callbacks are stored in this->{saxEvent} field for later use.
       
  2084     xmlSAXVersion(ret->sax, 2);
       
  2085     ret->startElement = ret->sax->startElement;
       
  2086     ret->sax->startElement = xmlTextReaderStartElement;
       
  2087     ret->endElement = ret->sax->endElement;
       
  2088     ret->sax->endElement = xmlTextReaderEndElement;
       
  2089 #ifdef LIBXML_SAX1_ENABLED
       
  2090     if (ret->sax->initialized == XML_SAX2_MAGIC) {
       
  2091 #endif /* LIBXML_SAX1_ENABLED */
       
  2092         ret->startElementNs = ret->sax->startElementNs;
       
  2093         ret->sax->startElementNs = xmlTextReaderStartElementNs;
       
  2094         ret->endElementNs = ret->sax->endElementNs;
       
  2095         ret->sax->endElementNs = xmlTextReaderEndElementNs;
       
  2096 #ifdef LIBXML_SAX1_ENABLED
       
  2097     } else {
       
  2098         ret->startElementNs = NULL;
       
  2099         ret->endElementNs = NULL;
       
  2100     }
       
  2101 #endif /* LIBXML_SAX1_ENABLED */
       
  2102     ret->characters = ret->sax->characters;
       
  2103     ret->sax->characters = xmlTextReaderCharacters;
       
  2104     ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
       
  2105     ret->cdataBlock = ret->sax->cdataBlock;
       
  2106     ret->sax->cdataBlock = xmlTextReaderCDataBlock;
       
  2107 
       
  2108     ret->mode = XML_TEXTREADER_MODE_INITIAL;
       
  2109     //ret->node = NULL;
       
  2110     //ret->curnode = NULL;
       
  2111     if (ret->input->buffer->use < 4) {
       
  2112         xmlParserInputBufferRead(input, 4);
       
  2113     }
       
  2114     if (ret->input->buffer->use >= 4) {
       
  2115         ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
       
  2116                         (const char *) ret->input->buffer->content, 4, URI);
       
  2117         //ret->base = 0;
       
  2118         ret->cur = 4;
       
  2119     } else {
       
  2120         ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
       
  2121         //ret->base = 0;
       
  2122         //ret->cur = 0;
       
  2123     }
       
  2124     if (!ret->ctxt) {
       
  2125         xmlGenericError(xmlGenericErrorContext,
       
  2126         EMBED_ERRTXT("xmlNewTextReader : malloc failed\n"));
       
  2127         xmlBufferFree(ret->buffer);
       
  2128         xmlFree(ret->sax);
       
  2129         xmlFree(ret);
       
  2130         return(NULL);
       
  2131     }
       
  2132     
       
  2133     //ret->ctxt->parseMode = XML_PARSE_READER;
       
  2134     // "user data" of the XML parser context is pointer to this xmlTextReader
       
  2135     // the parser context will be provided during calls to each of SAX callbacks.
       
  2136     ret->ctxt->_private = ret;
       
  2137 #ifdef LIBXML_ENABLE_NODE_LINEINFO
       
  2138     ret->ctxt->linenumbers = 1;
       
  2139 #endif
       
  2140     // make SAX parser store name strings in dictionary
       
  2141     ret->ctxt->dictNames = 1;
       
  2142     ret->allocs = XML_TEXTREADER_CTXT;
       
  2143     /*
       
  2144      * use the parser dictionnary to allocate all elements and attributes names
       
  2145      */ 
       
  2146     ret->ctxt->docdict = 1;
       
  2147     ret->dict = ret->ctxt->dict;
       
  2148 #ifdef LIBXML_XINCLUDE_ENABLED
       
  2149     //ret->xinclude = 0;
       
  2150 #endif
       
  2151 #ifdef LIBXML_PATTERN_ENABLED
       
  2152     //ret->patternMax = 0;
       
  2153     //ret->patternTab = NULL;
       
  2154 #endif
       
  2155     return(ret);
       
  2156 }
       
  2157 
       
  2158 /**
       
  2159  * xmlNewTextReaderFilename:
       
  2160  * @param URI the URI of the resource to process
       
  2161  *
       
  2162  * Create an xmlTextReader structure fed with the resource at URI
       
  2163  *
       
  2164  * Returns the new xmlTextReaderPtr or NULL in case of error
       
  2165  */
       
  2166 XMLPUBFUNEXPORT xmlTextReaderPtr
       
  2167 xmlNewTextReaderFilename(const char *URI)
       
  2168 {
       
  2169     xmlParserInputBufferPtr input;
       
  2170     xmlTextReaderPtr ret;
       
  2171     // Note:  'directory' variable was removed and function body changed (optimized)
       
  2172 
       
  2173     input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
       
  2174     if (!input)
       
  2175         return(NULL);
       
  2176 
       
  2177     ret = xmlNewTextReader(input, URI);
       
  2178     if (!ret) {
       
  2179         xmlFreeParserInputBuffer(input);
       
  2180         return(NULL);
       
  2181     }
       
  2182 
       
  2183     ret->allocs |= XML_TEXTREADER_INPUT;
       
  2184     if (!ret->ctxt->directory)
       
  2185         ret->ctxt->directory = xmlParserGetDirectory(URI);
       
  2186 
       
  2187     return(ret);
       
  2188 }
       
  2189 
       
  2190 /**
       
  2191  * xmlFreeTextReader:
       
  2192  * @param reader the xmlTextReaderPtr
       
  2193  *
       
  2194  * Deallocate all the resources associated to the reader
       
  2195  */
       
  2196 XMLPUBFUNEXPORT void
       
  2197 xmlFreeTextReader(xmlTextReaderPtr reader)
       
  2198 {
       
  2199     if (reader == NULL)
       
  2200         return;
       
  2201 #ifdef LIBXML_SCHEMAS_ENABLED
       
  2202     if (reader->rngSchemas != NULL) {
       
  2203         xmlRelaxNGFree(reader->rngSchemas);
       
  2204         reader->rngSchemas = NULL;
       
  2205     }
       
  2206     if (reader->rngValidCtxt != NULL) {
       
  2207         xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
       
  2208         reader->rngValidCtxt = NULL;
       
  2209     }
       
  2210     if (reader->xsdPlug != NULL) {
       
  2211         xmlSchemaSAXUnplug(reader->xsdPlug);
       
  2212         reader->xsdPlug = NULL;
       
  2213     }
       
  2214     if (reader->xsdValidCtxt != NULL) {
       
  2215         xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
       
  2216         reader->xsdValidCtxt = NULL;
       
  2217     }
       
  2218     if (reader->xsdSchemas != NULL) {
       
  2219         xmlSchemaFree(reader->xsdSchemas);
       
  2220         reader->xsdSchemas = NULL;
       
  2221     }
       
  2222 #endif
       
  2223 #ifdef LIBXML_XINCLUDE_ENABLED
       
  2224     if (reader->xincctxt != NULL)
       
  2225         xmlXIncludeFreeContext(reader->xincctxt);
       
  2226 #endif
       
  2227 #ifdef LIBXML_PATTERN_ENABLED
       
  2228     if (reader->patternTab != NULL) {
       
  2229         int i;
       
  2230         for (i = 0;i < reader->patternNr;i++) {
       
  2231             if (reader->patternTab[i] != NULL)
       
  2232                 xmlFreePattern(reader->patternTab[i]);
       
  2233         }
       
  2234         xmlFree(reader->patternTab);
       
  2235     }
       
  2236 #endif
       
  2237     if (reader->ctxt != NULL) {
       
  2238         if (reader->dict == reader->ctxt->dict)
       
  2239             reader->dict = NULL;
       
  2240         if (reader->ctxt->myDoc != NULL) {
       
  2241             if (reader->preserve == 0)
       
  2242                 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
       
  2243             reader->ctxt->myDoc = NULL;
       
  2244         }
       
  2245         if ((reader->ctxt->vctxt.vstateTab != NULL) &&
       
  2246             (reader->ctxt->vctxt.vstateMax > 0)){
       
  2247             xmlFree(reader->ctxt->vctxt.vstateTab);
       
  2248             reader->ctxt->vctxt.vstateTab = NULL;
       
  2249             reader->ctxt->vctxt.vstateMax = 0;
       
  2250         }
       
  2251         if (reader->allocs & XML_TEXTREADER_CTXT)
       
  2252             xmlFreeParserCtxt(reader->ctxt);
       
  2253     }
       
  2254     if (reader->sax != NULL)
       
  2255         xmlFree(reader->sax);
       
  2256     if ((reader->input != NULL)  && (reader->allocs & XML_TEXTREADER_INPUT))
       
  2257         xmlFreeParserInputBuffer(reader->input);
       
  2258     if (reader->faketext != NULL) {
       
  2259         xmlFreeNode(reader->faketext);
       
  2260     }
       
  2261     if (reader->buffer != NULL)
       
  2262         xmlBufferFree(reader->buffer);
       
  2263     if (reader->entTab != NULL)
       
  2264         xmlFree(reader->entTab);
       
  2265     if (reader->dict != NULL)
       
  2266         xmlDictFree(reader->dict);
       
  2267     xmlFree(reader);
       
  2268 }
       
  2269 
       
  2270 /************************************************************************
       
  2271  *                                                                      *
       
  2272  *          Methods for XmlTextReader                                   *
       
  2273  *                                                                      *
       
  2274  ************************************************************************/
       
  2275 /**
       
  2276  * xmlTextReaderClose:
       
  2277  * @param reader the xmlTextReaderPtr used
       
  2278  *
       
  2279  * This method releases any resources allocated by the current instance
       
  2280  * changes the state to Closed and close any underlying input.
       
  2281  *
       
  2282  * Returns 0 or -1 in case of error
       
  2283  */
       
  2284 XMLPUBFUNEXPORT int
       
  2285 xmlTextReaderClose(xmlTextReaderPtr reader) {
       
  2286     if (reader == NULL)
       
  2287         return(-1);
       
  2288     reader->node = NULL;
       
  2289     reader->curnode = NULL;
       
  2290     reader->mode = XML_TEXTREADER_MODE_CLOSED;
       
  2291     if (reader->ctxt != NULL) {
       
  2292         xmlStopParser(reader->ctxt);
       
  2293         if (reader->ctxt->myDoc != NULL) {
       
  2294             if (reader->preserve == 0)
       
  2295                 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
       
  2296             reader->ctxt->myDoc = NULL;
       
  2297         }
       
  2298     }
       
  2299     if ((reader->input != NULL)  && (reader->allocs & XML_TEXTREADER_INPUT)) {
       
  2300         xmlFreeParserInputBuffer(reader->input);
       
  2301         reader->allocs -= XML_TEXTREADER_INPUT;
       
  2302     }
       
  2303     return(0);
       
  2304 }
       
  2305 
       
  2306 /**
       
  2307  * xmlTextReaderGetAttributeNo:
       
  2308  * @param reader the xmlTextReaderPtr used
       
  2309  * @param no the zero-based index of the attribute relative to the containing element
       
  2310  *
       
  2311  * Provides the value of the attribute with the specified index relative
       
  2312  * to the containing element.
       
  2313  *
       
  2314  * Returns a string containing the value of the specified attribute, or NULL
       
  2315  *    in case of error. The string must be deallocated by the caller.
       
  2316  */
       
  2317 XMLPUBFUNEXPORT xmlChar *
       
  2318 xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
       
  2319     xmlChar *ret;
       
  2320     int i;
       
  2321     xmlAttrPtr cur;
       
  2322     xmlNsPtr ns;
       
  2323 
       
  2324     if (reader == NULL)
       
  2325         return(NULL);
       
  2326     if (reader->node == NULL)
       
  2327         return(NULL);
       
  2328     if (reader->curnode != NULL)
       
  2329         return(NULL);
       
  2330     
       
  2331     if (reader->node->type != XML_ELEMENT_NODE)
       
  2332         return(NULL);
       
  2333 
       
  2334     ns = reader->node->nsDef;
       
  2335     for (i = 0;(i < no) && (ns != NULL);i++) {
       
  2336         ns = ns->next;
       
  2337     }
       
  2338     if (ns != NULL)
       
  2339         return(xmlStrdup(ns->href));
       
  2340 
       
  2341     cur = reader->node->properties;
       
  2342     if (cur == NULL)
       
  2343         return(NULL);
       
  2344     for (;i < no;i++) {
       
  2345         cur = cur->next;
       
  2346         if (cur == NULL)
       
  2347             return(NULL);
       
  2348     }
       
  2349     
       
  2350 
       
  2351     ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
       
  2352     if (ret == NULL)
       
  2353         return(xmlStrdup((xmlChar *)""));
       
  2354     return(ret);
       
  2355 }
       
  2356 
       
  2357 /**
       
  2358  * xmlTextReaderGetAttribute:
       
  2359  * @param reader the xmlTextReaderPtr used
       
  2360  * @param name the qualified name of the attribute.
       
  2361  *
       
  2362  * Provides the value of the attribute with the specified qualified name.
       
  2363  *
       
  2364  * Returns a string containing the value of the specified attribute, or NULL
       
  2365  *    in case of error. The string must be deallocated by the caller.
       
  2366  */
       
  2367 XMLPUBFUNEXPORT xmlChar *
       
  2368 xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
       
  2369     xmlChar *prefix = NULL;
       
  2370     xmlChar *localname;
       
  2371     xmlNsPtr ns;
       
  2372     xmlChar *ret = NULL;
       
  2373 
       
  2374     if ((reader == NULL) || (name == NULL))
       
  2375         return(NULL);
       
  2376     if (reader->node == NULL)
       
  2377         return(NULL);
       
  2378     if (reader->curnode != NULL)
       
  2379         return(NULL);
       
  2380 
       
  2381     
       
  2382     if (reader->node->type != XML_ELEMENT_NODE)
       
  2383         return(NULL);
       
  2384 
       
  2385     localname = xmlSplitQName2(name, &prefix);
       
  2386     if (localname == NULL) {
       
  2387         /*
       
  2388          * Namespace default decl
       
  2389          */
       
  2390         if (xmlStrEqual(name, BAD_CAST "xmlns")) {
       
  2391             ns = reader->node->nsDef;
       
  2392             while (ns != NULL) {
       
  2393                 if (ns->prefix == NULL) {
       
  2394                     return(xmlStrdup(ns->href));
       
  2395                 }
       
  2396                 ns = ns->next;
       
  2397             }
       
  2398             return NULL;
       
  2399         }
       
  2400         return(xmlGetNoNsProp(reader->node, name));
       
  2401     }
       
  2402 
       
  2403     /*
       
  2404      * Namespace default decl
       
  2405      */
       
  2406     if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
       
  2407         ns = reader->node->nsDef;
       
  2408         while (ns != NULL) {
       
  2409             if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
       
  2410                 ret = xmlStrdup(ns->href);
       
  2411                 break;
       
  2412             }
       
  2413             ns = ns->next;
       
  2414         }
       
  2415     } else {
       
  2416         ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
       
  2417         if (ns != NULL)
       
  2418             ret = xmlGetNsProp(reader->node, localname, ns->href);
       
  2419     }
       
  2420 
       
  2421     xmlFree(localname);
       
  2422     if (prefix != NULL)
       
  2423         xmlFree(prefix);
       
  2424     return(ret);
       
  2425 }
       
  2426 
       
  2427 
       
  2428 /**
       
  2429  * xmlTextReaderGetAttributeNs:
       
  2430  * @param reader the xmlTextReaderPtr used
       
  2431  * @param localName the local name of the attribute.
       
  2432  * @param namespaceURI the namespace URI of the attribute.
       
  2433  *
       
  2434  * Provides the value of the specified attribute
       
  2435  *
       
  2436  * Returns a string containing the value of the specified attribute, or NULL
       
  2437  *    in case of error. The string must be deallocated by the caller.
       
  2438  */
       
  2439 XMLPUBFUNEXPORT xmlChar *
       
  2440 xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
       
  2441                             const xmlChar *namespaceURI) {
       
  2442     xmlChar *prefix = NULL;
       
  2443     xmlNsPtr ns;
       
  2444     if ((reader == NULL) || (localName == NULL))
       
  2445         return(NULL);
       
  2446     if (reader->node == NULL)
       
  2447         return(NULL);
       
  2448     if (reader->curnode != NULL)
       
  2449         return(NULL);
       
  2450 
       
  2451     
       
  2452     if (reader->node->type != XML_ELEMENT_NODE)
       
  2453         return(NULL);
       
  2454 
       
  2455     if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
       
  2456         if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
       
  2457             prefix = BAD_CAST localName;
       
  2458         }
       
  2459         ns = reader->node->nsDef;
       
  2460         while (ns != NULL) {
       
  2461             if ((prefix == NULL && ns->prefix == NULL) ||
       
  2462                 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
       
  2463                 return xmlStrdup(ns->href);
       
  2464             }
       
  2465             ns = ns->next;
       
  2466         }
       
  2467         return NULL;
       
  2468     }
       
  2469 
       
  2470     return(xmlGetNsProp(reader->node, localName, namespaceURI));
       
  2471 }
       
  2472 
       
  2473 /**
       
  2474  * xmlTextReaderGetRemainder:
       
  2475  * @param reader the xmlTextReaderPtr used
       
  2476  *
       
  2477  * Method to get the remainder of the buffered XML. this method stops the
       
  2478  * parser, set its state to End Of File and return the input stream with
       
  2479  * what is left that the parser did not use.
       
  2480  *
       
  2481  * The implementation is not good, the parser certainly progressed past
       
  2482  * what's left in reader->input, and there is an allocation problem. Best
       
  2483  * would be to rewrite it differently.
       
  2484  *
       
  2485  * Returns the xmlParserInputBufferPtr attached to the XML or NULL
       
  2486  *    in case of error.
       
  2487  */ 
       
  2488 XMLPUBFUNEXPORT xmlParserInputBufferPtr
       
  2489 xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
       
  2490     xmlParserInputBufferPtr ret = NULL;
       
  2491 
       
  2492     if (reader == NULL)
       
  2493         return(NULL);
       
  2494     if (reader->node == NULL)
       
  2495         return(NULL);
       
  2496 
       
  2497     reader->node = NULL;
       
  2498     reader->curnode = NULL;
       
  2499     reader->mode = XML_TEXTREADER_MODE_EOF;
       
  2500     if (reader->ctxt != NULL) {
       
  2501         xmlStopParser(reader->ctxt);
       
  2502         if (reader->ctxt->myDoc != NULL) {
       
  2503             if (reader->preserve == 0)
       
  2504                 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
       
  2505             reader->ctxt->myDoc = NULL;
       
  2506         }
       
  2507     }
       
  2508     if (reader->allocs & XML_TEXTREADER_INPUT) {
       
  2509         ret = reader->input;
       
  2510         reader->input = NULL;
       
  2511         reader->allocs -= XML_TEXTREADER_INPUT;
       
  2512     } else {
       
  2513         /*
       
  2514          * Hum, one may need to duplicate the data structure because
       
  2515          * without reference counting the input may be freed twice:
       
  2516          *   - by the layer which allocated it.
       
  2517          *   - by the layer to which would have been returned to.
       
  2518          */
       
  2519         TODO
       
  2520         return(NULL);
       
  2521     }
       
  2522     return(ret);
       
  2523 }
       
  2524 
       
  2525 /**
       
  2526  * xmlTextReaderLookupNamespace:
       
  2527  * @param reader the xmlTextReaderPtr used
       
  2528  * @param prefix the prefix whose namespace URI is to be resolved. To return
       
  2529  *          the default namespace, specify NULL
       
  2530  *
       
  2531  * Resolves a namespace prefix in the scope of the current element.
       
  2532  *
       
  2533  * Returns a string containing the namespace URI to which the prefix maps
       
  2534  *    or NULL in case of error. The string must be deallocated by the caller.
       
  2535  */
       
  2536 XMLPUBFUNEXPORT xmlChar *
       
  2537 xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
       
  2538     xmlNsPtr ns;
       
  2539 
       
  2540     if (reader == NULL)
       
  2541         return(NULL);
       
  2542     if (reader->node == NULL)
       
  2543         return(NULL);
       
  2544 
       
  2545     ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
       
  2546     if (ns == NULL)
       
  2547         return(NULL);
       
  2548     return(xmlStrdup(ns->href));
       
  2549 }
       
  2550 
       
  2551 /**
       
  2552  * xmlTextReaderMoveToAttributeNo:
       
  2553  * @param reader the xmlTextReaderPtr used
       
  2554  * @param no the zero-based index of the attribute relative to the containing
       
  2555  *      element.
       
  2556  *
       
  2557  * Moves the position of the current instance to the attribute with
       
  2558  * the specified index relative to the containing element.
       
  2559  *
       
  2560  * Returns 1 in case of success, -1 in case of error, 0 if not found
       
  2561  */
       
  2562 XMLPUBFUNEXPORT int
       
  2563 xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
       
  2564     int i;
       
  2565     xmlAttrPtr cur;
       
  2566     xmlNsPtr ns;
       
  2567 
       
  2568     if (reader == NULL)
       
  2569         return(-1);
       
  2570     if (reader->node == NULL)
       
  2571         return(-1);
       
  2572     
       
  2573     if (reader->node->type != XML_ELEMENT_NODE)
       
  2574         return(-1);
       
  2575 
       
  2576     reader->curnode = NULL;
       
  2577 
       
  2578     ns = reader->node->nsDef;
       
  2579     for (i = 0;(i < no) && (ns != NULL);i++) {
       
  2580         ns = ns->next;
       
  2581     }
       
  2582     if (ns != NULL) {
       
  2583         reader->curnode = (xmlNodePtr) ns;
       
  2584         return(1);
       
  2585     }
       
  2586 
       
  2587     cur = reader->node->properties;
       
  2588     if (cur == NULL)
       
  2589         return(0);
       
  2590     for (;i < no;i++) {
       
  2591         cur = cur->next;
       
  2592         if (cur == NULL)
       
  2593             return(0);
       
  2594     }
       
  2595     
       
  2596 
       
  2597     reader->curnode = (xmlNodePtr) cur;
       
  2598     return(1);
       
  2599 }
       
  2600 
       
  2601 /**
       
  2602  * xmlTextReaderMoveToAttribute:
       
  2603  * @param reader the xmlTextReaderPtr used
       
  2604  * @param name the qualified name of the attribute.
       
  2605  *
       
  2606  * Moves the position of the current instance to the attribute with
       
  2607  * the specified qualified name.
       
  2608  *
       
  2609  * Returns 1 in case of success, -1 in case of error, 0 if not found
       
  2610  */
       
  2611 XMLPUBFUNEXPORT int
       
  2612 xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar* name)
       
  2613 {
       
  2614     xmlChar *prefix = NULL;
       
  2615     xmlChar *localname;
       
  2616     xmlNsPtr ns;
       
  2617     xmlAttrPtr prop;
       
  2618 
       
  2619     if ((reader == NULL) || (name == NULL))
       
  2620         return(-1);
       
  2621     if (reader->node == NULL)
       
  2622         return(-1);
       
  2623 
       
  2624     
       
  2625     if (reader->node->type != XML_ELEMENT_NODE)
       
  2626         return(0);
       
  2627 
       
  2628     localname = xmlSplitQName2(name, &prefix);
       
  2629     if (localname == NULL) {
       
  2630         /*
       
  2631          * Namespace default decl
       
  2632          */
       
  2633         if (xmlStrEqual(name, BAD_CAST "xmlns")) {
       
  2634             ns = reader->node->nsDef;
       
  2635             while (ns != NULL) {
       
  2636                 if (ns->prefix == NULL) {
       
  2637                     reader->curnode = (xmlNodePtr) ns;
       
  2638                     return(1);
       
  2639                 }
       
  2640                 ns = ns->next;
       
  2641             }
       
  2642             return(0);
       
  2643         }
       
  2644 
       
  2645         prop = reader->node->properties;
       
  2646         while (prop != NULL) {
       
  2647             /*
       
  2648              * One need to have
       
  2649              *   - same attribute names
       
  2650              *   - and the attribute carrying that namespace
       
  2651              */
       
  2652             if ((xmlStrEqual(prop->name, name)) &&
       
  2653                 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
       
  2654                 reader->curnode = (xmlNodePtr) prop;
       
  2655                 return(1);
       
  2656             }
       
  2657             prop = prop->next;
       
  2658         }
       
  2659         return(0);
       
  2660     }
       
  2661 
       
  2662     /*
       
  2663      * Namespace default decl
       
  2664      */
       
  2665     if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
       
  2666         ns = reader->node->nsDef;
       
  2667         while (ns != NULL) {
       
  2668             if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
       
  2669                 reader->curnode = (xmlNodePtr) ns;
       
  2670                 goto found;
       
  2671             }
       
  2672             ns = ns->next;
       
  2673         }
       
  2674         goto not_found;
       
  2675     }
       
  2676     prop = reader->node->properties;
       
  2677     while (prop != NULL) {
       
  2678         /*
       
  2679          * One need to have
       
  2680          *   - same attribute names
       
  2681          *   - and the attribute carrying that namespace
       
  2682          */
       
  2683         if ((xmlStrEqual(prop->name, localname)) &&
       
  2684             (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix)))
       
  2685     	{
       
  2686             reader->curnode = (xmlNodePtr) prop;
       
  2687             goto found;
       
  2688         }
       
  2689         prop = prop->next;
       
  2690     }
       
  2691 not_found:
       
  2692     if (localname != NULL)
       
  2693         xmlFree(localname);
       
  2694     if (prefix != NULL)
       
  2695         xmlFree(prefix);
       
  2696     return(0);
       
  2697 
       
  2698 found:
       
  2699     if (localname != NULL)
       
  2700         xmlFree(localname);
       
  2701     if (prefix != NULL)
       
  2702         xmlFree(prefix);
       
  2703     return(1);
       
  2704 }
       
  2705 
       
  2706 /**
       
  2707  * xmlTextReaderMoveToAttributeNs:
       
  2708  * @param reader the xmlTextReaderPtr used
       
  2709  * @param localName the local name of the attribute.
       
  2710  * @param namespaceURI the namespace URI of the attribute.
       
  2711  *
       
  2712  * Moves the position of the current instance to the attribute with the
       
  2713  * specified local name and namespace URI.
       
  2714  *
       
  2715  * Returns 1 in case of success, -1 in case of error, 0 if not found
       
  2716  */
       
  2717 XMLPUBFUNEXPORT int
       
  2718 xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
       
  2719     const xmlChar *localName, const xmlChar *namespaceURI)
       
  2720 {
       
  2721     xmlAttrPtr prop;
       
  2722     xmlNodePtr node;
       
  2723     xmlNsPtr ns;
       
  2724     xmlChar *prefix = NULL;
       
  2725 
       
  2726     if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
       
  2727         return(-1);
       
  2728     if (reader->node == NULL)
       
  2729         return(-1);
       
  2730     if (reader->node->type != XML_ELEMENT_NODE)
       
  2731         return(0);
       
  2732     node = reader->node;
       
  2733 
       
  2734     if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
       
  2735         if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
       
  2736             prefix = BAD_CAST localName;
       
  2737         }
       
  2738         ns = reader->node->nsDef;
       
  2739         while (ns != NULL) {
       
  2740             if ((prefix == NULL && ns->prefix == NULL) ||
       
  2741                 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
       
  2742                 reader->curnode = (xmlNodePtr) ns;
       
  2743                 return(1);
       
  2744             }
       
  2745             ns = ns->next;
       
  2746         }
       
  2747         return(0);
       
  2748     }
       
  2749 
       
  2750     prop = node->properties;
       
  2751     while (prop != NULL)
       
  2752     {
       
  2753         /*
       
  2754          * One need to have
       
  2755          *   - same attribute names
       
  2756          *   - and the attribute carrying that namespace
       
  2757          */
       
  2758         if (xmlStrEqual(prop->name, localName) &&
       
  2759             ((prop->ns != NULL) &&
       
  2760             (xmlStrEqual(prop->ns->href, namespaceURI))))
       
  2761         {
       
  2762             reader->curnode = (xmlNodePtr) prop;
       
  2763             return(1);
       
  2764         }
       
  2765         prop = prop->next;
       
  2766     }
       
  2767     return(0);
       
  2768 }
       
  2769 
       
  2770 /**
       
  2771  * xmlTextReaderMoveToFirstAttribute:
       
  2772  * @param reader the xmlTextReaderPtr used
       
  2773  *
       
  2774  * Moves the position of the current instance to the first attribute
       
  2775  * associated with the current node.
       
  2776  *
       
  2777  * Returns 1 in case of success, -1 in case of error, 0 if not found
       
  2778  */
       
  2779 XMLPUBFUNEXPORT int
       
  2780 xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader)
       
  2781 {
       
  2782     if (reader == NULL)
       
  2783         return(-1);
       
  2784     if (reader->node == NULL)
       
  2785         return(-1);
       
  2786     if (reader->node->type != XML_ELEMENT_NODE)
       
  2787         return(0);
       
  2788 
       
  2789     if (reader->node->nsDef != NULL) {
       
  2790         reader->curnode = (xmlNodePtr) reader->node->nsDef;
       
  2791         return(1);
       
  2792     }
       
  2793     if (reader->node->properties != NULL) {
       
  2794         reader->curnode = (xmlNodePtr) reader->node->properties;
       
  2795         return(1);
       
  2796     }
       
  2797     return(0);
       
  2798 }
       
  2799 
       
  2800 /**
       
  2801  * xmlTextReaderMoveToNextAttribute:
       
  2802  * @param reader the xmlTextReaderPtr used
       
  2803  *
       
  2804  * Moves the position of the current instance to the next attribute
       
  2805  * associated with the current node.
       
  2806  *
       
  2807  * Returns 1 in case of success, -1 in case of error, 0 if not found
       
  2808  */
       
  2809 XMLPUBFUNEXPORT int
       
  2810 xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader)
       
  2811 {
       
  2812     if (reader == NULL)
       
  2813         return(-1);
       
  2814     if (reader->node == NULL)
       
  2815         return(-1);
       
  2816     if (reader->node->type != XML_ELEMENT_NODE)
       
  2817         return(0);
       
  2818     if (reader->curnode == NULL)
       
  2819         return(xmlTextReaderMoveToFirstAttribute(reader));
       
  2820 
       
  2821     if (reader->curnode->type == XML_NAMESPACE_DECL)
       
  2822     {
       
  2823         xmlNsPtr ns = (xmlNsPtr) reader->curnode;
       
  2824         if (ns->next != NULL) {
       
  2825             reader->curnode = (xmlNodePtr) ns->next;
       
  2826             return(1);
       
  2827         }
       
  2828         if (reader->node->properties != NULL) {
       
  2829             reader->curnode = (xmlNodePtr) reader->node->properties;
       
  2830             return(1);
       
  2831         }
       
  2832         //return(0);
       
  2833     }
       
  2834     else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
       
  2835                (reader->curnode->next != NULL))
       
  2836     {
       
  2837         reader->curnode = reader->curnode->next;
       
  2838         return(1);
       
  2839     }
       
  2840     return(0);
       
  2841 }
       
  2842 
       
  2843 /**
       
  2844  * xmlTextReaderMoveToElement:
       
  2845  * @param reader the xmlTextReaderPtr used
       
  2846  *
       
  2847  * Moves the position of the current instance to the node that
       
  2848  * contains the current Attribute  node.
       
  2849  *
       
  2850  * Returns 1 in case of success, -1 in case of error, 0 if not moved
       
  2851  */
       
  2852 XMLPUBFUNEXPORT int
       
  2853 xmlTextReaderMoveToElement(xmlTextReaderPtr reader)
       
  2854 {
       
  2855     if (reader == NULL)
       
  2856         return(-1);
       
  2857     if (reader->node == NULL)
       
  2858         return(-1);
       
  2859     if (reader->node->type != XML_ELEMENT_NODE)
       
  2860         return(0);
       
  2861     if (reader->curnode != NULL) {
       
  2862         reader->curnode = NULL;
       
  2863         return(1);
       
  2864     }
       
  2865     return(0);
       
  2866 }
       
  2867 
       
  2868 /**
       
  2869  * xmlTextReaderReadAttributeValue:
       
  2870  * @param reader the xmlTextReaderPtr used
       
  2871  *
       
  2872  * Parses an attribute value into one or more Text and EntityReference nodes.
       
  2873  *
       
  2874  * Returns 1 in case of success, 0 if the reader was not positionned on an
       
  2875  *         ttribute node or all the attribute values have been read, or -1
       
  2876  *         in case of error.
       
  2877  */
       
  2878 XMLPUBFUNEXPORT int
       
  2879 xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader)
       
  2880 {
       
  2881     if (reader == NULL)
       
  2882         return(-1);
       
  2883     if (reader->node == NULL)
       
  2884         return(-1);
       
  2885     if (reader->curnode == NULL)
       
  2886         return(0);
       
  2887 
       
  2888     if (reader->curnode->type == XML_ATTRIBUTE_NODE)
       
  2889     {
       
  2890         if (reader->curnode->children == NULL)
       
  2891             return(0);
       
  2892         reader->curnode = reader->curnode->children;
       
  2893     }
       
  2894     else if (reader->curnode->type == XML_NAMESPACE_DECL)
       
  2895     {
       
  2896         xmlNsPtr ns = (xmlNsPtr) reader->curnode;
       
  2897 
       
  2898         if (reader->faketext == NULL) {
       
  2899             reader->faketext = xmlNewDocText(reader->node->doc, ns->href);
       
  2900         } else {
       
  2901             if ((reader->faketext->content != NULL) &&
       
  2902                 (reader->faketext->content !=
       
  2903                 (xmlChar*) &(reader->faketext->properties)))
       
  2904                 xmlFree(reader->faketext->content);
       
  2905             reader->faketext->content = xmlStrdup(ns->href);
       
  2906         }
       
  2907         reader->curnode = reader->faketext;
       
  2908     }
       
  2909     else
       
  2910     {
       
  2911         if (reader->curnode->next == NULL)
       
  2912             return(0);
       
  2913         reader->curnode = reader->curnode->next;
       
  2914     }
       
  2915     return(1);
       
  2916 }
       
  2917 
       
  2918 /**
       
  2919  * xmlTextReaderConstEncoding:
       
  2920  * @param reader the xmlTextReaderPtr used
       
  2921  *
       
  2922  * Determine the encoding of the document being read.
       
  2923  *
       
  2924  * Returns a string containing the encoding of the document or NULL in
       
  2925  * case of error.  The string is deallocated with the reader.
       
  2926  */
       
  2927 XMLPUBFUNEXPORT const xmlChar *
       
  2928 xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
       
  2929     xmlDocPtr doc = NULL;
       
  2930     if (reader == NULL)
       
  2931     return(NULL);
       
  2932     if (reader->doc != NULL)
       
  2933         doc = reader->doc;
       
  2934     else if (reader->ctxt != NULL)
       
  2935     doc = reader->ctxt->myDoc;
       
  2936     if (doc == NULL)
       
  2937     return(NULL);
       
  2938 
       
  2939     if (doc->encoding == NULL)
       
  2940     return(NULL);
       
  2941     else
       
  2942       return(CONSTSTR(doc->encoding));
       
  2943 }
       
  2944 
       
  2945 
       
  2946 /************************************************************************
       
  2947  *                                                                      *
       
  2948  *          Access API to the current node                              *
       
  2949  *                                                                      *
       
  2950  ************************************************************************/
       
  2951 /**
       
  2952  * xmlTextReaderAttributeCount:
       
  2953  * @param reader the xmlTextReaderPtr used
       
  2954  *
       
  2955  * Provides the number of attributes of the current node
       
  2956  *
       
  2957  * Returns 0 i no attributes, -1 in case of error or the attribute count
       
  2958  */
       
  2959 XMLPUBFUNEXPORT int
       
  2960 xmlTextReaderAttributeCount(xmlTextReaderPtr reader)
       
  2961 {
       
  2962     int ret;
       
  2963     xmlAttrPtr attr;
       
  2964     xmlNsPtr ns;
       
  2965     xmlNodePtr node;
       
  2966 
       
  2967     if (reader == NULL)
       
  2968         return(-1);
       
  2969     if (reader->node == NULL)
       
  2970         return(0);
       
  2971 
       
  2972     if (reader->curnode != NULL)
       
  2973         node = reader->curnode;
       
  2974     else
       
  2975         node = reader->node;
       
  2976 
       
  2977     if (node->type != XML_ELEMENT_NODE)
       
  2978         return(0);
       
  2979     if ((reader->state == XML_TEXTREADER_END) ||
       
  2980         (reader->state == XML_TEXTREADER_BACKTRACK))
       
  2981     {
       
  2982         return(0);
       
  2983     }
       
  2984     ret = 0;
       
  2985     attr = node->properties;
       
  2986     while (attr != NULL) {
       
  2987         ret++;
       
  2988         attr = attr->next;
       
  2989     }
       
  2990     ns = node->nsDef;
       
  2991     while (ns != NULL) {
       
  2992         ret++;
       
  2993         ns = ns->next;
       
  2994     }
       
  2995     return(ret);
       
  2996 }
       
  2997 
       
  2998 /**
       
  2999  * xmlTextReaderNodeType:
       
  3000  * @param reader the xmlTextReaderPtr used
       
  3001  *
       
  3002  * Get the node type of the current node
       
  3003  * Reference:
       
  3004  * http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html
       
  3005  *
       
  3006  * Returns the xmlNodeType of the current node or -1 in case of error
       
  3007  */
       
  3008 XMLPUBFUNEXPORT int
       
  3009 xmlTextReaderNodeType(xmlTextReaderPtr reader)
       
  3010 {
       
  3011     xmlNodePtr node;
       
  3012 
       
  3013     if (reader == NULL)
       
  3014         return(-1);
       
  3015     if (reader->node == NULL)
       
  3016         return(XML_READER_TYPE_NONE);
       
  3017     if (reader->curnode != NULL)
       
  3018         node = reader->curnode;
       
  3019     else
       
  3020         node = reader->node;
       
  3021 
       
  3022     switch (node->type)
       
  3023     {
       
  3024         case XML_ELEMENT_NODE:
       
  3025             if ((reader->state == XML_TEXTREADER_END) ||
       
  3026                 (reader->state == XML_TEXTREADER_BACKTRACK))
       
  3027                 return(XML_READER_TYPE_END_ELEMENT);
       
  3028             return(XML_READER_TYPE_ELEMENT);
       
  3029         case XML_NAMESPACE_DECL:
       
  3030         case XML_ATTRIBUTE_NODE:
       
  3031             return(XML_READER_TYPE_ATTRIBUTE);
       
  3032         case XML_TEXT_NODE:
       
  3033             if (xmlIsBlankNode(reader->node)) {
       
  3034                 if (xmlNodeGetSpacePreserve(reader->node))
       
  3035                     return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
       
  3036                 else
       
  3037                     return(XML_READER_TYPE_WHITESPACE);
       
  3038             } else {
       
  3039                 return(XML_READER_TYPE_TEXT);
       
  3040             }
       
  3041         case XML_CDATA_SECTION_NODE:
       
  3042             return(XML_READER_TYPE_CDATA);
       
  3043         case XML_ENTITY_REF_NODE:
       
  3044             return(XML_READER_TYPE_ENTITY_REFERENCE);
       
  3045         case XML_ENTITY_NODE:
       
  3046             return(XML_READER_TYPE_ENTITY);
       
  3047 
       
  3048         case XML_PI_NODE:
       
  3049             return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
       
  3050         case XML_COMMENT_NODE:
       
  3051             return(XML_READER_TYPE_COMMENT);
       
  3052         case XML_DOCUMENT_NODE:
       
  3053         case XML_HTML_DOCUMENT_NODE:
       
  3054 #ifdef LIBXML_DOCB_ENABLED
       
  3055         case XML_DOCB_DOCUMENT_NODE:
       
  3056 #endif
       
  3057             return(XML_READER_TYPE_DOCUMENT);
       
  3058         case XML_DOCUMENT_FRAG_NODE:
       
  3059             return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
       
  3060         case XML_NOTATION_NODE:
       
  3061             return(XML_READER_TYPE_NOTATION);
       
  3062         case XML_DOCUMENT_TYPE_NODE:
       
  3063         case XML_DTD_NODE:
       
  3064             return(XML_READER_TYPE_DOCUMENT_TYPE);
       
  3065 
       
  3066         case XML_ELEMENT_DECL:
       
  3067         case XML_ATTRIBUTE_DECL:
       
  3068         case XML_ENTITY_DECL:
       
  3069         case XML_XINCLUDE_START:
       
  3070         case XML_XINCLUDE_END:
       
  3071             return(XML_READER_TYPE_NONE);
       
  3072     }
       
  3073     return(-1);
       
  3074 }
       
  3075 
       
  3076 /**
       
  3077  * xmlTextReaderIsEmptyElement:
       
  3078  * @param reader the xmlTextReaderPtr used
       
  3079  *
       
  3080  * Check if the current node is empty
       
  3081  *
       
  3082  * Returns 1 if empty, 0 if not and -1 in case of error
       
  3083  */
       
  3084 XMLPUBFUNEXPORT int
       
  3085 xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader)
       
  3086 {
       
  3087     if ((reader == NULL) || (reader->node == NULL))
       
  3088         return(-1);
       
  3089     if (reader->node->type != XML_ELEMENT_NODE)
       
  3090         return(0);
       
  3091     if (reader->curnode != NULL)
       
  3092         return(0);
       
  3093     if (reader->node->children != NULL)
       
  3094         return(0);
       
  3095     if (reader->state == XML_TEXTREADER_END)
       
  3096         return(0);
       
  3097     if (reader->doc != NULL)
       
  3098         return(1);
       
  3099 #ifdef LIBXML_XINCLUDE_ENABLED
       
  3100     if (reader->in_xinclude > 0)
       
  3101         return(1);
       
  3102 #endif
       
  3103     return((reader->node->extra & NODE_IS_EMPTY) != 0);
       
  3104 }
       
  3105 
       
  3106 /**
       
  3107  * xmlTextReaderLocalName:
       
  3108  * @param reader the xmlTextReaderPtr used
       
  3109  *
       
  3110  * The local name of the node.
       
  3111  *
       
  3112  * Returns the local name or NULL if not available
       
  3113  */
       
  3114 XMLPUBFUNEXPORT xmlChar*
       
  3115 xmlTextReaderLocalName(xmlTextReaderPtr reader)
       
  3116 {
       
  3117     xmlNodePtr node;
       
  3118     if ((reader == NULL) || (reader->node == NULL))
       
  3119         return(NULL);
       
  3120     if (reader->curnode != NULL)
       
  3121         node = reader->curnode;
       
  3122     else
       
  3123         node = reader->node;
       
  3124 
       
  3125     if (node->type == XML_NAMESPACE_DECL) {
       
  3126         xmlNsPtr ns = (xmlNsPtr) node;
       
  3127         if (ns->prefix == NULL)
       
  3128             return(xmlStrdup(BAD_CAST "xmlns"));
       
  3129         else
       
  3130             return(xmlStrdup(ns->prefix));
       
  3131     }
       
  3132     if ((node->type != XML_ELEMENT_NODE) &&
       
  3133         (node->type != XML_ATTRIBUTE_NODE))
       
  3134         return(xmlTextReaderName(reader));
       
  3135     return(xmlStrdup(node->name));
       
  3136 }
       
  3137 
       
  3138 /**
       
  3139  * xmlTextReaderConstLocalName:
       
  3140  * @param reader the xmlTextReaderPtr used
       
  3141  *
       
  3142  * The local name of the node.
       
  3143  *
       
  3144  * Returns the local name or NULL if not available, the
       
  3145  *         string will be deallocated with the reader.
       
  3146  */
       
  3147 XMLPUBFUNEXPORT const xmlChar*
       
  3148 xmlTextReaderConstLocalName(xmlTextReaderPtr reader)
       
  3149 {
       
  3150     xmlNodePtr node;
       
  3151     if ((reader == NULL) || (reader->node == NULL))
       
  3152         return(NULL);
       
  3153     if (reader->curnode != NULL)
       
  3154         node = reader->curnode;
       
  3155     else
       
  3156         node = reader->node;
       
  3157 
       
  3158     if (node->type == XML_NAMESPACE_DECL) {
       
  3159         xmlNsPtr ns = (xmlNsPtr) node;
       
  3160         if (ns->prefix == NULL)
       
  3161             return(CONSTSTR(BAD_CAST "xmlns"));
       
  3162         else
       
  3163             return(ns->prefix);
       
  3164     }
       
  3165 
       
  3166     if ((node->type != XML_ELEMENT_NODE) &&
       
  3167         (node->type != XML_ATTRIBUTE_NODE))
       
  3168         return(xmlTextReaderConstName(reader));
       
  3169     return(node->name);
       
  3170 }
       
  3171 
       
  3172 /**
       
  3173  * xmlTextReaderName:
       
  3174  * @param reader the xmlTextReaderPtr used
       
  3175  *
       
  3176  * The qualified name of the node, equal to Prefix :LocalName.
       
  3177  *
       
  3178  * Returns the local name or NULL if not available
       
  3179  */
       
  3180 XMLPUBFUNEXPORT xmlChar*
       
  3181 xmlTextReaderName(xmlTextReaderPtr reader)
       
  3182 {
       
  3183     xmlNodePtr node;
       
  3184     xmlChar *ret;
       
  3185 
       
  3186     if ((reader == NULL) || (reader->node == NULL))
       
  3187         return(NULL);
       
  3188     if (reader->curnode != NULL)
       
  3189         node = reader->curnode;
       
  3190     else
       
  3191         node = reader->node;
       
  3192 
       
  3193     switch (node->type)
       
  3194     {
       
  3195         case XML_ELEMENT_NODE:
       
  3196         case XML_ATTRIBUTE_NODE:
       
  3197             if ((node->ns == NULL) ||
       
  3198                 (node->ns->prefix == NULL))
       
  3199                 return(xmlStrdup(node->name));
       
  3200 
       
  3201             ret = xmlStrdup(node->ns->prefix);
       
  3202             ret = xmlStrcat(ret, BAD_CAST ":");
       
  3203             ret = xmlStrcat(ret, node->name);
       
  3204             return(ret);
       
  3205         case XML_TEXT_NODE:
       
  3206             return(xmlStrdup(BAD_CAST "#text"));
       
  3207         case XML_CDATA_SECTION_NODE:
       
  3208             return(xmlStrdup(BAD_CAST "#cdata-section"));
       
  3209         case XML_ENTITY_NODE:
       
  3210         case XML_ENTITY_REF_NODE:
       
  3211             return(xmlStrdup(node->name));
       
  3212         case XML_PI_NODE:
       
  3213             return(xmlStrdup(node->name));
       
  3214         case XML_COMMENT_NODE:
       
  3215             return(xmlStrdup(BAD_CAST "#comment"));
       
  3216         case XML_DOCUMENT_NODE:
       
  3217         case XML_HTML_DOCUMENT_NODE:
       
  3218 #ifdef LIBXML_DOCB_ENABLED
       
  3219         case XML_DOCB_DOCUMENT_NODE:
       
  3220 #endif
       
  3221             return(xmlStrdup(BAD_CAST "#document"));
       
  3222         case XML_DOCUMENT_FRAG_NODE:
       
  3223             return(xmlStrdup(BAD_CAST "#document-fragment"));
       
  3224         case XML_NOTATION_NODE:
       
  3225             return(xmlStrdup(node->name));
       
  3226         case XML_DOCUMENT_TYPE_NODE:
       
  3227         case XML_DTD_NODE:
       
  3228             return(xmlStrdup(node->name));
       
  3229         case XML_NAMESPACE_DECL: {
       
  3230             xmlNsPtr ns = (xmlNsPtr) node;
       
  3231 
       
  3232             ret = xmlStrdup(BAD_CAST "xmlns");
       
  3233             if (ns->prefix == NULL)
       
  3234                 return(ret);
       
  3235             ret = xmlStrcat(ret, BAD_CAST ":");
       
  3236             ret = xmlStrcat(ret, ns->prefix);
       
  3237             return(ret);
       
  3238         }
       
  3239 
       
  3240         case XML_ELEMENT_DECL:
       
  3241         case XML_ATTRIBUTE_DECL:
       
  3242         case XML_ENTITY_DECL:
       
  3243         case XML_XINCLUDE_START:
       
  3244         case XML_XINCLUDE_END:
       
  3245             return(NULL);
       
  3246     }
       
  3247     return(NULL);
       
  3248 }
       
  3249 
       
  3250 /**
       
  3251  * xmlTextReaderConstName:
       
  3252  * @param reader the xmlTextReaderPtr used
       
  3253  *
       
  3254  * The qualified name of the node, equal to Prefix :LocalName.
       
  3255  *
       
  3256  * Returns the local name or NULL if not available, the string is
       
  3257  *         deallocated with the reader.
       
  3258  */
       
  3259 XMLPUBFUNEXPORT const xmlChar*
       
  3260 xmlTextReaderConstName(xmlTextReaderPtr reader)
       
  3261 {
       
  3262     xmlNodePtr node;
       
  3263 
       
  3264     if ((reader == NULL) || (reader->node == NULL))
       
  3265         return(NULL);
       
  3266     if (reader->curnode != NULL)
       
  3267         node = reader->curnode;
       
  3268     else
       
  3269         node = reader->node;
       
  3270 
       
  3271     switch (node->type)
       
  3272     {
       
  3273         case XML_ELEMENT_NODE:
       
  3274         case XML_ATTRIBUTE_NODE:
       
  3275             if ((node->ns == NULL) ||
       
  3276                 (node->ns->prefix == NULL))
       
  3277                 return(node->name);
       
  3278             return(CONSTQSTR(node->ns->prefix, node->name));
       
  3279         case XML_TEXT_NODE:
       
  3280             return(CONSTSTR(BAD_CAST "#text"));
       
  3281         case XML_CDATA_SECTION_NODE:
       
  3282             return(CONSTSTR(BAD_CAST "#cdata-section"));
       
  3283         case XML_ENTITY_NODE:
       
  3284         case XML_ENTITY_REF_NODE:
       
  3285             return(CONSTSTR(node->name));
       
  3286         case XML_PI_NODE:
       
  3287             return(CONSTSTR(node->name));
       
  3288         case XML_COMMENT_NODE:
       
  3289             return(CONSTSTR(BAD_CAST "#comment"));
       
  3290         case XML_DOCUMENT_NODE:
       
  3291         case XML_HTML_DOCUMENT_NODE:
       
  3292 #ifdef LIBXML_DOCB_ENABLED
       
  3293         case XML_DOCB_DOCUMENT_NODE:
       
  3294 #endif
       
  3295             return(CONSTSTR(BAD_CAST "#document"));
       
  3296         case XML_DOCUMENT_FRAG_NODE:
       
  3297             return(CONSTSTR(BAD_CAST "#document-fragment"));
       
  3298         case XML_NOTATION_NODE:
       
  3299             return(CONSTSTR(node->name));
       
  3300         case XML_DOCUMENT_TYPE_NODE:
       
  3301         case XML_DTD_NODE:
       
  3302             return(CONSTSTR(node->name));
       
  3303         case XML_NAMESPACE_DECL: {
       
  3304             xmlNsPtr ns = (xmlNsPtr) node;
       
  3305 
       
  3306             if (ns->prefix == NULL)
       
  3307                 return(CONSTSTR(BAD_CAST "xmlns"));
       
  3308             return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
       
  3309         }
       
  3310 
       
  3311         case XML_ELEMENT_DECL:
       
  3312         case XML_ATTRIBUTE_DECL:
       
  3313         case XML_ENTITY_DECL:
       
  3314         case XML_XINCLUDE_START:
       
  3315         case XML_XINCLUDE_END:
       
  3316             return(NULL);
       
  3317     }
       
  3318     return(NULL);
       
  3319 }
       
  3320 
       
  3321 /**
       
  3322  * xmlTextReaderPrefix:
       
  3323  * @param reader the xmlTextReaderPtr used
       
  3324  *
       
  3325  * A shorthand reference to the namespace associated with the node.
       
  3326  *
       
  3327  * Returns the prefix or NULL if not available
       
  3328  */
       
  3329 XMLPUBFUNEXPORT xmlChar *
       
  3330 xmlTextReaderPrefix(xmlTextReaderPtr reader)
       
  3331 {
       
  3332     xmlNodePtr node;
       
  3333     if ((reader == NULL) || (reader->node == NULL))
       
  3334         return(NULL);
       
  3335     if (reader->curnode != NULL)
       
  3336         node = reader->curnode;
       
  3337     else
       
  3338         node = reader->node;
       
  3339 
       
  3340     if (node->type == XML_NAMESPACE_DECL) {
       
  3341         xmlNsPtr ns = (xmlNsPtr) node;
       
  3342         if (ns->prefix == NULL)
       
  3343             return(NULL);
       
  3344         return(xmlStrdup(BAD_CAST "xmlns"));
       
  3345     }
       
  3346     if ((node->type != XML_ELEMENT_NODE) &&
       
  3347         (node->type != XML_ATTRIBUTE_NODE))
       
  3348         return(NULL);
       
  3349 
       
  3350     if ((node->ns != NULL) && (node->ns->prefix != NULL))
       
  3351         return(xmlStrdup(node->ns->prefix));
       
  3352     return(NULL);
       
  3353 }
       
  3354 
       
  3355 /**
       
  3356  * xmlTextReaderConstPrefix:
       
  3357  * @param reader the xmlTextReaderPtr used
       
  3358  *
       
  3359  * A shorthand reference to the namespace associated with the node.
       
  3360  *
       
  3361  * Returns the prefix or NULL if not available, the string is deallocated
       
  3362  *         with the reader.
       
  3363  */
       
  3364 XMLPUBFUNEXPORT const xmlChar*
       
  3365 xmlTextReaderConstPrefix(xmlTextReaderPtr reader)
       
  3366 {
       
  3367     xmlNodePtr node;
       
  3368     if ((reader == NULL) || (reader->node == NULL))
       
  3369         return(NULL);
       
  3370     if (reader->curnode != NULL)
       
  3371         node = reader->curnode;
       
  3372     else
       
  3373         node = reader->node;
       
  3374 
       
  3375     if (node->type == XML_NAMESPACE_DECL) {
       
  3376         xmlNsPtr ns = (xmlNsPtr) node;
       
  3377         if (ns->prefix == NULL)
       
  3378             return(NULL);
       
  3379         return(CONSTSTR(BAD_CAST "xmlns"));
       
  3380     }
       
  3381 
       
  3382     if ((node->type != XML_ELEMENT_NODE) &&
       
  3383         (node->type != XML_ATTRIBUTE_NODE))
       
  3384         return(NULL);
       
  3385 
       
  3386     if ((node->ns != NULL) && (node->ns->prefix != NULL))
       
  3387         return(CONSTSTR(node->ns->prefix));
       
  3388     return(NULL);
       
  3389 }
       
  3390 
       
  3391 /**
       
  3392  * xmlTextReaderNamespaceUri:
       
  3393  * @param reader the xmlTextReaderPtr used
       
  3394  *
       
  3395  * The URI defining the namespace associated with the node.
       
  3396  *
       
  3397  * Returns the namespace URI or NULL if not available
       
  3398  */
       
  3399 XMLPUBFUNEXPORT xmlChar*
       
  3400 xmlTextReaderNamespaceUri(xmlTextReaderPtr reader)
       
  3401 {
       
  3402     xmlNodePtr node;
       
  3403     if ((reader == NULL) || (reader->node == NULL))
       
  3404         return(NULL);
       
  3405     if (reader->curnode != NULL)
       
  3406         node = reader->curnode;
       
  3407     else
       
  3408         node = reader->node;
       
  3409 
       
  3410     if (node->type == XML_NAMESPACE_DECL)
       
  3411         return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
       
  3412     if ((node->type != XML_ELEMENT_NODE) &&
       
  3413         (node->type != XML_ATTRIBUTE_NODE))
       
  3414         return(NULL);
       
  3415 
       
  3416     if (node->ns != NULL)
       
  3417         return(xmlStrdup(node->ns->href));
       
  3418     return(NULL);
       
  3419 }
       
  3420 
       
  3421 /**
       
  3422  * xmlTextReaderConstNamespaceUri:
       
  3423  * @param reader the xmlTextReaderPtr used
       
  3424  *
       
  3425  * The URI defining the namespace associated with the node.
       
  3426  *
       
  3427  * Returns the namespace URI or NULL if not available, the string
       
  3428  *         will be deallocated with the reader
       
  3429  */
       
  3430 XMLPUBFUNEXPORT const xmlChar*
       
  3431 xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader)
       
  3432 {
       
  3433     xmlNodePtr node;
       
  3434     if ((reader == NULL) || (reader->node == NULL))
       
  3435         return(NULL);
       
  3436     if (reader->curnode != NULL)
       
  3437         node = reader->curnode;
       
  3438     else
       
  3439         node = reader->node;
       
  3440 
       
  3441     if (node->type == XML_NAMESPACE_DECL)
       
  3442         return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
       
  3443     if ((node->type != XML_ELEMENT_NODE) &&
       
  3444         (node->type != XML_ATTRIBUTE_NODE))
       
  3445         return(NULL);
       
  3446     if (node->ns != NULL)
       
  3447         return(CONSTSTR(node->ns->href));
       
  3448     return(NULL);
       
  3449 }
       
  3450 
       
  3451 /**
       
  3452  * xmlTextReaderBaseUri:
       
  3453  * @param reader the xmlTextReaderPtr used
       
  3454  *
       
  3455  * The base URI of the node.
       
  3456  *
       
  3457  * Returns the base URI or NULL if not available
       
  3458  */
       
  3459 XMLPUBFUNEXPORT xmlChar*
       
  3460 xmlTextReaderBaseUri(xmlTextReaderPtr reader)
       
  3461 {
       
  3462     if ((reader == NULL) || (reader->node == NULL))
       
  3463         return(NULL);
       
  3464     return(xmlNodeGetBase(NULL, reader->node));
       
  3465 }
       
  3466 
       
  3467 /**
       
  3468  * xmlTextReaderConstBaseUri:
       
  3469  * @param reader the xmlTextReaderPtr used
       
  3470  *
       
  3471  * The base URI of the node.
       
  3472  *
       
  3473  * Returns the base URI or NULL if not available, the string
       
  3474  *         will be deallocated with the reader
       
  3475  */
       
  3476 XMLPUBFUNEXPORT const xmlChar*
       
  3477 xmlTextReaderConstBaseUri(xmlTextReaderPtr reader)
       
  3478 {
       
  3479     xmlChar* tmp;
       
  3480     const xmlChar *ret;
       
  3481 
       
  3482     if ((reader == NULL) || (reader->node == NULL))
       
  3483         return(NULL);
       
  3484 
       
  3485     tmp = xmlNodeGetBase(NULL, reader->node);
       
  3486     if (tmp == NULL)
       
  3487         return(NULL);
       
  3488     ret = CONSTSTR(tmp);
       
  3489     xmlFree(tmp);
       
  3490     return(ret);
       
  3491 }
       
  3492 
       
  3493 /**
       
  3494  * xmlTextReaderDepth:
       
  3495  * @param reader the xmlTextReaderPtr used
       
  3496  *
       
  3497  * The depth of the node in the tree.
       
  3498  *
       
  3499  * Returns the depth or -1 in case of error
       
  3500  */
       
  3501 XMLPUBFUNEXPORT int
       
  3502 xmlTextReaderDepth(xmlTextReaderPtr reader)
       
  3503 {
       
  3504     if (reader == NULL)
       
  3505         return(-1);
       
  3506     if (reader->node == NULL)
       
  3507         return(0);
       
  3508 
       
  3509     if (reader->curnode != NULL) {
       
  3510         if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
       
  3511             (reader->curnode->type == XML_NAMESPACE_DECL))
       
  3512             return(reader->depth + 1);
       
  3513         return(reader->depth + 2);
       
  3514     }
       
  3515     return(reader->depth);
       
  3516 }
       
  3517 
       
  3518 /**
       
  3519  * xmlTextReaderHasAttributes:
       
  3520  * @param reader the xmlTextReaderPtr used
       
  3521  *
       
  3522  * Whether the node has attributes.
       
  3523  *
       
  3524  * Returns 1 if true, 0 if false, and -1 in case or error
       
  3525  */
       
  3526 XMLPUBFUNEXPORT int
       
  3527 xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
       
  3528     xmlNodePtr node;
       
  3529     if (reader == NULL)
       
  3530         return(-1);
       
  3531     if (reader->node == NULL)
       
  3532         return(0);
       
  3533     if (reader->curnode != NULL)
       
  3534         node = reader->curnode;
       
  3535     else
       
  3536         node = reader->node;
       
  3537 
       
  3538     if ((node->type == XML_ELEMENT_NODE) &&
       
  3539         (node->properties || node->nsDef))
       
  3540         return(1);
       
  3541     
       
  3542     return(0);
       
  3543 }
       
  3544 
       
  3545 /**
       
  3546  * xmlTextReaderHasValue:
       
  3547  * @param reader the xmlTextReaderPtr used
       
  3548  *
       
  3549  * Whether the node can have a text value.
       
  3550  *
       
  3551  * Returns 1 if true, 0 if false, and -1 in case or error
       
  3552  */
       
  3553 XMLPUBFUNEXPORT int
       
  3554 xmlTextReaderHasValue(xmlTextReaderPtr reader)
       
  3555 {
       
  3556     xmlNodePtr node;
       
  3557     if (reader == NULL)
       
  3558         return(-1);
       
  3559     if (reader->node == NULL)
       
  3560         return(0);
       
  3561     if (reader->curnode != NULL)
       
  3562         node = reader->curnode;
       
  3563     else
       
  3564         node = reader->node;
       
  3565 
       
  3566     switch (node->type) {
       
  3567         case XML_ATTRIBUTE_NODE:
       
  3568         case XML_TEXT_NODE:
       
  3569         case XML_CDATA_SECTION_NODE:
       
  3570         case XML_PI_NODE:
       
  3571         case XML_COMMENT_NODE:
       
  3572         case XML_NAMESPACE_DECL:
       
  3573             return(1);
       
  3574         default:
       
  3575             break;
       
  3576     }
       
  3577     return(0);
       
  3578 }
       
  3579 
       
  3580 /**
       
  3581  * xmlTextReaderValue:
       
  3582  * @param reader the xmlTextReaderPtr used
       
  3583  *
       
  3584  * Provides the text value of the node if present
       
  3585  *
       
  3586  * Returns the string or NULL if not available. The result must be deallocated
       
  3587  *     with xmlFree()
       
  3588  */
       
  3589 XMLPUBFUNEXPORT xmlChar*
       
  3590 xmlTextReaderValue(xmlTextReaderPtr reader)
       
  3591 {
       
  3592     xmlNodePtr node;
       
  3593     if (reader == NULL)
       
  3594         return(NULL);
       
  3595     if (reader->node == NULL)
       
  3596         return(NULL);
       
  3597     if (reader->curnode != NULL)
       
  3598         node = reader->curnode;
       
  3599     else
       
  3600         node = reader->node;
       
  3601 
       
  3602     switch (node->type)
       
  3603     {
       
  3604         case XML_NAMESPACE_DECL:
       
  3605             return(xmlStrdup(((xmlNsPtr) node)->href));
       
  3606         case XML_ATTRIBUTE_NODE:{
       
  3607             xmlAttrPtr attr = (xmlAttrPtr) node;
       
  3608 
       
  3609             if (attr->parent != NULL)
       
  3610            	 return (xmlNodeListGetString(attr->parent->doc, attr->children, 1));
       
  3611             else
       
  3612                 return (xmlNodeListGetString(NULL, attr->children, 1));
       
  3613         }
       
  3614         case XML_TEXT_NODE:
       
  3615         case XML_CDATA_SECTION_NODE:
       
  3616         case XML_PI_NODE:
       
  3617         case XML_COMMENT_NODE:
       
  3618             if (node->content != NULL)
       
  3619                 return (xmlStrdup(node->content));
       
  3620         default:
       
  3621             break;
       
  3622     }
       
  3623     return(NULL);
       
  3624 }
       
  3625 
       
  3626 /**
       
  3627  * xmlTextReaderConstValue:
       
  3628  * @param reader the xmlTextReaderPtr used
       
  3629  *
       
  3630  * Provides the text value of the node if present
       
  3631  *
       
  3632  * Returns the string or NULL if not available. The result will be
       
  3633  *     deallocated on the next Read() operation.
       
  3634  */
       
  3635 XMLPUBFUNEXPORT const xmlChar*
       
  3636 xmlTextReaderConstValue(xmlTextReaderPtr reader)
       
  3637 {
       
  3638     xmlNodePtr node;
       
  3639     if (reader == NULL)
       
  3640         return(NULL);
       
  3641     if (reader->node == NULL)
       
  3642         return(NULL);
       
  3643     if (reader->curnode != NULL)
       
  3644         node = reader->curnode;
       
  3645     else
       
  3646         node = reader->node;
       
  3647 
       
  3648     switch (node->type) {
       
  3649         case XML_NAMESPACE_DECL:
       
  3650             return(((xmlNsPtr) node)->href);
       
  3651         case XML_ATTRIBUTE_NODE:{
       
  3652             xmlAttrPtr attr = (xmlAttrPtr) node;
       
  3653 
       
  3654             if (attr->children &&
       
  3655                 (attr->children->type == XML_TEXT_NODE) &&
       
  3656                 !attr->children->next)
       
  3657             {
       
  3658                 return(attr->children->content);
       
  3659             } else {
       
  3660                 if (reader->buffer == NULL)
       
  3661                     reader->buffer = xmlBufferCreateSize(100);
       
  3662                 if (reader->buffer == NULL) {
       
  3663                     xmlGenericError(xmlGenericErrorContext,
       
  3664                     "xmlTextReaderSetup : malloc failed\n");
       
  3665                     return (NULL);
       
  3666                 }
       
  3667                 reader->buffer->use = 0;
       
  3668                 xmlNodeBufGetContent(reader->buffer, node);
       
  3669                 return(reader->buffer->content);
       
  3670             }
       
  3671         }
       
  3672         case XML_TEXT_NODE:
       
  3673         case XML_CDATA_SECTION_NODE:
       
  3674         case XML_PI_NODE:
       
  3675         case XML_COMMENT_NODE:
       
  3676             return(node->content);
       
  3677         default:
       
  3678             break;
       
  3679     }
       
  3680     return(NULL);
       
  3681 }
       
  3682 
       
  3683 /**
       
  3684  * xmlTextReaderIsDefault:
       
  3685  * @param reader the xmlTextReaderPtr used
       
  3686  *
       
  3687  * Whether an Attribute  node was generated from the default value
       
  3688  * defined in the DTD or schema.
       
  3689  *
       
  3690  * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
       
  3691  */
       
  3692 XMLPUBFUNEXPORT int
       
  3693 xmlTextReaderIsDefault(xmlTextReaderPtr reader)
       
  3694 {
       
  3695     if (reader == NULL)
       
  3696         return(-1);
       
  3697     return(0);
       
  3698 }
       
  3699 
       
  3700 /**
       
  3701  * xmlTextReaderQuoteChar:
       
  3702  * @param reader the xmlTextReaderPtr used
       
  3703  *
       
  3704  * The quotation mark character used to enclose the value of an attribute.
       
  3705  *
       
  3706  * Returns " or ' and -1 in case of error
       
  3707  */
       
  3708 XMLPUBFUNEXPORT int
       
  3709 xmlTextReaderQuoteChar(xmlTextReaderPtr reader)
       
  3710 {
       
  3711     if (reader == NULL)
       
  3712         return(-1);
       
  3713     
       
  3714     return((int) '"');
       
  3715 }
       
  3716 
       
  3717 /**
       
  3718  * xmlTextReaderXmlLang:
       
  3719  * @param reader the xmlTextReaderPtr used
       
  3720  *
       
  3721  * The xml:lang scope within which the node resides.
       
  3722  *
       
  3723  * Returns the xml:lang value or NULL if none exists.
       
  3724  */
       
  3725 XMLPUBFUNEXPORT xmlChar*
       
  3726 xmlTextReaderXmlLang(xmlTextReaderPtr reader)
       
  3727 {
       
  3728     if (reader == NULL)
       
  3729         return(NULL);
       
  3730     if (reader->node == NULL)
       
  3731         return(NULL);
       
  3732     return(xmlNodeGetLang(reader->node));
       
  3733 }
       
  3734 
       
  3735 /**
       
  3736  * xmlTextReaderConstXmlLang:
       
  3737  * @param reader the xmlTextReaderPtr used
       
  3738  *
       
  3739  * The xml:lang scope within which the node resides.
       
  3740  *
       
  3741  * Returns the xml:lang value or NULL if none exists.
       
  3742  */
       
  3743 XMLPUBFUNEXPORT const xmlChar*
       
  3744 xmlTextReaderConstXmlLang(xmlTextReaderPtr reader)
       
  3745 {
       
  3746     xmlChar *tmp;
       
  3747     const xmlChar *ret;
       
  3748 
       
  3749     if (reader == NULL)
       
  3750         return(NULL);
       
  3751     if (reader->node == NULL)
       
  3752         return(NULL);
       
  3753     tmp = xmlNodeGetLang(reader->node);
       
  3754     if (tmp == NULL)
       
  3755         return(NULL);
       
  3756     ret = CONSTSTR(tmp);
       
  3757     xmlFree(tmp);
       
  3758     return(ret);
       
  3759 }
       
  3760 
       
  3761 /**
       
  3762  * xmlTextReaderConstString:
       
  3763  * @param reader the xmlTextReaderPtr used
       
  3764  * @param str the string to intern.
       
  3765  *
       
  3766  * Get an interned string from the reader, allows for example to
       
  3767  * speedup string name comparisons
       
  3768  *
       
  3769  * Returns an interned copy of the string or NULL in case of error. The
       
  3770  *         string will be deallocated with the reader.
       
  3771  */
       
  3772 XMLPUBFUNEXPORT const xmlChar*
       
  3773 xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str)
       
  3774 {
       
  3775     if (reader == NULL)
       
  3776         return(NULL);
       
  3777     return(CONSTSTR(str));
       
  3778 }
       
  3779 
       
  3780 /**
       
  3781  * xmlTextReaderNormalization:
       
  3782  * @param reader the xmlTextReaderPtr used
       
  3783  *
       
  3784  * The value indicating whether to normalize white space and attribute values.
       
  3785  * Since attribute value and end of line normalizations are a MUST in the XML
       
  3786  * specification only the value true is accepted. The broken bahaviour of
       
  3787  * accepting out of range character entities like &#0; is of course not
       
  3788  * supported either.
       
  3789  *
       
  3790  * Returns 1 or -1 in case of error.
       
  3791  */
       
  3792 XMLPUBFUNEXPORT int
       
  3793 xmlTextReaderNormalization(xmlTextReaderPtr reader)
       
  3794 {
       
  3795     if (reader == NULL)
       
  3796         return(-1);
       
  3797     return(1);
       
  3798 }
       
  3799 
       
  3800 /************************************************************************
       
  3801  *                                                                      *
       
  3802  *          Extensions to the base APIs                                 *
       
  3803  *                                                                      *
       
  3804  ************************************************************************/
       
  3805 
       
  3806 /**
       
  3807  * xmlTextReaderSetParserProp:
       
  3808  * @param reader the xmlTextReaderPtr used
       
  3809  * @param prop the xmlParserProperties to set
       
  3810  * @param value usually 0 or 1 to (de)activate it
       
  3811  *
       
  3812  * Change the parser processing behaviour by changing some of its internal
       
  3813  * properties. Note that some properties can only be changed before any
       
  3814  * read has been done.
       
  3815  *
       
  3816  * Returns 0 if the call was successful, or -1 in case of error
       
  3817  */
       
  3818 XMLPUBFUNEXPORT int
       
  3819 xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value)
       
  3820 {
       
  3821     xmlParserProperties p = (xmlParserProperties) prop;
       
  3822     xmlParserCtxtPtr ctxt;
       
  3823 
       
  3824     if ((reader == NULL) || (reader->ctxt == NULL))
       
  3825         return(-1);
       
  3826     ctxt = reader->ctxt;
       
  3827 
       
  3828     switch (p)
       
  3829     {
       
  3830         case XML_PARSER_LOADDTD:
       
  3831             if (value != 0) {
       
  3832                 if (ctxt->loadsubset == 0) {
       
  3833                     if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
       
  3834                         return(-1);
       
  3835                     ctxt->loadsubset = XML_DETECT_IDS;
       
  3836                 }
       
  3837             } else {
       
  3838                 ctxt->loadsubset = 0;
       
  3839             }
       
  3840             return(0);
       
  3841         case XML_PARSER_DEFAULTATTRS:
       
  3842             if (value != 0) {
       
  3843                 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
       
  3844             } else {
       
  3845                 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
       
  3846                     ctxt->loadsubset -= XML_COMPLETE_ATTRS;
       
  3847             }
       
  3848             return(0);
       
  3849         case XML_PARSER_VALIDATE:
       
  3850             if (value != 0) {
       
  3851                 ctxt->validate = 1;
       
  3852                 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
       
  3853             } else {
       
  3854                 ctxt->validate = 0;
       
  3855             }
       
  3856             return(0);
       
  3857         case XML_PARSER_SUBST_ENTITIES:
       
  3858             if (value != 0) {
       
  3859                 ctxt->replaceEntities = 1;
       
  3860             } else {
       
  3861                 ctxt->replaceEntities = 0;
       
  3862             }
       
  3863             return(0);
       
  3864     }
       
  3865     return(-1);
       
  3866 }
       
  3867 
       
  3868 /**
       
  3869  * xmlTextReaderGetParserProp:
       
  3870  * @param reader the xmlTextReaderPtr used
       
  3871  * @param prop the xmlParserProperties to get
       
  3872  *
       
  3873  * Read the parser internal property.
       
  3874  *
       
  3875  * Returns the value, usually 0 or 1, or -1 in case of error.
       
  3876  */
       
  3877 XMLPUBFUNEXPORT int
       
  3878 xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop)
       
  3879 {
       
  3880     xmlParserProperties p = (xmlParserProperties) prop;
       
  3881     xmlParserCtxtPtr ctxt;
       
  3882 
       
  3883     if ((reader == NULL) || (reader->ctxt == NULL))
       
  3884         return(-1);
       
  3885     ctxt = reader->ctxt;
       
  3886 
       
  3887     switch (p)
       
  3888     {
       
  3889         case XML_PARSER_LOADDTD:
       
  3890             if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
       
  3891                 return(1);
       
  3892             return(0);
       
  3893         case XML_PARSER_DEFAULTATTRS:
       
  3894             if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
       
  3895                 return(1);
       
  3896             return(0);
       
  3897         case XML_PARSER_VALIDATE:
       
  3898             return(reader->validate);
       
  3899         case XML_PARSER_SUBST_ENTITIES:
       
  3900             return(ctxt->replaceEntities);
       
  3901     }
       
  3902     return(-1);
       
  3903 }
       
  3904 
       
  3905 /**
       
  3906  * xmlTextReaderGetParserLineNumber:
       
  3907  * @param reader the user data (XML reader context)
       
  3908  *
       
  3909  * Provide the line number of the current parsing point.
       
  3910  *
       
  3911  * Returns an int or 0 if not available
       
  3912  */
       
  3913 XMLPUBFUNEXPORT int
       
  3914 xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
       
  3915 {
       
  3916     if ((reader == NULL) || (reader->ctxt == NULL) ||
       
  3917         (reader->ctxt->input == NULL)) {
       
  3918         return (0);
       
  3919     }
       
  3920     return (reader->ctxt->input->line);
       
  3921 }
       
  3922 
       
  3923 /**
       
  3924  * xmlTextReaderGetParserColumnNumber:
       
  3925  * @param reader the user data (XML reader context)
       
  3926  *
       
  3927  * Provide the column number of the current parsing point.
       
  3928  *
       
  3929  * Returns an int or 0 if not available
       
  3930  */
       
  3931 XMLPUBFUNEXPORT int
       
  3932 xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
       
  3933 {
       
  3934     if ((reader == NULL) || (reader->ctxt == NULL) ||
       
  3935         (reader->ctxt->input == NULL)) {
       
  3936         return (0);
       
  3937     }
       
  3938     return (reader->ctxt->input->col);
       
  3939 }
       
  3940 
       
  3941 /**
       
  3942  * xmlTextReaderCurrentNode:
       
  3943  * @param reader the xmlTextReaderPtr used
       
  3944  *
       
  3945  * Hacking interface allowing to get the xmlNodePtr correponding to the
       
  3946  * current node being accessed by the xmlTextReader. This is dangerous
       
  3947  * because the underlying node may be destroyed on the next Reads.
       
  3948  *
       
  3949  * Returns the xmlNodePtr or NULL in case of error.
       
  3950  */
       
  3951 XMLPUBFUNEXPORT xmlNodePtr
       
  3952 xmlTextReaderCurrentNode(xmlTextReaderPtr reader)
       
  3953 {
       
  3954     if (reader == NULL)
       
  3955         return(NULL);
       
  3956 
       
  3957     if (reader->curnode != NULL)
       
  3958         return(reader->curnode);
       
  3959     return(reader->node);
       
  3960 }
       
  3961 
       
  3962 /**
       
  3963  * xmlTextReaderPreserve:
       
  3964  * @param reader the xmlTextReaderPtr used
       
  3965  *
       
  3966  * This tells the XML Reader to preserve the current node.
       
  3967  * The caller must also use xmlTextReaderCurrentDoc() to
       
  3968  * keep an handle on the resulting document once parsing has finished
       
  3969  *
       
  3970  * Returns the xmlNodePtr or NULL in case of error.
       
  3971  */
       
  3972 XMLPUBFUNEXPORT xmlNodePtr
       
  3973 xmlTextReaderPreserve(xmlTextReaderPtr reader)
       
  3974 {
       
  3975     xmlNodePtr cur, parent;
       
  3976 
       
  3977     if (reader == NULL)
       
  3978         return(NULL);
       
  3979 
       
  3980     if (reader->curnode != NULL)
       
  3981         cur = reader->curnode;
       
  3982     else
       
  3983         cur = reader->node;
       
  3984     if (cur == NULL)
       
  3985         return(NULL);
       
  3986 
       
  3987     if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
       
  3988         cur->extra |= NODE_IS_PRESERVED;
       
  3989         cur->extra |= NODE_IS_SPRESERVED;
       
  3990     }
       
  3991     reader->preserves++;
       
  3992 
       
  3993     parent = cur->parent;
       
  3994     while (parent != NULL) {
       
  3995         if (parent->type == XML_ELEMENT_NODE)
       
  3996             parent->extra |= NODE_IS_PRESERVED;
       
  3997         parent = parent->parent;
       
  3998     }
       
  3999     return(cur);
       
  4000 }
       
  4001 
       
  4002 #ifdef LIBXML_PATTERN_ENABLED
       
  4003 /**
       
  4004  * xmlTextReaderPreservePattern:
       
  4005  * @param reader the xmlTextReaderPtr used
       
  4006  * @param pattern an XPath subset pattern
       
  4007  * @param namespaces the prefix definitions, array of [URI, prefix] or NULL
       
  4008  *
       
  4009  * This tells the XML Reader to preserve all nodes matched by the
       
  4010  * pattern. The caller must also use xmlTextReaderCurrentDoc() to
       
  4011  * keep an handle on the resulting document once parsing has finished
       
  4012  *
       
  4013  * Returns a positive number in case of success and -1 in case of error
       
  4014  */
       
  4015 int
       
  4016 xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
       
  4017                              const xmlChar **namespaces)
       
  4018 {
       
  4019     xmlPatternPtr comp;
       
  4020 
       
  4021     if ((reader == NULL) || (pattern == NULL))
       
  4022         return(-1);
       
  4023 
       
  4024     comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
       
  4025     if (comp == NULL)
       
  4026         return(-1);
       
  4027 
       
  4028     if (reader->patternMax <= 0) {
       
  4029         reader->patternMax = 4;
       
  4030         reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
       
  4031                                               sizeof(reader->patternTab[0]));
       
  4032         if (reader->patternTab == NULL) {
       
  4033             xmlGenericError(xmlGenericErrorContext, EMBED_ERRTXT("xmlMalloc failed !\n"));
       
  4034             return (-1);
       
  4035         }
       
  4036     }
       
  4037     if (reader->patternNr >= reader->patternMax) {
       
  4038         xmlPatternPtr *tmp;
       
  4039         reader->patternMax *= 2;
       
  4040         tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
       
  4041                                       reader->patternMax *
       
  4042                                       sizeof(reader->patternTab[0]));
       
  4043         if (tmp == NULL) {
       
  4044             xmlGenericError(xmlGenericErrorContext, EMBED_ERRTXT("xmlRealloc failed !\n"));
       
  4045             reader->patternMax /= 2;
       
  4046             return (-1);
       
  4047         }
       
  4048         reader->patternTab = tmp;
       
  4049     }
       
  4050     reader->patternTab[reader->patternNr] = comp;
       
  4051     return(reader->patternNr++);
       
  4052 }
       
  4053 #endif
       
  4054 
       
  4055 /**
       
  4056  * xmlTextReaderCurrentDoc:
       
  4057  * @param reader the xmlTextReaderPtr used
       
  4058  *
       
  4059  * Hacking interface allowing to get the xmlDocPtr correponding to the
       
  4060  * current document being accessed by the xmlTextReader.
       
  4061  * NOTE: as a result of this call, the reader will not destroy the
       
  4062  *       associated XML document and calling xmlFreeDoc() on the result
       
  4063  *       is needed once the reader parsing has finished.
       
  4064  *
       
  4065  * Returns the xmlDocPtr or NULL in case of error.
       
  4066  */
       
  4067 XMLPUBFUNEXPORT xmlDocPtr
       
  4068 xmlTextReaderCurrentDoc(xmlTextReaderPtr reader)
       
  4069 {
       
  4070     if (reader == NULL)
       
  4071         return(NULL);
       
  4072     if (reader->doc != NULL)
       
  4073         return(reader->doc);
       
  4074     if ((reader == NULL) || (reader->ctxt == NULL) ||
       
  4075         (reader->ctxt->myDoc == NULL))
       
  4076         return(NULL);
       
  4077 
       
  4078     reader->preserve = 1;
       
  4079     return(reader->ctxt->myDoc);
       
  4080 }
       
  4081 
       
  4082 #ifdef LIBXML_SCHEMAS_ENABLED
       
  4083 
       
  4084 static char *
       
  4085 xmlTextReaderBuildMessage(const char *msg, va_list ap);
       
  4086 
       
  4087 static void XMLCDECL
       
  4088 xmlTextReaderValidityError(void *ctxt, const char *msg, ...);
       
  4089 
       
  4090 static void XMLCDECL
       
  4091 xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...);
       
  4092 
       
  4093 static void XMLCDECL xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
       
  4094 {
       
  4095     xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
       
  4096     char * str;
       
  4097     va_list ap;
       
  4098 
       
  4099     va_start(ap,msg);
       
  4100     str = xmlTextReaderBuildMessage(msg,ap);
       
  4101     if (!reader->errorFunc) {
       
  4102         xmlTextReaderValidityError(ctx, "%s", str);
       
  4103     } else {
       
  4104         reader->errorFunc(reader->errorFuncArg, str, XML_PARSER_SEVERITY_VALIDITY_ERROR, NULL /* locator */);
       
  4105     }
       
  4106     if (str != NULL)
       
  4107         xmlFree(str);
       
  4108     va_end(ap);
       
  4109 }
       
  4110 
       
  4111 static void XMLCDECL xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
       
  4112 {
       
  4113     xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
       
  4114     char * str;
       
  4115     va_list ap;
       
  4116 
       
  4117     va_start(ap,msg);
       
  4118     str = xmlTextReaderBuildMessage(msg,ap);
       
  4119     if (!reader->errorFunc) {
       
  4120         xmlTextReaderValidityWarning(ctx, "%s", str);
       
  4121     } else {
       
  4122         reader->errorFunc(reader->errorFuncArg, str, XML_PARSER_SEVERITY_VALIDITY_WARNING, NULL /* locator */);
       
  4123     }
       
  4124     if (str != NULL)
       
  4125         xmlFree(str);
       
  4126     va_end(ap);
       
  4127 }
       
  4128 
       
  4129 static void
       
  4130 xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
       
  4131 
       
  4132 static void xmlTextReaderValidityStructuredRelay(void * userData, xmlErrorPtr error)
       
  4133 {
       
  4134     xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
       
  4135 
       
  4136     if (reader->sErrorFunc) {
       
  4137         reader->sErrorFunc(reader->errorFuncArg, error);
       
  4138     } else {
       
  4139         xmlTextReaderStructuredError(reader, error);
       
  4140     }
       
  4141 }
       
  4142 
       
  4143 /**
       
  4144  * xmlTextReaderRelaxNGSetSchema:
       
  4145  * @param reader the xmlTextReaderPtr used
       
  4146  * @param schema a precompiled RelaxNG schema
       
  4147  *
       
  4148  * Use RelaxNG to validate the document as it is processed.
       
  4149  * Activation is only possible before the first Read().
       
  4150  * if schema is NULL, then RelaxNG validation is desactivated.
       
  4151  * The schema should not be freed until the reader is deallocated
       
  4152  * or its use has been deactivated.
       
  4153  *
       
  4154  * Returns 0 in case the RelaxNG validation could be (des)activated and
       
  4155  *         -1 in case of error.
       
  4156  */
       
  4157 int
       
  4158 xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
       
  4159     if (reader == NULL)
       
  4160         return(-1);
       
  4161     if (schema == NULL) {
       
  4162         if (reader->rngSchemas != NULL) {
       
  4163             xmlRelaxNGFree(reader->rngSchemas);
       
  4164             reader->rngSchemas = NULL;
       
  4165         }
       
  4166         if (reader->rngValidCtxt != NULL) {
       
  4167             xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
       
  4168             reader->rngValidCtxt = NULL;
       
  4169         }
       
  4170         return(0);
       
  4171     }
       
  4172     if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
       
  4173         return(-1);
       
  4174     if (reader->rngSchemas != NULL) {
       
  4175         xmlRelaxNGFree(reader->rngSchemas);
       
  4176         reader->rngSchemas = NULL;
       
  4177     }
       
  4178     if (reader->rngValidCtxt != NULL) {
       
  4179         xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
       
  4180         reader->rngValidCtxt = NULL;
       
  4181     }
       
  4182     reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
       
  4183     if (reader->rngValidCtxt == NULL)
       
  4184         return(-1);
       
  4185     if (reader->errorFunc != NULL) {
       
  4186         xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
       
  4187             xmlTextReaderValidityErrorRelay,
       
  4188             xmlTextReaderValidityWarningRelay,
       
  4189             reader);
       
  4190     }
       
  4191     if (reader->sErrorFunc != NULL) {
       
  4192         xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
       
  4193             xmlTextReaderValidityStructuredRelay,
       
  4194             reader);
       
  4195     }
       
  4196     reader->rngValidErrors = 0;
       
  4197     reader->rngFullNode = NULL;
       
  4198     reader->validate = XML_TEXTREADER_VALIDATE_RNG;
       
  4199     return(0);
       
  4200 }
       
  4201 
       
  4202 /**
       
  4203  * xmlTextReaderSetSchema:
       
  4204  * @param reader the xmlTextReaderPtr used
       
  4205  * @param schema a precompiled Schema schema
       
  4206  *
       
  4207  * Use XSD Schema to validate the document as it is processed.
       
  4208  * Activation is only possible before the first Read().
       
  4209  * if schema is NULL, then Schema validation is desactivated.
       
  4210  * The schema should not be freed until the reader is deallocated
       
  4211  * or its use has been deactivated.
       
  4212  *
       
  4213  * Returns 0 in case the Schema validation could be (des)activated and
       
  4214  *         -1 in case of error.
       
  4215  */
       
  4216 int
       
  4217 xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
       
  4218     if (reader == NULL)
       
  4219         return(-1);
       
  4220     if (schema == NULL) {
       
  4221     if (reader->xsdPlug != NULL) {
       
  4222         xmlSchemaSAXUnplug(reader->xsdPlug);
       
  4223         reader->xsdPlug = NULL;
       
  4224     }
       
  4225         if (reader->xsdValidCtxt != NULL) {
       
  4226         xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
       
  4227         reader->xsdValidCtxt = NULL;
       
  4228         }
       
  4229         if (reader->xsdSchemas != NULL) {
       
  4230         xmlSchemaFree(reader->xsdSchemas);
       
  4231         reader->xsdSchemas = NULL;
       
  4232     }
       
  4233     return(0);
       
  4234     }
       
  4235     if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
       
  4236     return(-1);
       
  4237     if (reader->xsdPlug != NULL) {
       
  4238     xmlSchemaSAXUnplug(reader->xsdPlug);
       
  4239     reader->xsdPlug = NULL;
       
  4240     }
       
  4241     if (reader->xsdValidCtxt != NULL) {
       
  4242     xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
       
  4243     reader->xsdValidCtxt = NULL;
       
  4244     }
       
  4245     if (reader->xsdSchemas != NULL) {
       
  4246     xmlSchemaFree(reader->xsdSchemas);
       
  4247     reader->xsdSchemas = NULL;
       
  4248     }
       
  4249     reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
       
  4250     if (reader->xsdValidCtxt == NULL) {
       
  4251     xmlSchemaFree(reader->xsdSchemas);
       
  4252     reader->xsdSchemas = NULL;
       
  4253         return(-1);
       
  4254     }
       
  4255     reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
       
  4256                                        &(reader->ctxt->sax),
       
  4257                        &(reader->ctxt->userData));
       
  4258     if (reader->xsdPlug == NULL) {
       
  4259     xmlSchemaFree(reader->xsdSchemas);
       
  4260     reader->xsdSchemas = NULL;
       
  4261     xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
       
  4262     reader->xsdValidCtxt = NULL;
       
  4263     return(-1);
       
  4264     }
       
  4265     if (reader->errorFunc != NULL) {
       
  4266     xmlSchemaSetValidErrors(reader->xsdValidCtxt,
       
  4267             xmlTextReaderValidityErrorRelay,
       
  4268             xmlTextReaderValidityWarningRelay,
       
  4269             reader);
       
  4270     }
       
  4271     if (reader->sErrorFunc != NULL) {
       
  4272         xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
       
  4273             xmlTextReaderValidityStructuredRelay,
       
  4274             reader);
       
  4275     }
       
  4276     reader->xsdValidErrors = 0;
       
  4277     reader->validate = XML_TEXTREADER_VALIDATE_XSD;
       
  4278     return(0);
       
  4279 }
       
  4280 
       
  4281 /**
       
  4282  * xmlTextReaderRelaxNGValidate:
       
  4283  * @param reader the xmlTextReaderPtr used
       
  4284  * @param rng the path to a RelaxNG schema or NULL
       
  4285  *
       
  4286  * Use RelaxNG to validate the document as it is processed.
       
  4287  * Activation is only possible before the first Read().
       
  4288  * if rng is NULL, then RelaxNG validation is desactivated.
       
  4289  *
       
  4290  * Returns 0 in case the RelaxNG validation could be (des)activated and
       
  4291  *         -1 in case of error.
       
  4292  */
       
  4293 int
       
  4294 xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng)
       
  4295 {
       
  4296     xmlRelaxNGParserCtxtPtr ctxt;
       
  4297 
       
  4298     if (reader == NULL)
       
  4299         return(-1);
       
  4300 
       
  4301     if (rng == NULL) {
       
  4302         if (reader->rngValidCtxt != NULL) {
       
  4303             xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
       
  4304             reader->rngValidCtxt = NULL;
       
  4305         }
       
  4306         if (reader->rngSchemas != NULL) {
       
  4307         xmlRelaxNGFree(reader->rngSchemas);
       
  4308         reader->rngSchemas = NULL;
       
  4309         }
       
  4310         return(0);
       
  4311     }
       
  4312     if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
       
  4313         return(-1);
       
  4314     if (reader->rngSchemas != NULL) {
       
  4315         xmlRelaxNGFree(reader->rngSchemas);
       
  4316         reader->rngSchemas = NULL;
       
  4317     }
       
  4318     if (reader->rngValidCtxt != NULL) {
       
  4319         xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
       
  4320         reader->rngValidCtxt = NULL;
       
  4321     }
       
  4322     ctxt = xmlRelaxNGNewParserCtxt(rng);
       
  4323     if (reader->errorFunc != NULL) {
       
  4324         xmlRelaxNGSetParserErrors(ctxt,
       
  4325              xmlTextReaderValidityErrorRelay,
       
  4326              xmlTextReaderValidityWarningRelay,
       
  4327              reader);
       
  4328     }
       
  4329     if (reader->sErrorFunc != NULL) {
       
  4330         xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
       
  4331             xmlTextReaderValidityStructuredRelay,
       
  4332             reader);
       
  4333     }
       
  4334     reader->rngSchemas = xmlRelaxNGParse(ctxt);
       
  4335     xmlRelaxNGFreeParserCtxt(ctxt);
       
  4336     if (reader->rngSchemas == NULL)
       
  4337         return(-1);
       
  4338     reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
       
  4339     if (reader->rngValidCtxt == NULL) {
       
  4340     xmlRelaxNGFree(reader->rngSchemas);
       
  4341     reader->rngSchemas = NULL;
       
  4342         return(-1);
       
  4343     }
       
  4344     if (reader->errorFunc != NULL) {
       
  4345         xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
       
  4346              xmlTextReaderValidityErrorRelay,
       
  4347              xmlTextReaderValidityWarningRelay,
       
  4348              reader);
       
  4349     }
       
  4350     if (reader->sErrorFunc != NULL) {
       
  4351         xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
       
  4352             xmlTextReaderValidityStructuredRelay,
       
  4353             reader);
       
  4354     }
       
  4355     reader->rngValidErrors = 0;
       
  4356     reader->rngFullNode = NULL;
       
  4357     reader->validate = XML_TEXTREADER_VALIDATE_RNG;
       
  4358     return(0);
       
  4359 }
       
  4360 
       
  4361 /**
       
  4362  * xmlTextReaderSchemaValidate:
       
  4363  * @param reader the xmlTextReaderPtr used
       
  4364  * @param xsd the path to a W3C XSD schema or NULL
       
  4365  *
       
  4366  * Use W3C XSD schema to validate the document as it is processed.
       
  4367  * Activation is only possible before the first Read().
       
  4368  * if xsd is NULL, then RelaxNG validation is desactivated.
       
  4369  *
       
  4370  * Returns 0 in case the schemas validation could be (des)activated and
       
  4371  *         -1 in case of error.
       
  4372  */
       
  4373 int
       
  4374 xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd) {
       
  4375     xmlSchemaParserCtxtPtr ctxt;
       
  4376 
       
  4377     if (reader == NULL)
       
  4378         return(-1);
       
  4379 
       
  4380     if (xsd == NULL) {
       
  4381     if (reader->xsdPlug != NULL) {
       
  4382         xmlSchemaSAXUnplug(reader->xsdPlug);
       
  4383         reader->xsdPlug = NULL;
       
  4384     }
       
  4385         if (reader->xsdSchemas != NULL) {
       
  4386         xmlSchemaFree(reader->xsdSchemas);
       
  4387         reader->xsdSchemas = NULL;
       
  4388     }
       
  4389         if (reader->xsdValidCtxt != NULL) {
       
  4390         xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
       
  4391         reader->xsdValidCtxt = NULL;
       
  4392         }
       
  4393     return(0);
       
  4394     }
       
  4395     if ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
       
  4396         (reader->ctxt == NULL))
       
  4397     return(-1);
       
  4398     if (reader->xsdPlug != NULL) {
       
  4399     xmlSchemaSAXUnplug(reader->xsdPlug);
       
  4400     reader->xsdPlug = NULL;
       
  4401     }
       
  4402     if (reader->xsdValidCtxt != NULL) {
       
  4403     xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
       
  4404     reader->xsdValidCtxt = NULL;
       
  4405     }
       
  4406     if (reader->xsdSchemas != NULL) {
       
  4407     xmlSchemaFree(reader->xsdSchemas);
       
  4408     reader->xsdSchemas = NULL;
       
  4409     }
       
  4410     ctxt = xmlSchemaNewParserCtxt(xsd);
       
  4411     if (reader->errorFunc != NULL) {
       
  4412     xmlSchemaSetParserErrors(ctxt,
       
  4413              xmlTextReaderValidityErrorRelay,
       
  4414              xmlTextReaderValidityWarningRelay,
       
  4415              reader);
       
  4416     }
       
  4417     reader->xsdSchemas = xmlSchemaParse(ctxt);
       
  4418     xmlSchemaFreeParserCtxt(ctxt);
       
  4419     if (reader->xsdSchemas == NULL)
       
  4420         return(-1);
       
  4421     reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
       
  4422     if (reader->xsdValidCtxt == NULL) {
       
  4423     xmlSchemaFree(reader->xsdSchemas);
       
  4424     reader->xsdSchemas = NULL;
       
  4425         return(-1);
       
  4426     }
       
  4427     reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
       
  4428                                        &(reader->ctxt->sax),
       
  4429                        &(reader->ctxt->userData));
       
  4430     if (reader->xsdPlug == NULL) {
       
  4431     xmlSchemaFree(reader->xsdSchemas);
       
  4432     reader->xsdSchemas = NULL;
       
  4433     xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
       
  4434     reader->xsdValidCtxt = NULL;
       
  4435     return(-1);
       
  4436     }
       
  4437     if (reader->errorFunc != NULL) {
       
  4438     xmlSchemaSetValidErrors(reader->xsdValidCtxt,
       
  4439              xmlTextReaderValidityErrorRelay,
       
  4440              xmlTextReaderValidityWarningRelay,
       
  4441              reader);
       
  4442     }
       
  4443     if (reader->sErrorFunc != NULL) {
       
  4444         xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
       
  4445             xmlTextReaderValidityStructuredRelay,
       
  4446             reader);
       
  4447     }
       
  4448     reader->xsdValidErrors = 0;
       
  4449     reader->validate = XML_TEXTREADER_VALIDATE_XSD;
       
  4450     return(0);
       
  4451 }
       
  4452 #endif
       
  4453 
       
  4454 /**
       
  4455  * xmlTextReaderIsNamespaceDecl:
       
  4456  * @param reader the xmlTextReaderPtr used
       
  4457  *
       
  4458  * Determine whether the current node is a namespace declaration
       
  4459  * rather than a regular attribute.
       
  4460  *
       
  4461  * Returns 1 if the current node is a namespace declaration, 0 if it
       
  4462  * is a regular attribute or other type of node, or -1 in case of
       
  4463  * error.
       
  4464  */
       
  4465 XMLPUBFUNEXPORT int
       
  4466 xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
       
  4467     xmlNodePtr node;
       
  4468     if (reader == NULL)
       
  4469     return(-1);
       
  4470     if (reader->node == NULL)
       
  4471     return(-1);
       
  4472     if (reader->curnode != NULL)
       
  4473     node = reader->curnode;
       
  4474     else
       
  4475     node = reader->node;
       
  4476 
       
  4477     if (XML_NAMESPACE_DECL == node->type)
       
  4478     return(1);
       
  4479     else
       
  4480     return(0);
       
  4481 }
       
  4482 
       
  4483 /**
       
  4484  * xmlTextReaderConstXmlVersion:
       
  4485  * @param reader the xmlTextReaderPtr used
       
  4486  *
       
  4487  * Determine the XML version of the document being read.
       
  4488  *
       
  4489  * Returns a string containing the XML version of the document or NULL
       
  4490  * in case of error.  The string is deallocated with the reader.
       
  4491  */
       
  4492 XMLPUBFUNEXPORT const xmlChar *
       
  4493 xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
       
  4494     xmlDocPtr doc = NULL;
       
  4495     if (reader == NULL)
       
  4496     return(NULL);
       
  4497     if (reader->doc != NULL)
       
  4498         doc = reader->doc;
       
  4499     else if (reader->ctxt != NULL)
       
  4500     doc = reader->ctxt->myDoc;
       
  4501     if (doc == NULL)
       
  4502     return(NULL);
       
  4503 
       
  4504     if (doc->version == NULL)
       
  4505     return(NULL);
       
  4506     else
       
  4507       return(CONSTSTR(doc->version));
       
  4508 }
       
  4509 
       
  4510 /**
       
  4511  * xmlTextReaderStandalone:
       
  4512  * @param reader the xmlTextReaderPtr used
       
  4513  *
       
  4514  * Determine the standalone status of the document being read.
       
  4515  *
       
  4516  * Returns 1 if the document was declared to be standalone, 0 if it
       
  4517  * was declared to be not standalone, or -1 if the document did not
       
  4518  * specify its standalone status or in case of error.
       
  4519  */
       
  4520 XMLPUBFUNEXPORT int
       
  4521 xmlTextReaderStandalone(xmlTextReaderPtr reader) {
       
  4522     xmlDocPtr doc = NULL;
       
  4523     if (reader == NULL)
       
  4524     return(-1);
       
  4525     if (reader->doc != NULL)
       
  4526         doc = reader->doc;
       
  4527     else if (reader->ctxt != NULL)
       
  4528     doc = reader->ctxt->myDoc;
       
  4529     if (doc == NULL)
       
  4530     return(-1);
       
  4531 
       
  4532     return(doc->standalone);
       
  4533 }
       
  4534 
       
  4535 /************************************************************************
       
  4536  *                                                                      *
       
  4537  *          Error Handling Extensions                                   *
       
  4538  *                                                                      *
       
  4539  ************************************************************************/
       
  4540 
       
  4541 /* helper to build a xmlMalloc'ed string from a format and va_list */
       
  4542 static char*
       
  4543 xmlTextReaderBuildMessage(const char *msg, va_list ap)
       
  4544 {
       
  4545     int size;
       
  4546     int chars;
       
  4547     char* larger;
       
  4548     char* str;
       
  4549 
       
  4550     str = (char*) xmlMallocAtomic(150);
       
  4551     if (str == NULL) {
       
  4552         xmlGenericError(xmlGenericErrorContext, EMBED_ERRTXT("xmlMalloc failed !\n"));
       
  4553         return NULL;
       
  4554     }
       
  4555 
       
  4556     size = 150;
       
  4557 
       
  4558     while (1)
       
  4559     {
       
  4560         chars = vsnprintf(str, size, msg, ap);
       
  4561         if ((chars > -1) && (chars < size))
       
  4562             break;
       
  4563         if (chars > -1)
       
  4564             size += chars + 1;
       
  4565         else
       
  4566             size += 100;
       
  4567         if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
       
  4568             xmlGenericError(xmlGenericErrorContext, EMBED_ERRTXT("xmlRealloc failed !\n"));
       
  4569             xmlFree(str);
       
  4570             return NULL;
       
  4571         }
       
  4572         str = larger;
       
  4573     }
       
  4574 
       
  4575     return str;
       
  4576 }
       
  4577 
       
  4578 #ifdef LIBXML_ENABLE_NODE_LINEINFO
       
  4579 /**
       
  4580  * xmlTextReaderLocatorLineNumber:
       
  4581  * @param locator the xmlTextReaderLocatorPtr used
       
  4582  *
       
  4583  * Obtain the line number for the given locator.
       
  4584  *
       
  4585  * Returns the line number or -1 in case of error.
       
  4586  */
       
  4587 int
       
  4588 xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator)
       
  4589 {
       
  4590     /* we know that locator is a xmlParserCtxtPtr */
       
  4591     xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
       
  4592     int ret = -1;
       
  4593 
       
  4594     if (locator == NULL)
       
  4595         return(-1);
       
  4596     if (ctx->node != NULL) {
       
  4597         ret = xmlGetLineNo(ctx->node);
       
  4598     }
       
  4599     else {
       
  4600         /* inspired from error.c */
       
  4601         xmlParserInputPtr input;
       
  4602         input = ctx->input;
       
  4603         if ((input->filename == NULL) && (ctx->inputNr > 1))
       
  4604             input = ctx->inputTab[ctx->inputNr - 2];
       
  4605         if (input != NULL) {
       
  4606             ret = input->line;
       
  4607         }
       
  4608         else {
       
  4609             ret = -1;
       
  4610         }
       
  4611     }
       
  4612 
       
  4613     return ret;
       
  4614 }
       
  4615 #endif /* LIBXML_ENABLE_NODE_LINEINFO */
       
  4616 
       
  4617 /**
       
  4618  * xmlTextReaderLocatorBaseURI:
       
  4619  * @param locator the xmlTextReaderLocatorPtr used
       
  4620  *
       
  4621  * Obtain the base URI for the given locator.
       
  4622  *
       
  4623  * Returns the base URI or NULL in case of error.
       
  4624  */
       
  4625 XMLPUBFUNEXPORT xmlChar *
       
  4626 xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator)
       
  4627 {
       
  4628     /* we know that locator is a xmlParserCtxtPtr */
       
  4629     xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
       
  4630     xmlChar *ret = NULL;
       
  4631 
       
  4632     if (locator == NULL)
       
  4633         return(NULL);
       
  4634     if (ctx->node != NULL) {
       
  4635         ret = xmlNodeGetBase(NULL,ctx->node);
       
  4636     }
       
  4637     else
       
  4638     {
       
  4639         /* inspired from error.c */
       
  4640         xmlParserInputPtr input;
       
  4641         input = ctx->input;
       
  4642         if ((input->filename == NULL) && (ctx->inputNr > 1))
       
  4643             input = ctx->inputTab[ctx->inputNr - 2];
       
  4644         if (input != NULL) {
       
  4645             ret = xmlStrdup(BAD_CAST input->filename);
       
  4646         }
       
  4647         else {
       
  4648             ret = NULL;
       
  4649         }
       
  4650     }
       
  4651 
       
  4652     return ret;
       
  4653 }
       
  4654 
       
  4655 static void
       
  4656 xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, char *str)
       
  4657 {
       
  4658     xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)ctxt;
       
  4659     xmlTextReaderPtr reader = (xmlTextReaderPtr)ctx->_private;
       
  4660 
       
  4661     if (str != NULL) {
       
  4662       if (reader->errorFunc)
       
  4663         reader->errorFunc(reader->errorFuncArg,
       
  4664                           str,
       
  4665                           severity,
       
  4666                           (xmlTextReaderLocatorPtr)ctx);
       
  4667 
       
  4668     if (str != NULL) { // NOTE: no this check in the latest open-source version
       
  4669         xmlFree(str);
       
  4670     }
       
  4671     }
       
  4672 }
       
  4673 
       
  4674 static void
       
  4675 xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error)
       
  4676 {
       
  4677     xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
       
  4678     xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
       
  4679 
       
  4680     if (error && reader->sErrorFunc) {
       
  4681         reader->sErrorFunc(reader->errorFuncArg,
       
  4682                       (xmlErrorPtr) error);
       
  4683     }
       
  4684 }
       
  4685 
       
  4686 
       
  4687 static void /* XMLCDECL */
       
  4688 xmlTextReaderError(void *ctxt, const char *msg, ...)
       
  4689 {
       
  4690     va_list ap;
       
  4691 
       
  4692     va_start(ap,msg);
       
  4693     xmlTextReaderGenericError(ctxt,
       
  4694                               XML_PARSER_SEVERITY_ERROR,
       
  4695                               xmlTextReaderBuildMessage(msg,ap));
       
  4696     va_end(ap);
       
  4697 
       
  4698 }
       
  4699 
       
  4700 
       
  4701 static void /* XMLCDECL */
       
  4702 xmlTextReaderWarning(void *ctxt, const char *msg, ...)
       
  4703 {
       
  4704     va_list ap;
       
  4705 
       
  4706     va_start(ap,msg);
       
  4707     xmlTextReaderGenericError(ctxt,
       
  4708                               XML_PARSER_SEVERITY_WARNING,
       
  4709                               xmlTextReaderBuildMessage(msg,ap));
       
  4710     va_end(ap);
       
  4711 }
       
  4712 
       
  4713 
       
  4714 static void /* XMLCDECL */
       
  4715 xmlTextReaderValidityError(void *ctxt, const char *msg, ...)
       
  4716 {
       
  4717     va_list ap;
       
  4718     int len = xmlStrlen((const xmlChar *) msg);
       
  4719 
       
  4720     if ((len > 1) && (msg[len - 2] != ':'))
       
  4721     {
       
  4722         /*
       
  4723          * some callbacks only report locator information:
       
  4724          * skip them (mimicking behaviour in error.c)
       
  4725          */
       
  4726         va_start(ap,msg);
       
  4727         xmlTextReaderGenericError(ctxt,
       
  4728                                   XML_PARSER_SEVERITY_VALIDITY_ERROR,
       
  4729                                   xmlTextReaderBuildMessage(msg,ap));
       
  4730         va_end(ap);
       
  4731     }
       
  4732 }
       
  4733 
       
  4734 
       
  4735 static void /* XMLCDECL */
       
  4736 xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...)
       
  4737 {
       
  4738     va_list ap;
       
  4739     int len = xmlStrlen((const xmlChar *) msg);
       
  4740 
       
  4741     if ((len != 0) && (msg[len - 1] != ':'))
       
  4742     {
       
  4743         /*
       
  4744          * some callbacks only report locator information:
       
  4745          * skip them (mimicking behaviour in error.c)
       
  4746          */
       
  4747         va_start(ap,msg);
       
  4748         xmlTextReaderGenericError(ctxt,
       
  4749                                   XML_PARSER_SEVERITY_VALIDITY_WARNING,
       
  4750                                   xmlTextReaderBuildMessage(msg,ap));
       
  4751         va_end(ap);
       
  4752     }
       
  4753 }
       
  4754 
       
  4755 /**
       
  4756  * xmlTextReaderSetErrorHandler:
       
  4757  * @param reader the xmlTextReaderPtr used
       
  4758  * @param f the callback function to call on error and warnings
       
  4759  * @param arg a user argument to pass to the callback function
       
  4760  *
       
  4761  * Register a callback function that will be called on error and warnings.
       
  4762  *
       
  4763  * If f is NULL, the default error and warning handlers are restored.
       
  4764  */
       
  4765 XMLPUBFUNEXPORT void
       
  4766 xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
       
  4767                  xmlTextReaderErrorFunc f,
       
  4768                  void *arg)
       
  4769 {
       
  4770     if (f != NULL)
       
  4771     {
       
  4772         reader->ctxt->sax->error = xmlTextReaderError;
       
  4773         reader->ctxt->sax->serror = NULL;
       
  4774         reader->ctxt->vctxt.error = xmlTextReaderValidityError;
       
  4775         reader->ctxt->sax->warning = xmlTextReaderWarning;
       
  4776         reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
       
  4777         reader->errorFunc = f;
       
  4778         reader->sErrorFunc = NULL;
       
  4779         reader->errorFuncArg = arg;
       
  4780 #ifdef LIBXML_SCHEMAS_ENABLED
       
  4781         if (reader->rngValidCtxt) {
       
  4782             xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
       
  4783                  xmlTextReaderValidityErrorRelay,
       
  4784                  xmlTextReaderValidityWarningRelay,
       
  4785                  reader);
       
  4786             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
       
  4787         }
       
  4788         if (reader->xsdValidCtxt) {
       
  4789             xmlSchemaSetValidErrors(reader->xsdValidCtxt,
       
  4790                  xmlTextReaderValidityErrorRelay,
       
  4791                  xmlTextReaderValidityWarningRelay,
       
  4792                  reader);
       
  4793             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
       
  4794         }
       
  4795 #endif
       
  4796     }
       
  4797     else {
       
  4798         /* restore defaults */
       
  4799         reader->ctxt->sax->error = xmlParserError;
       
  4800         reader->ctxt->vctxt.error = xmlParserValidityError;
       
  4801         reader->ctxt->sax->warning = xmlParserWarning;
       
  4802         reader->ctxt->vctxt.warning = xmlParserValidityWarning;
       
  4803         reader->errorFunc = NULL;
       
  4804         reader->sErrorFunc = NULL;
       
  4805         reader->errorFuncArg = NULL;
       
  4806 #ifdef LIBXML_SCHEMAS_ENABLED
       
  4807         if (reader->rngValidCtxt) {
       
  4808             xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
       
  4809             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
       
  4810         }
       
  4811         if (reader->xsdValidCtxt) {
       
  4812             xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
       
  4813             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
       
  4814         }
       
  4815 #endif
       
  4816     }
       
  4817 }
       
  4818 
       
  4819 /**
       
  4820 * xmlTextReaderSetStructuredErrorHandler:
       
  4821  * @param reader the xmlTextReaderPtr used
       
  4822  * @param f the callback function to call on error and warnings
       
  4823  * @param arg a user argument to pass to the callback function
       
  4824  *
       
  4825  * Register a callback function that will be called on error and warnings.
       
  4826  *
       
  4827  * If f is NULL, the default error and warning handlers are restored.
       
  4828  */
       
  4829 XMLPUBFUNEXPORT void
       
  4830 xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
       
  4831                      xmlStructuredErrorFunc f,
       
  4832                      void *arg)
       
  4833 {
       
  4834   if (f != NULL) {
       
  4835         reader->ctxt->sax->error = NULL;
       
  4836         reader->ctxt->sax->serror = xmlTextReaderStructuredError;
       
  4837         reader->ctxt->vctxt.error = xmlTextReaderValidityError;
       
  4838         reader->ctxt->sax->warning = xmlTextReaderWarning;
       
  4839         reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
       
  4840         reader->sErrorFunc = f;
       
  4841         reader->errorFunc = NULL;
       
  4842         reader->errorFuncArg = arg;
       
  4843 #ifdef LIBXML_SCHEMAS_ENABLED
       
  4844         if (reader->rngValidCtxt) {
       
  4845             xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
       
  4846             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
       
  4847                 xmlTextReaderValidityStructuredRelay,
       
  4848                 reader);
       
  4849         }
       
  4850         if (reader->xsdValidCtxt) {
       
  4851             xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
       
  4852             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
       
  4853                 xmlTextReaderValidityStructuredRelay,
       
  4854                 reader);
       
  4855         }
       
  4856 #endif
       
  4857   }
       
  4858   else {
       
  4859         /* restore defaults */
       
  4860         reader->ctxt->sax->error = xmlParserError;
       
  4861         reader->ctxt->sax->serror = NULL;
       
  4862         reader->ctxt->vctxt.error = xmlParserValidityError;
       
  4863         reader->ctxt->sax->warning = xmlParserWarning;
       
  4864         reader->ctxt->vctxt.warning = xmlParserValidityWarning;
       
  4865         reader->errorFunc = NULL;
       
  4866         reader->sErrorFunc = NULL;
       
  4867         reader->errorFuncArg = NULL;
       
  4868 #ifdef LIBXML_SCHEMAS_ENABLED
       
  4869         if (reader->rngValidCtxt) {
       
  4870             xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
       
  4871             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
       
  4872         }
       
  4873         if (reader->xsdValidCtxt) {
       
  4874             xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
       
  4875             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
       
  4876         }
       
  4877 #endif
       
  4878   }
       
  4879 }
       
  4880 
       
  4881 /**
       
  4882  * xmlTextReaderIsValid:
       
  4883  * @param reader the xmlTextReaderPtr used
       
  4884  *
       
  4885  * Retrieve the validity status from the parser context
       
  4886  *
       
  4887  * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
       
  4888  */
       
  4889 XMLPUBFUNEXPORT int
       
  4890 xmlTextReaderIsValid(xmlTextReaderPtr reader)
       
  4891 {
       
  4892     if (reader == NULL) return(-1);
       
  4893 #ifdef LIBXML_SCHEMAS_ENABLED
       
  4894     if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
       
  4895         return(reader->rngValidErrors == 0);
       
  4896     if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
       
  4897         return(reader->xsdValidErrors == 0);
       
  4898 #endif
       
  4899     if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
       
  4900         return(reader->ctxt->valid);
       
  4901     return(0);
       
  4902 }
       
  4903 
       
  4904 /**
       
  4905  * xmlTextReaderGetErrorHandler:
       
  4906  * @param reader the xmlTextReaderPtr used
       
  4907  * @param f the callback function or NULL is no callback has been registered
       
  4908  * @param arg a user argument
       
  4909  *
       
  4910  * Retrieve the error callback function and user argument.
       
  4911  */
       
  4912 XMLPUBFUNEXPORT void
       
  4913 xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
       
  4914                  xmlTextReaderErrorFunc *f,
       
  4915                  void **arg)
       
  4916 {
       
  4917     if (f != NULL) *f = reader->errorFunc;
       
  4918     if (arg != NULL) *arg = reader->errorFuncArg;
       
  4919 }
       
  4920 
       
  4921 
       
  4922 /************************************************************************
       
  4923  *                                                                      *
       
  4924  *  New set (2.6.0) of simpler and more flexible APIs                   *
       
  4925  *                                                                      *
       
  4926  ************************************************************************/
       
  4927 
       
  4928 /**
       
  4929  * xmlTextReaderSetup:
       
  4930  * @param reader an XML reader
       
  4931  * @param URL the base URL to use for the document
       
  4932  * @param encoding the document encoding, or NULL
       
  4933  * @param options a combination of xmlParserOption
       
  4934  * @param reuse keep the context for reuse
       
  4935  *
       
  4936  * Setup an XML reader with new options
       
  4937  *
       
  4938  * Returns 0 in case of success and -1 in case of error.
       
  4939  */
       
  4940 static int
       
  4941 xmlTextReaderSetup(xmlTextReaderPtr reader,
       
  4942                    xmlParserInputBufferPtr input, const char *URL,
       
  4943                    const char *encoding, int options)
       
  4944 {	
       
  4945     if (reader == NULL)
       
  4946         return (-1);
       
  4947 
       
  4948     /*
       
  4949      * we force the generation of compact text nodes on the reader
       
  4950      * since usr applications should never modify the tree
       
  4951      */
       
  4952      // XMLENGINE:  Enable when whole libxml2 is updated from open-source
       
  4953     //options |= XML_PARSE_COMPACT;
       
  4954 
       
  4955     reader->doc = NULL;
       
  4956     reader->entNr = 0;
       
  4957     reader->parserFlags = options;
       
  4958     reader->validate = XML_TEXTREADER_NOT_VALIDATE;
       
  4959     if ((input != NULL) && (reader->input != NULL) &&
       
  4960         (reader->allocs & XML_TEXTREADER_INPUT))
       
  4961     {
       
  4962         xmlFreeParserInputBuffer(reader->input);
       
  4963         reader->input = NULL;
       
  4964         reader->allocs -= XML_TEXTREADER_INPUT;
       
  4965     }
       
  4966     if (input != NULL) {
       
  4967         reader->input = input;
       
  4968         reader->allocs |= XML_TEXTREADER_INPUT;
       
  4969     }
       
  4970     if (reader->buffer == NULL)
       
  4971         reader->buffer = xmlBufferCreateSize(100);
       
  4972     if (reader->buffer == NULL) {
       
  4973         xmlGenericError(xmlGenericErrorContext,
       
  4974                         EMBED_ERRTXT("xmlTextReaderSetup : malloc failed\n"));
       
  4975         return (-1);
       
  4976     }
       
  4977     if (reader->sax == NULL)
       
  4978         reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
       
  4979     if (reader->sax == NULL) {
       
  4980         xmlGenericError(xmlGenericErrorContext,
       
  4981                         EMBED_ERRTXT("xmlTextReaderSetup : malloc failed\n"));
       
  4982         return (-1);
       
  4983     }
       
  4984     xmlSAXVersion(reader->sax, 2);
       
  4985     reader->startElement = reader->sax->startElement;
       
  4986     reader->sax->startElement = xmlTextReaderStartElement;
       
  4987     reader->endElement = reader->sax->endElement;
       
  4988     reader->sax->endElement = xmlTextReaderEndElement;
       
  4989 #ifdef LIBXML_SAX1_ENABLED
       
  4990     if (reader->sax->initialized == XML_SAX2_MAGIC) {
       
  4991 #endif /* LIBXML_SAX1_ENABLED */
       
  4992         reader->startElementNs = reader->sax->startElementNs;
       
  4993         reader->sax->startElementNs = xmlTextReaderStartElementNs;
       
  4994         reader->endElementNs = reader->sax->endElementNs;
       
  4995         reader->sax->endElementNs = xmlTextReaderEndElementNs;
       
  4996 #ifdef LIBXML_SAX1_ENABLED
       
  4997     } else {
       
  4998         reader->startElementNs = NULL;
       
  4999         reader->endElementNs = NULL;
       
  5000     }
       
  5001 #endif /* LIBXML_SAX1_ENABLED */
       
  5002     reader->characters = reader->sax->characters;
       
  5003     reader->sax->characters = xmlTextReaderCharacters;
       
  5004     reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
       
  5005     reader->cdataBlock = reader->sax->cdataBlock;
       
  5006     reader->sax->cdataBlock = xmlTextReaderCDataBlock;
       
  5007 
       
  5008     reader->mode = XML_TEXTREADER_MODE_INITIAL;
       
  5009     reader->node = NULL;
       
  5010     reader->curnode = NULL;
       
  5011     if (input)
       
  5012     {
       
  5013         if (reader->input->buffer->use < 4) {
       
  5014             xmlParserInputBufferRead(input, 4);
       
  5015         }
       
  5016         if (reader->ctxt == NULL) {
       
  5017             if (reader->input->buffer->use >= 4) {
       
  5018                 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
       
  5019                         (const char*) reader->input->buffer->content,
       
  5020                         4, URL);
       
  5021                 reader->base = 0;
       
  5022                 reader->cur = 4;
       
  5023             } else {
       
  5024                 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
       
  5025                 reader->base = 0;
       
  5026                 reader->cur = 0;
       
  5027             }
       
  5028         } else {
       
  5029             xmlParserInputPtr inputStream;
       
  5030             xmlParserInputBufferPtr buf;
       
  5031             xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
       
  5032 
       
  5033             xmlCtxtReset(reader->ctxt);
       
  5034             buf = xmlAllocParserInputBuffer(enc);
       
  5035             if (buf == NULL)
       
  5036                 return(-1);
       
  5037             inputStream = xmlNewInputStream(reader->ctxt);
       
  5038             if (inputStream == NULL) {
       
  5039                 xmlFreeParserInputBuffer(buf);
       
  5040                 return(-1);
       
  5041             }
       
  5042 
       
  5043             if (URL == NULL)
       
  5044                 inputStream->filename = NULL;
       
  5045             else
       
  5046                 inputStream->filename = (char*)
       
  5047                     xmlCanonicPath((const xmlChar*) URL);
       
  5048             inputStream->buf = buf;
       
  5049             inputStream->base = inputStream->buf->buffer->content;
       
  5050             inputStream->cur = inputStream->buf->buffer->content;
       
  5051             inputStream->end = &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
       
  5052 
       
  5053             inputPush(reader->ctxt, inputStream);
       
  5054             reader->cur = 0;
       
  5055         }
       
  5056         if (reader->ctxt == NULL) {
       
  5057             xmlGenericError(xmlGenericErrorContext,
       
  5058                             EMBED_ERRTXT("xmlTextReaderSetup : malloc failed\n"));
       
  5059             return (-1);
       
  5060         }
       
  5061     } // end if (input)
       
  5062 
       
  5063     if (reader->dict != NULL) {
       
  5064         if (reader->ctxt->dict != NULL) {
       
  5065             if (reader->dict != reader->ctxt->dict) {
       
  5066                 xmlDictFree(reader->dict);
       
  5067                 reader->dict = reader->ctxt->dict;
       
  5068             }
       
  5069         } else {
       
  5070             reader->ctxt->dict = reader->dict;
       
  5071         }
       
  5072     } else {
       
  5073         if (reader->ctxt->dict == NULL)
       
  5074             reader->ctxt->dict = xmlDictCreate();
       
  5075         reader->dict = reader->ctxt->dict;
       
  5076     }
       
  5077     reader->ctxt->_private = reader;
       
  5078 #ifdef LIBXML_ENABLE_NODE_LINEINFO
       
  5079     reader->ctxt->linenumbers = 1;
       
  5080 #endif
       
  5081     reader->ctxt->dictNames = 1;
       
  5082     /*
       
  5083      * use the parser dictionnary to allocate all elements and attributes names
       
  5084      */
       
  5085     reader->ctxt->docdict = 1;
       
  5086     
       
  5087     //reader->ctxt->parseMode = XML_PARSE_READER;
       
  5088 
       
  5089 #ifdef LIBXML_XINCLUDE_ENABLED
       
  5090     if (reader->xincctxt != NULL) {
       
  5091         xmlXIncludeFreeContext(reader->xincctxt);
       
  5092         reader->xincctxt = NULL;
       
  5093     }
       
  5094     if (options & XML_PARSE_XINCLUDE) {
       
  5095         reader->xinclude = 1;
       
  5096         reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
       
  5097         options -= XML_PARSE_XINCLUDE;
       
  5098     } else {
       
  5099         reader->xinclude = 0;
       
  5100     }
       
  5101     reader->in_xinclude = 0;
       
  5102 #endif
       
  5103 #ifdef LIBXML_PATTERN_ENABLED
       
  5104     if (reader->patternTab == NULL) {
       
  5105         reader->patternNr = 0;
       
  5106         reader->patternMax = 0;
       
  5107     }
       
  5108     while (reader->patternNr > 0) {
       
  5109         reader->patternNr--;
       
  5110         if (reader->patternTab[reader->patternNr] != NULL) {
       
  5111             xmlFreePattern(reader->patternTab[reader->patternNr]);
       
  5112             reader->patternTab[reader->patternNr] = NULL;
       
  5113         }
       
  5114     }
       
  5115 #endif
       
  5116 
       
  5117     if (options & XML_PARSE_DTDVALID)
       
  5118         reader->validate = XML_TEXTREADER_VALIDATE_DTD;
       
  5119 
       
  5120     xmlCtxtUseOptions(reader->ctxt, options);
       
  5121     if (encoding != NULL) {
       
  5122         xmlCharEncodingHandlerPtr hdlr;
       
  5123 
       
  5124         hdlr = xmlFindCharEncodingHandler(encoding);
       
  5125         if (hdlr != NULL)
       
  5126             xmlSwitchToEncoding(reader->ctxt, hdlr);
       
  5127     }
       
  5128     if ((URL != NULL) && (reader->ctxt->input != NULL) &&
       
  5129         (reader->ctxt->input->filename == NULL))
       
  5130     {
       
  5131         reader->ctxt->input->filename = (char*)xmlStrdup((const xmlChar*) URL);
       
  5132     }
       
  5133 
       
  5134     reader->doc = NULL;
       
  5135 
       
  5136     return (0);
       
  5137 }
       
  5138 
       
  5139 /**
       
  5140  * xmlTextReaderByteConsumed:
       
  5141  * @param reader an XML reader
       
  5142  *
       
  5143  * This function provides the current index of the parser used
       
  5144  * by the reader, relative to the start of the current entity.
       
  5145  * This function actually just wraps a call to xmlBytesConsumed()
       
  5146  * for the parser context associated with the reader.
       
  5147  * See xmlBytesConsumed() for more information.
       
  5148  *
       
  5149  * Returns the index in bytes from the beginning of the entity or -1
       
  5150  *         in case the index could not be computed.
       
  5151  */
       
  5152 XMLPUBFUNEXPORT long
       
  5153 xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
       
  5154     if ((reader == NULL) || (reader->ctxt == NULL))
       
  5155         return(-1);
       
  5156     
       
  5157     //return(xmlByteConsumed(reader->ctxt));
       
  5158     return 0;
       
  5159 }
       
  5160 
       
  5161 
       
  5162 /**
       
  5163  * xmlReaderWalker:
       
  5164  * @param doc a preparsed document
       
  5165  *
       
  5166  * Create an xmltextReader for a preparsed document.
       
  5167  *
       
  5168  * Returns the new reader or NULL in case of error.
       
  5169  */
       
  5170 XMLPUBFUNEXPORT xmlTextReaderPtr
       
  5171 xmlReaderWalker(xmlDocPtr doc)
       
  5172 {
       
  5173     xmlTextReaderPtr ret;
       
  5174 
       
  5175     if (doc == NULL)
       
  5176         return(NULL);
       
  5177 
       
  5178     ret = xmlMalloc(sizeof(xmlTextReader));
       
  5179     if (ret == NULL) {
       
  5180         xmlGenericError(xmlGenericErrorContext,
       
  5181                 EMBED_ERRTXT("xmlNewTextReader : malloc failed\n"));
       
  5182         return(NULL);
       
  5183     }
       
  5184     memset(ret, 0, sizeof(xmlTextReader));
       
  5185     //ret->entNr = 0;
       
  5186     //ret->input = NULL;
       
  5187     ret->mode = XML_TEXTREADER_MODE_INITIAL;
       
  5188     //ret->node = NULL;
       
  5189     //ret->curnode = NULL;
       
  5190     //ret->base = 0;
       
  5191     //ret->cur = 0;
       
  5192     ret->allocs = XML_TEXTREADER_CTXT;
       
  5193     ret->doc = doc;
       
  5194     ret->state = XML_TEXTREADER_START;
       
  5195     ret->dict = xmlDictCreate();
       
  5196     return(ret);
       
  5197 }
       
  5198 
       
  5199 /**
       
  5200  * xmlReaderForDoc:
       
  5201  * @param cur a pointer to a zero terminated string
       
  5202  * @param URL the base URL to use for the document
       
  5203  * @param encoding the document encoding, or NULL
       
  5204  * @param options a combination of xmlParserOption
       
  5205  *
       
  5206  * Create an xmltextReader for an XML in-memory document.
       
  5207  * The parsing flags options are a combination of xmlParserOption.
       
  5208  *
       
  5209  * Returns the new reader or NULL in case of error.
       
  5210  */
       
  5211 XMLPUBFUNEXPORT xmlTextReaderPtr
       
  5212 xmlReaderForDoc(const xmlChar* cur, const char* URL, const char* encoding, int options)
       
  5213 {
       
  5214     int len;
       
  5215 
       
  5216     if (cur == NULL)
       
  5217         return (NULL);
       
  5218     len = xmlStrlen(cur); 
       
  5219 
       
  5220     return xmlReaderForMemory((const char*) cur, len, URL, encoding, options);
       
  5221 }
       
  5222 
       
  5223 /**
       
  5224  * xmlReaderForFile:
       
  5225  * @param filename a file or URL
       
  5226  * @param encoding the document encoding, or NULL
       
  5227  * @param options a combination of xmlParserOption
       
  5228  *
       
  5229  * parse an XML file from the filesystem or the network.
       
  5230  * The parsing flags options are a combination of xmlParserOption.
       
  5231  *
       
  5232  * Returns the new reader or NULL in case of error.
       
  5233  */
       
  5234 XMLPUBFUNEXPORT xmlTextReaderPtr
       
  5235 xmlReaderForFile(const char *filename, const char *encoding, int options)
       
  5236 {
       
  5237     xmlTextReaderPtr reader;
       
  5238 
       
  5239     reader = xmlNewTextReaderFilename(filename);
       
  5240     if (reader == NULL)
       
  5241         return (NULL);
       
  5242     xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
       
  5243     return (reader);
       
  5244 }
       
  5245 
       
  5246 /**
       
  5247  * xmlReaderForMemory:
       
  5248  * @param buffer a pointer to a char array
       
  5249  * @param size the size of the array
       
  5250  * @param URL the base URL to use for the document
       
  5251  * @param encoding the document encoding, or NULL
       
  5252  * @param options a combination of xmlParserOption
       
  5253  *
       
  5254  * Create an xmltextReader for an XML in-memory document.
       
  5255  * The parsing flags options are a combination of xmlParserOption.
       
  5256  *
       
  5257  * Returns the new reader or NULL in case of error.
       
  5258  */
       
  5259 XMLPUBFUNEXPORT xmlTextReaderPtr
       
  5260 xmlReaderForMemory(const char *buffer, int size, const char *URL,
       
  5261                    const char *encoding, int options)
       
  5262 {
       
  5263     xmlTextReaderPtr reader;
       
  5264     xmlParserInputBufferPtr buf;
       
  5265 
       
  5266     buf = xmlParserInputBufferCreateStatic(buffer, size, XML_CHAR_ENCODING_NONE);
       
  5267     if (buf == NULL) {
       
  5268         return (NULL);
       
  5269     }
       
  5270     reader = xmlNewTextReader(buf, URL);
       
  5271     if (reader == NULL) {
       
  5272         xmlFreeParserInputBuffer(buf);
       
  5273         return (NULL);
       
  5274     }
       
  5275     reader->allocs |= XML_TEXTREADER_INPUT;
       
  5276     xmlTextReaderSetup(reader, NULL, URL, encoding, options);
       
  5277     return (reader);
       
  5278 }
       
  5279 
       
  5280 /**
       
  5281  * xmlReaderForFd:
       
  5282  * @param fd an open file descriptor
       
  5283  * @param URL the base URL to use for the document
       
  5284  * @param encoding the document encoding, or NULL
       
  5285  * @param options a combination of xmlParserOption
       
  5286  *
       
  5287  * Create an xmltextReader for an XML from a file descriptor.
       
  5288  * The parsing flags options are a combination of xmlParserOption.
       
  5289  * NOTE that the file descriptor will not be closed when the
       
  5290  *      reader is closed or reset.
       
  5291  *
       
  5292  * Returns the new reader or NULL in case of error.
       
  5293  */
       
  5294 XMLPUBFUNEXPORT xmlTextReaderPtr
       
  5295 xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
       
  5296 {
       
  5297     xmlTextReaderPtr reader;
       
  5298     xmlParserInputBufferPtr input;
       
  5299 
       
  5300     if (fd < 0)
       
  5301         return (NULL);
       
  5302 
       
  5303     input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
       
  5304     if (input == NULL)
       
  5305         return (NULL);
       
  5306     input->closecallback = NULL;
       
  5307     reader = xmlNewTextReader(input, URL);
       
  5308     if (reader == NULL) {
       
  5309         xmlFreeParserInputBuffer(input);
       
  5310         return (NULL);
       
  5311     }
       
  5312     reader->allocs |= XML_TEXTREADER_INPUT;
       
  5313     xmlTextReaderSetup(reader, NULL, URL, encoding, options);
       
  5314     return (reader);
       
  5315 }
       
  5316 
       
  5317 /**
       
  5318  * xmlReaderForIO:
       
  5319  * @param ioread an I/O read function
       
  5320  * @param ioclose an I/O close function
       
  5321  * @param ioctx an I/O handler
       
  5322  * @param URL the base URL to use for the document
       
  5323  * @param encoding the document encoding, or NULL
       
  5324  * @param options a combination of xmlParserOption
       
  5325  *
       
  5326  * Create an xmltextReader for an XML document from I/O functions and source.
       
  5327  * The parsing flags options are a combination of xmlParserOption.
       
  5328  *
       
  5329  * Returns the new reader or NULL in case of error.
       
  5330  */
       
  5331 XMLPUBFUNEXPORT xmlTextReaderPtr
       
  5332 xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
       
  5333                void *ioctx, const char *URL, const char *encoding,
       
  5334                int options)
       
  5335 {
       
  5336     xmlTextReaderPtr reader;
       
  5337     xmlParserInputBufferPtr input;
       
  5338 
       
  5339     if (ioread == NULL)
       
  5340         return (NULL);
       
  5341 
       
  5342     input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
       
  5343                                          XML_CHAR_ENCODING_NONE);
       
  5344     if (input == NULL)
       
  5345         return (NULL);
       
  5346     reader = xmlNewTextReader(input, URL);
       
  5347     if (reader == NULL) {
       
  5348         xmlFreeParserInputBuffer(input);
       
  5349         return (NULL);
       
  5350     }
       
  5351     reader->allocs |= XML_TEXTREADER_INPUT;
       
  5352     xmlTextReaderSetup(reader, NULL, URL, encoding, options);
       
  5353     return (reader);
       
  5354 }
       
  5355 
       
  5356 /**
       
  5357  * xmlReaderNewWalker:
       
  5358  * @param reader an XML reader
       
  5359  * @param doc a preparsed document
       
  5360  *
       
  5361  * Setup an xmltextReader to parse a preparsed XML document.
       
  5362  * This reuses the existing reader xmlTextReader.
       
  5363  *
       
  5364  * Returns 0 in case of success and -1 in case of error
       
  5365  */
       
  5366 XMLPUBFUNEXPORT int
       
  5367 xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
       
  5368 {
       
  5369     if (doc == NULL)
       
  5370         return (-1);
       
  5371     if (reader == NULL)
       
  5372         return (-1);
       
  5373 
       
  5374     if (reader->input != NULL) {
       
  5375         xmlFreeParserInputBuffer(reader->input);
       
  5376     }
       
  5377     if (reader->ctxt != NULL) {
       
  5378         xmlCtxtReset(reader->ctxt);
       
  5379     }
       
  5380 
       
  5381     reader->entNr = 0;
       
  5382     reader->input = NULL;
       
  5383     reader->mode = XML_TEXTREADER_MODE_INITIAL;
       
  5384     reader->node = NULL;
       
  5385     reader->curnode = NULL;
       
  5386     reader->base = 0;
       
  5387     reader->cur = 0;
       
  5388     reader->allocs = XML_TEXTREADER_CTXT;
       
  5389     reader->doc = doc;
       
  5390     reader->state = XML_TEXTREADER_START;
       
  5391     if (reader->dict == NULL) {
       
  5392         if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
       
  5393             reader->dict = reader->ctxt->dict;
       
  5394         else
       
  5395             reader->dict = xmlDictCreate();
       
  5396     }
       
  5397     return(0);
       
  5398 }
       
  5399 
       
  5400 /**
       
  5401  * xmlReaderNewDoc:
       
  5402  * @param reader an XML reader
       
  5403  * @param cur a pointer to a zero terminated string
       
  5404  * @param URL the base URL to use for the document
       
  5405  * @param encoding the document encoding, or NULL
       
  5406  * @param options a combination of xmlParserOption
       
  5407  *
       
  5408  * Setup an xmltextReader to parse an XML in-memory document.
       
  5409  * The parsing flags options are a combination of xmlParserOption.
       
  5410  * This reuses the existing reader xmlTextReader.
       
  5411  *
       
  5412  * Returns 0 in case of success and -1 in case of error
       
  5413  */
       
  5414 XMLPUBFUNEXPORT int
       
  5415 xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
       
  5416                 const char *URL, const char *encoding, int options)
       
  5417 {
       
  5418     int len;
       
  5419 
       
  5420     if (cur == NULL)
       
  5421         return (-1);
       
  5422     if (reader == NULL)
       
  5423         return (-1);
       
  5424 
       
  5425     len = xmlStrlen(cur);
       
  5426     return (xmlReaderNewMemory(reader, (const char *)cur, len,
       
  5427                                URL, encoding, options));
       
  5428 }
       
  5429 
       
  5430 /**
       
  5431  * xmlReaderNewFile:
       
  5432  * @param reader an XML reader
       
  5433  * @param filename a file or URL
       
  5434  * @param encoding the document encoding, or NULL
       
  5435  * @param options a combination of xmlParserOption
       
  5436  *
       
  5437  * parse an XML file from the filesystem or the network.
       
  5438  * The parsing flags options are a combination of xmlParserOption.
       
  5439  * This reuses the existing reader xmlTextReader.
       
  5440  *
       
  5441  * Returns 0 in case of success and -1 in case of error
       
  5442  */
       
  5443 XMLPUBFUNEXPORT int
       
  5444 xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
       
  5445                  const char *encoding, int options)
       
  5446 {
       
  5447     xmlParserInputBufferPtr input;
       
  5448 
       
  5449     if (filename == NULL)
       
  5450         return (-1);
       
  5451     if (reader == NULL)
       
  5452         return (-1);
       
  5453 
       
  5454     input = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
       
  5455     if (input == NULL)
       
  5456         return (-1);
       
  5457     return (xmlTextReaderSetup(reader, input, filename, encoding, options));
       
  5458 }
       
  5459 
       
  5460 /**
       
  5461  * xmlReaderNewMemory:
       
  5462  * @param reader an XML reader
       
  5463  * @param buffer a pointer to a char array
       
  5464  * @param size the size of the array
       
  5465  * @param URL the base URL to use for the document
       
  5466  * @param encoding the document encoding, or NULL
       
  5467  * @param options a combination of xmlParserOption
       
  5468  *
       
  5469  * Setup an xmltextReader to parse an XML in-memory document.
       
  5470  * The parsing flags options are a combination of xmlParserOption.
       
  5471  * This reuses the existing reader xmlTextReader.
       
  5472  *
       
  5473  * Returns 0 in case of success and -1 in case of error
       
  5474  */
       
  5475 XMLPUBFUNEXPORT int
       
  5476 xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
       
  5477                    const char *URL, const char *encoding, int options)
       
  5478 {
       
  5479     xmlParserInputBufferPtr input;
       
  5480 
       
  5481     if (reader == NULL)
       
  5482         return (-1);
       
  5483     if (buffer == NULL)
       
  5484         return (-1);
       
  5485 
       
  5486     input = xmlParserInputBufferCreateStatic(buffer, size, XML_CHAR_ENCODING_NONE);
       
  5487     if (input == NULL) {
       
  5488         return (-1);
       
  5489     }
       
  5490     return (xmlTextReaderSetup(reader, input, URL, encoding, options));
       
  5491 }
       
  5492 
       
  5493 /**
       
  5494  * xmlReaderNewFd:
       
  5495  * @param reader an XML reader
       
  5496  * @param fd an open file descriptor
       
  5497  * @param URL the base URL to use for the document
       
  5498  * @param encoding the document encoding, or NULL
       
  5499  * @param options a combination of xmlParserOption
       
  5500  *
       
  5501  * Setup an xmltextReader to parse an XML from a file descriptor.
       
  5502  * NOTE that the file descriptor will not be closed when the
       
  5503  *      reader is closed or reset.
       
  5504  * The parsing flags options are a combination of xmlParserOption.
       
  5505  * This reuses the existing reader xmlTextReader.
       
  5506  *
       
  5507  * Returns 0 in case of success and -1 in case of error
       
  5508  */
       
  5509 XMLPUBFUNEXPORT int
       
  5510 xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
       
  5511                const char *URL, const char *encoding, int options)
       
  5512 {
       
  5513     xmlParserInputBufferPtr input;
       
  5514 
       
  5515     if (fd < 0)
       
  5516         return (-1);
       
  5517     if (reader == NULL)
       
  5518         return (-1);
       
  5519 
       
  5520     input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
       
  5521     if (input == NULL)
       
  5522         return (-1);
       
  5523     input->closecallback = NULL;
       
  5524     return (xmlTextReaderSetup(reader, input, URL, encoding, options));
       
  5525 }
       
  5526 
       
  5527 /**
       
  5528  * xmlReaderNewIO:
       
  5529  * @param reader an XML reader
       
  5530  * @param ioread an I/O read function
       
  5531  * @param ioclose an I/O close function
       
  5532  * @param ioctx an I/O handler
       
  5533  * @param URL the base URL to use for the document
       
  5534  * @param encoding the document encoding, or NULL
       
  5535  * @param options a combination of xmlParserOption
       
  5536  *
       
  5537  * Setup an xmltextReader to parse an XML document from I/O functions
       
  5538  * and source.
       
  5539  * The parsing flags options are a combination of xmlParserOption.
       
  5540  * This reuses the existing reader xmlTextReader.
       
  5541  *
       
  5542  * Returns 0 in case of success and -1 in case of error
       
  5543  */
       
  5544 XMLPUBFUNEXPORT int
       
  5545 xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
       
  5546                xmlInputCloseCallback ioclose, void *ioctx,
       
  5547                const char *URL, const char *encoding, int options)
       
  5548 {
       
  5549     xmlParserInputBufferPtr input;
       
  5550 
       
  5551     if (ioread == NULL)
       
  5552         return (-1);
       
  5553     if (reader == NULL)
       
  5554         return (-1);
       
  5555 
       
  5556     input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
       
  5557                                          XML_CHAR_ENCODING_NONE);
       
  5558     if (input == NULL)
       
  5559         return (-1);
       
  5560     return (xmlTextReaderSetup(reader, input, URL, encoding, options));
       
  5561 }
       
  5562 
       
  5563 /************************************************************************
       
  5564  *                                                                      *
       
  5565  *          Utilities                                                   *
       
  5566  *                                                                      *
       
  5567  ************************************************************************/
       
  5568 #ifdef NOT_USED_YET
       
  5569 /**
       
  5570  * xmlBase64Decode:
       
  5571  * @param in the input buffer
       
  5572  * @param inlen the size of the input (in), the size read from it (out)
       
  5573  * @param to the output buffer
       
  5574  * @param tolen the size of the output (in), the size written to (out)
       
  5575  *
       
  5576  * Base64 decoder, reads from in and save in to
       
  5577  * 
       
  5578  *
       
  5579  * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
       
  5580  *         2 if there wasn't enough space on the output or -1 in case of error.
       
  5581  */
       
  5582 static int
       
  5583 xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
       
  5584                 unsigned char *to, unsigned long *tolen) {
       
  5585     unsigned long incur;                /* current index in in[] */
       
  5586     unsigned long inblk;                /* last block index in in[] */
       
  5587     unsigned long outcur;               /* current index in out[] */
       
  5588     unsigned long inmax;                /* size of in[] */
       
  5589     unsigned long outmax;               /* size of out[] */
       
  5590     unsigned char cur;                  /* the current value read from in[] */
       
  5591     unsigned char intmp[4], outtmp[4];  /* temporary buffers for the convert */
       
  5592     int nbintmp;                        /* number of byte in intmp[] */
       
  5593     int is_ignore;                      /* cur should be ignored */
       
  5594     int is_end = 0;                     /* the end of the base64 was found */
       
  5595     int retval = 1;
       
  5596     int i;
       
  5597 
       
  5598     if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
       
  5599         return(-1);
       
  5600 
       
  5601     incur = 0;
       
  5602     inblk = 0;
       
  5603     outcur = 0;
       
  5604     inmax = *inlen;
       
  5605     outmax = *tolen;
       
  5606     nbintmp = 0;
       
  5607 
       
  5608     while (1) {
       
  5609         if (incur >= inmax)
       
  5610             break;
       
  5611         cur = in[incur++];
       
  5612         is_ignore = 0;
       
  5613         if ((cur >= 'A') && (cur <= 'Z'))
       
  5614             cur = cur - 'A';
       
  5615         else if ((cur >= 'a') && (cur <= 'z'))
       
  5616             cur = cur - 'a' + 26;
       
  5617         else if ((cur >= '0') && (cur <= '9'))
       
  5618             cur = cur - '0' + 52;
       
  5619         else if (cur == '+')
       
  5620             cur = 62;
       
  5621         else if (cur == '/')
       
  5622             cur = 63;
       
  5623         else if (cur == '.')
       
  5624             cur = 0;
       
  5625         else if (cur == '=') /*no op , end of the base64 stream */
       
  5626             is_end = 1;
       
  5627         else {
       
  5628             is_ignore = 1;
       
  5629             if (nbintmp == 0)
       
  5630                 inblk = incur;
       
  5631         }
       
  5632 
       
  5633         if (!is_ignore) {
       
  5634             int nbouttmp = 3;
       
  5635             int is_break = 0;
       
  5636 
       
  5637             if (is_end) {
       
  5638                 if (nbintmp == 0)
       
  5639                     break;
       
  5640                 if ((nbintmp == 1) || (nbintmp == 2))
       
  5641                     nbouttmp = 1;
       
  5642                 else
       
  5643                     nbouttmp = 2;
       
  5644                 nbintmp = 3;
       
  5645                 is_break = 1;
       
  5646             }
       
  5647             intmp[nbintmp++] = cur;
       
  5648             /*
       
  5649              * if intmp is full, push the 4byte sequence as a 3 byte
       
  5650              * sequence out
       
  5651              */
       
  5652             if (nbintmp == 4) {
       
  5653                 nbintmp = 0;
       
  5654                 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
       
  5655                 outtmp[1] =
       
  5656                     ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
       
  5657                 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
       
  5658                 if (outcur + 3 >= outmax) {
       
  5659                     retval = 2;
       
  5660                     break;
       
  5661                 }
       
  5662 
       
  5663                 for (i = 0; i < nbouttmp; i++)
       
  5664                     to[outcur++] = outtmp[i];
       
  5665                 inblk = incur;
       
  5666             }
       
  5667 
       
  5668             if (is_break) {
       
  5669                 retval = 0;
       
  5670                 break;
       
  5671             }
       
  5672         }
       
  5673     }
       
  5674 
       
  5675     *tolen = outcur;
       
  5676     *inlen = inblk;
       
  5677     return (retval);
       
  5678 }
       
  5679 
       
  5680 /*
       
  5681  * Test routine for the xmlBase64Decode function
       
  5682  */
       
  5683 #if 0
       
  5684 int main(int argc, char **argv) {
       
  5685     char *input = "  VW4 gcGV0        \n      aXQgdGVzdCAuCg== ";
       
  5686     char output[100];
       
  5687     char output2[100];
       
  5688     char output3[100];
       
  5689     unsigned long inlen = strlen(input);
       
  5690     unsigned long outlen = 100;
       
  5691     int ret;
       
  5692     unsigned long cons, tmp, tmp2, prod;
       
  5693 
       
  5694     /*
       
  5695      * Direct
       
  5696      */
       
  5697     ret = xmlBase64Decode(input, &inlen, output, &outlen);
       
  5698 
       
  5699     output[outlen] = 0;
       
  5700     printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output);
       
  5701 
       
  5702     /*
       
  5703      * output chunking
       
  5704      */
       
  5705     cons = 0;
       
  5706     prod = 0;
       
  5707     while (cons < inlen) {
       
  5708         tmp = 5;
       
  5709         tmp2 = inlen - cons;
       
  5710 
       
  5711         printf("%ld %ld\n", cons, prod);
       
  5712         ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
       
  5713         cons += tmp2;
       
  5714         prod += tmp;
       
  5715         printf("%ld %ld\n", cons, prod);
       
  5716     }
       
  5717     output2[outlen] = 0;
       
  5718     printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2);
       
  5719 
       
  5720     /*
       
  5721      * input chunking
       
  5722      */
       
  5723     cons = 0;
       
  5724     prod = 0;
       
  5725     while (cons < inlen) {
       
  5726         tmp = 100 - prod;
       
  5727         tmp2 = inlen - cons;
       
  5728         if (tmp2 > 5)
       
  5729             tmp2 = 5;
       
  5730 
       
  5731         printf("%ld %ld\n", cons, prod);
       
  5732         ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
       
  5733         cons += tmp2;
       
  5734         prod += tmp;
       
  5735         printf("%ld %ld\n", cons, prod);
       
  5736     }
       
  5737     output3[outlen] = 0;
       
  5738     printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3);
       
  5739     return(0);
       
  5740 
       
  5741 }
       
  5742 #endif
       
  5743 #endif /* NOT_USED_YET */
       
  5744 //#define bottom_xmlreader
       
  5745 //#include "elfgcchack.h"
       
  5746 #endif /* LIBXML_READER_ENABLED */