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