~ubuntu-branches/ubuntu/wily/opencollada/wily-proposed

« back to all changes in this revision

Viewing changes to Externals/LibXML/xmlreader.c

  • Committer: Package Import Robot
  • Author(s): Matteo F. Vescovi
  • Date: 2015-05-14 17:23:27 UTC
  • Revision ID: package-import@ubuntu.com-20150514172327-f862u8envms01fra
Tags: upstream-0.1.0~20140703.ddf8f47+dfsg1
ImportĀ upstreamĀ versionĀ 0.1.0~20140703.ddf8f47+dfsg1

Show diffs side-by-side

added added

removed removed

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