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