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

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

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