Annotation of embedaddon/libxml2/xmlreader.c, revision 1.1.1.1

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

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