Annotation of XML/parser.c, revision 1.131
1.1 veillard 1: /*
1.3 veillard 2: * parser.c : an XML 1.0 non-verifying parser
1.15 veillard 3: *
4: * See Copyright for the status of this software.
5: *
1.60 daniel 6: * Daniel.Veillard@w3.org
1.1 veillard 7: */
8:
1.26 daniel 9: #ifdef WIN32
10: #define HAVE_FCNTL_H
11: #include <io.h>
12: #else
1.121 daniel 13: #include "config.h"
1.26 daniel 14: #endif
1.121 daniel 15:
1.1 veillard 16: #include <stdio.h>
1.121 daniel 17: #include <string.h> /* for memset() only */
18: #ifdef HAVE_CTYPE_H
1.1 veillard 19: #include <ctype.h>
1.121 daniel 20: #endif
21: #ifdef HAVE_STDLIB_H
1.50 daniel 22: #include <stdlib.h>
1.121 daniel 23: #endif
24: #ifdef HAVE_SYS_STAT_H
1.9 httpng 25: #include <sys/stat.h>
1.121 daniel 26: #endif
1.9 httpng 27: #ifdef HAVE_FCNTL_H
28: #include <fcntl.h>
29: #endif
1.10 httpng 30: #ifdef HAVE_UNISTD_H
31: #include <unistd.h>
32: #endif
1.20 daniel 33: #ifdef HAVE_ZLIB_H
34: #include <zlib.h>
35: #endif
1.1 veillard 36:
1.119 daniel 37: #include "xmlmemory.h"
1.14 veillard 38: #include "tree.h"
1.1 veillard 39: #include "parser.h"
1.14 veillard 40: #include "entities.h"
1.75 daniel 41: #include "encoding.h"
1.61 daniel 42: #include "valid.h"
1.69 daniel 43: #include "parserInternals.h"
1.91 daniel 44: #include "xmlIO.h"
1.122 daniel 45: #include "xml-error.h"
1.1 veillard 46:
1.86 daniel 47: const char *xmlParserVersion = LIBXML_VERSION;
48:
1.91 daniel 49:
50: /************************************************************************
51: * *
52: * Input handling functions for progressive parsing *
53: * *
54: ************************************************************************/
55:
56: /* #define DEBUG_INPUT */
57:
1.110 daniel 58: #define INPUT_CHUNK 250
59: /* we need to keep enough input to show errors in context */
60: #define LINE_LEN 80
1.91 daniel 61:
62: #ifdef DEBUG_INPUT
63: #define CHECK_BUFFER(in) check_buffer(in)
64:
65: void check_buffer(xmlParserInputPtr in) {
66: if (in->base != in->buf->buffer->content) {
67: fprintf(stderr, "xmlParserInput: base mismatch problem\n");
68: }
69: if (in->cur < in->base) {
70: fprintf(stderr, "xmlParserInput: cur < base problem\n");
71: }
72: if (in->cur > in->base + in->buf->buffer->use) {
73: fprintf(stderr, "xmlParserInput: cur > base + use problem\n");
74: }
75: fprintf(stderr,"buffer %x : content %x, cur %d, use %d, size %d\n",
76: (int) in, (int) in->buf->buffer->content, in->cur - in->base,
77: in->buf->buffer->use, in->buf->buffer->size);
78: }
79:
1.110 daniel 80: #else
81: #define CHECK_BUFFER(in)
82: #endif
83:
1.91 daniel 84:
85: /**
86: * xmlParserInputRead:
87: * @in: an XML parser input
88: * @len: an indicative size for the lookahead
89: *
90: * This function refresh the input for the parser. It doesn't try to
91: * preserve pointers to the input buffer, and discard already read data
92: *
1.123 daniel 93: * Returns the number of xmlChars read, or -1 in case of error, 0 indicate the
1.91 daniel 94: * end of this entity
95: */
96: int
97: xmlParserInputRead(xmlParserInputPtr in, int len) {
98: int ret;
99: int used;
100: int index;
101:
102: #ifdef DEBUG_INPUT
103: fprintf(stderr, "Read\n");
104: #endif
105: if (in->buf == NULL) return(-1);
106: if (in->base == NULL) return(-1);
107: if (in->cur == NULL) return(-1);
108: if (in->buf->buffer == NULL) return(-1);
109:
110: CHECK_BUFFER(in);
111:
112: used = in->cur - in->buf->buffer->content;
113: ret = xmlBufferShrink(in->buf->buffer, used);
114: if (ret > 0) {
115: in->cur -= ret;
116: in->consumed += ret;
117: }
118: ret = xmlParserInputBufferRead(in->buf, len);
119: if (in->base != in->buf->buffer->content) {
120: /*
121: * the buffer has been realloced
122: */
123: index = in->cur - in->base;
124: in->base = in->buf->buffer->content;
125: in->cur = &in->buf->buffer->content[index];
126: }
127:
128: CHECK_BUFFER(in);
129:
130: return(ret);
131: }
132:
133: /**
134: * xmlParserInputGrow:
135: * @in: an XML parser input
136: * @len: an indicative size for the lookahead
137: *
138: * This function increase the input for the parser. It tries to
139: * preserve pointers to the input buffer, and keep already read data
140: *
1.123 daniel 141: * Returns the number of xmlChars read, or -1 in case of error, 0 indicate the
1.91 daniel 142: * end of this entity
143: */
144: int
145: xmlParserInputGrow(xmlParserInputPtr in, int len) {
146: int ret;
147: int index;
148:
149: #ifdef DEBUG_INPUT
150: fprintf(stderr, "Grow\n");
151: #endif
152: if (in->buf == NULL) return(-1);
153: if (in->base == NULL) return(-1);
154: if (in->cur == NULL) return(-1);
155: if (in->buf->buffer == NULL) return(-1);
156:
157: CHECK_BUFFER(in);
158:
159: index = in->cur - in->base;
160: if (in->buf->buffer->use > index + INPUT_CHUNK) {
161:
162: CHECK_BUFFER(in);
163:
164: return(0);
165: }
166: ret = xmlParserInputBufferGrow(in->buf, len);
167: if (in->base != in->buf->buffer->content) {
168: /*
169: * the buffer has been realloced
170: */
171: index = in->cur - in->base;
172: in->base = in->buf->buffer->content;
173: in->cur = &in->buf->buffer->content[index];
174: }
175:
176: CHECK_BUFFER(in);
177:
178: return(ret);
179: }
180:
181: /**
182: * xmlParserInputShrink:
183: * @in: an XML parser input
184: *
185: * This function removes used input for the parser.
186: */
187: void
188: xmlParserInputShrink(xmlParserInputPtr in) {
189: int used;
190: int ret;
191: int index;
192:
193: #ifdef DEBUG_INPUT
194: fprintf(stderr, "Shrink\n");
195: #endif
196: if (in->buf == NULL) return;
197: if (in->base == NULL) return;
198: if (in->cur == NULL) return;
199: if (in->buf->buffer == NULL) return;
200:
201: CHECK_BUFFER(in);
202:
203: used = in->cur - in->buf->buffer->content;
204: if (used > INPUT_CHUNK) {
1.110 daniel 205: ret = xmlBufferShrink(in->buf->buffer, used - LINE_LEN);
1.91 daniel 206: if (ret > 0) {
207: in->cur -= ret;
208: in->consumed += ret;
209: }
210: }
211:
212: CHECK_BUFFER(in);
213:
214: if (in->buf->buffer->use > INPUT_CHUNK) {
215: return;
216: }
217: xmlParserInputBufferRead(in->buf, 2 * INPUT_CHUNK);
218: if (in->base != in->buf->buffer->content) {
219: /*
220: * the buffer has been realloced
221: */
222: index = in->cur - in->base;
223: in->base = in->buf->buffer->content;
224: in->cur = &in->buf->buffer->content[index];
225: }
226:
227: CHECK_BUFFER(in);
228: }
229:
1.45 daniel 230: /************************************************************************
231: * *
232: * Parser stacks related functions and macros *
233: * *
234: ************************************************************************/
1.79 daniel 235:
236: int xmlSubstituteEntitiesDefaultValue = 0;
1.100 daniel 237: int xmlDoValidityCheckingDefaultValue = 0;
1.79 daniel 238:
1.1 veillard 239: /*
1.40 daniel 240: * Generic function for accessing stacks in the Parser Context
1.1 veillard 241: */
242:
1.31 daniel 243: #define PUSH_AND_POP(type, name) \
1.72 daniel 244: extern int name##Push(xmlParserCtxtPtr ctxt, type value) { \
1.31 daniel 245: if (ctxt->name##Nr >= ctxt->name##Max) { \
246: ctxt->name##Max *= 2; \
1.119 daniel 247: ctxt->name##Tab = (void *) xmlRealloc(ctxt->name##Tab, \
1.40 daniel 248: ctxt->name##Max * sizeof(ctxt->name##Tab[0])); \
249: if (ctxt->name##Tab == NULL) { \
1.31 daniel 250: fprintf(stderr, "realloc failed !\n"); \
251: exit(1); \
252: } \
253: } \
1.40 daniel 254: ctxt->name##Tab[ctxt->name##Nr] = value; \
255: ctxt->name = value; \
256: return(ctxt->name##Nr++); \
1.31 daniel 257: } \
1.72 daniel 258: extern type name##Pop(xmlParserCtxtPtr ctxt) { \
1.69 daniel 259: type ret; \
1.40 daniel 260: if (ctxt->name##Nr <= 0) return(0); \
261: ctxt->name##Nr--; \
1.50 daniel 262: if (ctxt->name##Nr > 0) \
263: ctxt->name = ctxt->name##Tab[ctxt->name##Nr - 1]; \
264: else \
265: ctxt->name = NULL; \
1.69 daniel 266: ret = ctxt->name##Tab[ctxt->name##Nr]; \
267: ctxt->name##Tab[ctxt->name##Nr] = 0; \
268: return(ret); \
1.31 daniel 269: } \
270:
1.40 daniel 271: PUSH_AND_POP(xmlParserInputPtr, input)
1.41 daniel 272: PUSH_AND_POP(xmlNodePtr, node)
1.40 daniel 273:
1.55 daniel 274: /*
275: * Macros for accessing the content. Those should be used only by the parser,
276: * and not exported.
277: *
278: * Dirty macros, i.e. one need to make assumption on the context to use them
279: *
1.123 daniel 280: * CUR_PTR return the current pointer to the xmlChar to be parsed.
281: * CUR returns the current xmlChar value, i.e. a 8 bit value if compiled
1.55 daniel 282: * in ISO-Latin or UTF-8, and the current 16 bit value if compiled
283: * in UNICODE mode. This should be used internally by the parser
284: * only to compare to ASCII values otherwise it would break when
285: * running with UTF-8 encoding.
1.123 daniel 286: * NXT(n) returns the n'th next xmlChar. Same as CUR is should be used only
1.55 daniel 287: * to compare on ASCII based substring.
1.123 daniel 288: * SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
1.55 daniel 289: * strings within the parser.
290: *
1.77 daniel 291: * Clean macros, not dependent of an ASCII context, expect UTF-8 encoding
1.55 daniel 292: *
293: * CURRENT Returns the current char value, with the full decoding of
294: * UTF-8 if we are using this mode. It returns an int.
295: * NEXT Skip to the next character, this does the proper decoding
296: * in UTF-8 mode. It also pop-up unfinished entities on the fly.
1.77 daniel 297: * COPY(to) copy one char to *to, increment CUR_PTR and to accordingly
1.55 daniel 298: */
1.45 daniel 299:
1.97 daniel 300: #define CUR (ctxt->token ? ctxt->token : (*ctxt->input->cur))
1.55 daniel 301: #define SKIP(val) ctxt->input->cur += (val)
302: #define NXT(val) ctxt->input->cur[(val)]
303: #define CUR_PTR ctxt->input->cur
1.97 daniel 304: #define SHRINK xmlParserInputShrink(ctxt->input); \
305: if ((*ctxt->input->cur == 0) && \
306: (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) \
307: xmlPopInput(ctxt)
308:
309: #define GROW xmlParserInputGrow(ctxt->input, INPUT_CHUNK); \
310: if ((*ctxt->input->cur == 0) && \
311: (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) \
312: xmlPopInput(ctxt)
1.55 daniel 313:
314: #define SKIP_BLANKS \
1.101 daniel 315: do { \
316: while (IS_BLANK(CUR)) NEXT; \
317: if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \
318: if (*ctxt->input->cur == '&') xmlParserHandleReference(ctxt); \
319: } while (IS_BLANK(CUR));
1.55 daniel 320:
321: #define CURRENT (*ctxt->input->cur)
1.91 daniel 322: #define NEXT { \
1.97 daniel 323: if (ctxt->token != 0) ctxt->token = 0; \
324: else { \
1.91 daniel 325: if ((*ctxt->input->cur == 0) && \
326: (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) { \
327: xmlPopInput(ctxt); \
328: } else { \
329: if (*(ctxt->input->cur) == '\n') { \
330: ctxt->input->line++; ctxt->input->col = 1; \
331: } else ctxt->input->col++; \
332: ctxt->input->cur++; \
333: if (*ctxt->input->cur == 0) \
334: xmlParserInputGrow(ctxt->input, INPUT_CHUNK); \
1.96 daniel 335: } \
336: if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \
337: if (*ctxt->input->cur == '&') xmlParserHandleReference(ctxt); \
1.97 daniel 338: }}
1.91 daniel 339:
1.42 daniel 340:
1.97 daniel 341: /************************************************************************
342: * *
343: * Commodity functions to handle entities processing *
344: * *
345: ************************************************************************/
1.40 daniel 346:
1.50 daniel 347: /**
348: * xmlPopInput:
349: * @ctxt: an XML parser context
350: *
1.40 daniel 351: * xmlPopInput: the current input pointed by ctxt->input came to an end
352: * pop it and return the next char.
1.45 daniel 353: *
1.123 daniel 354: * Returns the current xmlChar in the parser context
1.40 daniel 355: */
1.123 daniel 356: xmlChar
1.55 daniel 357: xmlPopInput(xmlParserCtxtPtr ctxt) {
1.40 daniel 358: if (ctxt->inputNr == 1) return(0); /* End of main Input */
1.69 daniel 359: xmlFreeInputStream(inputPop(ctxt));
1.97 daniel 360: if ((*ctxt->input->cur == 0) &&
361: (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
362: return(xmlPopInput(ctxt));
1.40 daniel 363: return(CUR);
364: }
365:
1.50 daniel 366: /**
367: * xmlPushInput:
368: * @ctxt: an XML parser context
369: * @input: an XML parser input fragment (entity, XML fragment ...).
370: *
1.40 daniel 371: * xmlPushInput: switch to a new input stream which is stacked on top
372: * of the previous one(s).
373: */
1.55 daniel 374: void
375: xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) {
1.40 daniel 376: if (input == NULL) return;
377: inputPush(ctxt, input);
378: }
379:
1.50 daniel 380: /**
1.69 daniel 381: * xmlFreeInputStream:
1.127 daniel 382: * @input: an xmlParserInputPtr
1.69 daniel 383: *
384: * Free up an input stream.
385: */
386: void
387: xmlFreeInputStream(xmlParserInputPtr input) {
388: if (input == NULL) return;
389:
1.119 daniel 390: if (input->filename != NULL) xmlFree((char *) input->filename);
391: if (input->directory != NULL) xmlFree((char *) input->directory);
1.69 daniel 392: if ((input->free != NULL) && (input->base != NULL))
1.123 daniel 393: input->free((xmlChar *) input->base);
1.93 veillard 394: if (input->buf != NULL)
395: xmlFreeParserInputBuffer(input->buf);
1.69 daniel 396: memset(input, -1, sizeof(xmlParserInput));
1.119 daniel 397: xmlFree(input);
1.69 daniel 398: }
399:
400: /**
1.96 daniel 401: * xmlNewInputStream:
402: * @ctxt: an XML parser context
403: *
404: * Create a new input stream structure
405: * Returns the new input stream or NULL
406: */
407: xmlParserInputPtr
408: xmlNewInputStream(xmlParserCtxtPtr ctxt) {
409: xmlParserInputPtr input;
410:
1.119 daniel 411: input = (xmlParserInputPtr) xmlMalloc(sizeof(xmlParserInput));
1.96 daniel 412: if (input == NULL) {
1.123 daniel 413: ctxt->errNo = XML_ERR_NO_MEMORY;
1.96 daniel 414: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 415: ctxt->sax->error(ctxt->userData,
416: "malloc: couldn't allocate a new input stream\n");
1.123 daniel 417: ctxt->errNo = XML_ERR_NO_MEMORY;
1.96 daniel 418: return(NULL);
419: }
420: input->filename = NULL;
421: input->directory = NULL;
422: input->base = NULL;
423: input->cur = NULL;
424: input->buf = NULL;
425: input->line = 1;
426: input->col = 1;
427: input->buf = NULL;
428: input->free = NULL;
429: input->consumed = 0;
430: return(input);
431: }
432:
433: /**
1.50 daniel 434: * xmlNewEntityInputStream:
435: * @ctxt: an XML parser context
436: * @entity: an Entity pointer
437: *
1.82 daniel 438: * Create a new input stream based on an xmlEntityPtr
1.113 daniel 439: *
440: * Returns the new input stream or NULL
1.45 daniel 441: */
1.50 daniel 442: xmlParserInputPtr
443: xmlNewEntityInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
1.45 daniel 444: xmlParserInputPtr input;
445:
446: if (entity == NULL) {
1.123 daniel 447: ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1.55 daniel 448: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 449: ctxt->sax->error(ctxt->userData,
1.45 daniel 450: "internal: xmlNewEntityInputStream entity = NULL\n");
1.123 daniel 451: ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1.50 daniel 452: return(NULL);
1.45 daniel 453: }
454: if (entity->content == NULL) {
1.113 daniel 455: switch (entity->type) {
456: case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
1.123 daniel 457: ctxt->errNo = XML_ERR_UNPARSED_ENTITY;
1.113 daniel 458: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
459: ctxt->sax->error(ctxt->userData,
460: "xmlNewEntityInputStream unparsed entity !\n");
461: break;
462: case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
463: case XML_EXTERNAL_PARAMETER_ENTITY:
1.116 daniel 464: return(xmlLoadExternalEntity((char *) entity->SystemID,
465: (char *) entity->ExternalID, ctxt->input));
1.113 daniel 466: case XML_INTERNAL_GENERAL_ENTITY:
467: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
468: ctxt->sax->error(ctxt->userData,
469: "Internal entity %s without content !\n", entity->name);
470: break;
471: case XML_INTERNAL_PARAMETER_ENTITY:
1.123 daniel 472: ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1.113 daniel 473: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
474: ctxt->sax->error(ctxt->userData,
475: "Internal parameter entity %s without content !\n", entity->name);
476: break;
477: case XML_INTERNAL_PREDEFINED_ENTITY:
1.123 daniel 478: ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1.113 daniel 479: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
480: ctxt->sax->error(ctxt->userData,
481: "Predefined entity %s without content !\n", entity->name);
482: break;
483: }
1.50 daniel 484: return(NULL);
1.45 daniel 485: }
1.96 daniel 486: input = xmlNewInputStream(ctxt);
1.45 daniel 487: if (input == NULL) {
1.50 daniel 488: return(NULL);
1.45 daniel 489: }
1.123 daniel 490: input->filename = (char *) entity->SystemID; /* TODO !!! char <- xmlChar */
1.45 daniel 491: input->base = entity->content;
492: input->cur = entity->content;
1.50 daniel 493: return(input);
1.45 daniel 494: }
495:
1.59 daniel 496: /**
497: * xmlNewStringInputStream:
498: * @ctxt: an XML parser context
1.96 daniel 499: * @buffer: an memory buffer
1.59 daniel 500: *
501: * Create a new input stream based on a memory buffer.
1.68 daniel 502: * Returns the new input stream
1.59 daniel 503: */
504: xmlParserInputPtr
1.123 daniel 505: xmlNewStringInputStream(xmlParserCtxtPtr ctxt, const xmlChar *buffer) {
1.59 daniel 506: xmlParserInputPtr input;
507:
1.96 daniel 508: if (buffer == NULL) {
1.123 daniel 509: ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1.59 daniel 510: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 511: ctxt->sax->error(ctxt->userData,
1.59 daniel 512: "internal: xmlNewStringInputStream string = NULL\n");
513: return(NULL);
514: }
1.96 daniel 515: input = xmlNewInputStream(ctxt);
1.59 daniel 516: if (input == NULL) {
517: return(NULL);
518: }
1.96 daniel 519: input->base = buffer;
520: input->cur = buffer;
1.59 daniel 521: return(input);
522: }
523:
1.76 daniel 524: /**
525: * xmlNewInputFromFile:
526: * @ctxt: an XML parser context
527: * @filename: the filename to use as entity
528: *
529: * Create a new input stream based on a file.
530: *
531: * Returns the new input stream or NULL in case of error
532: */
533: xmlParserInputPtr
1.79 daniel 534: xmlNewInputFromFile(xmlParserCtxtPtr ctxt, const char *filename) {
1.91 daniel 535: xmlParserInputBufferPtr buf;
1.76 daniel 536: xmlParserInputPtr inputStream;
1.111 daniel 537: char *directory = NULL;
1.76 daniel 538:
1.96 daniel 539: if (ctxt == NULL) return(NULL);
1.91 daniel 540: buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
1.94 daniel 541: if (buf == NULL) {
1.106 daniel 542: char name[1024];
543:
1.94 daniel 544: if ((ctxt->input != NULL) && (ctxt->input->directory != NULL)) {
545: #ifdef WIN32
546: sprintf(name, "%s\\%s", ctxt->input->directory, filename);
547: #else
548: sprintf(name, "%s/%s", ctxt->input->directory, filename);
549: #endif
550: buf = xmlParserInputBufferCreateFilename(name,
551: XML_CHAR_ENCODING_NONE);
1.106 daniel 552: if (buf != NULL)
1.119 daniel 553: directory = xmlMemStrdup(ctxt->input->directory);
1.106 daniel 554: }
555: if ((buf == NULL) && (ctxt->directory != NULL)) {
556: #ifdef WIN32
557: sprintf(name, "%s\\%s", ctxt->directory, filename);
558: #else
559: sprintf(name, "%s/%s", ctxt->directory, filename);
560: #endif
561: buf = xmlParserInputBufferCreateFilename(name,
562: XML_CHAR_ENCODING_NONE);
563: if (buf != NULL)
1.119 daniel 564: directory = xmlMemStrdup(ctxt->directory);
1.106 daniel 565: }
566: if (buf == NULL)
1.94 daniel 567: return(NULL);
568: }
569: if (directory == NULL)
570: directory = xmlParserGetDirectory(filename);
1.76 daniel 571:
1.96 daniel 572: inputStream = xmlNewInputStream(ctxt);
1.76 daniel 573: if (inputStream == NULL) {
1.119 daniel 574: if (directory != NULL) xmlFree((char *) directory);
1.76 daniel 575: return(NULL);
576: }
577:
1.119 daniel 578: inputStream->filename = xmlMemStrdup(filename);
1.94 daniel 579: inputStream->directory = directory;
1.91 daniel 580: inputStream->buf = buf;
1.76 daniel 581:
1.91 daniel 582: inputStream->base = inputStream->buf->buffer->content;
583: inputStream->cur = inputStream->buf->buffer->content;
1.106 daniel 584: if ((ctxt->directory == NULL) && (directory != NULL))
1.110 daniel 585: ctxt->directory = directory;
1.76 daniel 586: return(inputStream);
587: }
588:
1.77 daniel 589: /************************************************************************
590: * *
1.97 daniel 591: * Commodity functions to handle parser contexts *
592: * *
593: ************************************************************************/
594:
595: /**
596: * xmlInitParserCtxt:
597: * @ctxt: an XML parser context
598: *
599: * Initialize a parser context
600: */
601:
602: void
603: xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
604: {
605: xmlSAXHandler *sax;
606:
1.119 daniel 607: sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
1.97 daniel 608: if (sax == NULL) {
609: fprintf(stderr, "xmlInitParserCtxt: out of memory\n");
610: }
611:
612: /* Allocate the Input stack */
1.119 daniel 613: ctxt->inputTab = (xmlParserInputPtr *) xmlMalloc(5 * sizeof(xmlParserInputPtr));
1.97 daniel 614: ctxt->inputNr = 0;
615: ctxt->inputMax = 5;
616: ctxt->input = NULL;
617: ctxt->version = NULL;
618: ctxt->encoding = NULL;
619: ctxt->standalone = -1;
1.98 daniel 620: ctxt->hasExternalSubset = 0;
621: ctxt->hasPErefs = 0;
1.97 daniel 622: ctxt->html = 0;
1.98 daniel 623: ctxt->external = 0;
1.97 daniel 624: ctxt->instate = XML_PARSER_PROLOG;
625: ctxt->token = 0;
1.106 daniel 626: ctxt->directory = NULL;
1.97 daniel 627:
628: /* Allocate the Node stack */
1.119 daniel 629: ctxt->nodeTab = (xmlNodePtr *) xmlMalloc(10 * sizeof(xmlNodePtr));
1.97 daniel 630: ctxt->nodeNr = 0;
631: ctxt->nodeMax = 10;
632: ctxt->node = NULL;
633:
634: if (sax == NULL) ctxt->sax = &xmlDefaultSAXHandler;
635: else {
636: ctxt->sax = sax;
637: memcpy(sax, &xmlDefaultSAXHandler, sizeof(xmlSAXHandler));
638: }
639: ctxt->userData = ctxt;
640: ctxt->myDoc = NULL;
641: ctxt->wellFormed = 1;
1.99 daniel 642: ctxt->valid = 1;
1.100 daniel 643: ctxt->validate = xmlDoValidityCheckingDefaultValue;
644: ctxt->vctxt.userData = ctxt;
645: ctxt->vctxt.error = xmlParserValidityError;
646: ctxt->vctxt.warning = xmlParserValidityWarning;
1.97 daniel 647: ctxt->replaceEntities = xmlSubstituteEntitiesDefaultValue;
648: ctxt->record_info = 0;
649: xmlInitNodeInfoSeq(&ctxt->node_seq);
650: }
651:
652: /**
653: * xmlFreeParserCtxt:
654: * @ctxt: an XML parser context
655: *
656: * Free all the memory used by a parser context. However the parsed
657: * document in ctxt->myDoc is not freed.
658: */
659:
660: void
661: xmlFreeParserCtxt(xmlParserCtxtPtr ctxt)
662: {
663: xmlParserInputPtr input;
664:
665: if (ctxt == NULL) return;
666:
667: while ((input = inputPop(ctxt)) != NULL) {
668: xmlFreeInputStream(input);
669: }
670:
1.119 daniel 671: if (ctxt->nodeTab != NULL) xmlFree(ctxt->nodeTab);
672: if (ctxt->inputTab != NULL) xmlFree(ctxt->inputTab);
673: if (ctxt->version != NULL) xmlFree((char *) ctxt->version);
674: if (ctxt->encoding != NULL) xmlFree((char *) ctxt->encoding);
1.97 daniel 675: if ((ctxt->sax != NULL) && (ctxt->sax != &xmlDefaultSAXHandler))
1.119 daniel 676: xmlFree(ctxt->sax);
677: if (ctxt->directory != NULL) xmlFree((char *) ctxt->directory);
678: xmlFree(ctxt);
1.97 daniel 679: }
680:
681: /**
682: * xmlNewParserCtxt:
683: *
684: * Allocate and initialize a new parser context.
685: *
686: * Returns the xmlParserCtxtPtr or NULL
687: */
688:
689: xmlParserCtxtPtr
690: xmlNewParserCtxt()
691: {
692: xmlParserCtxtPtr ctxt;
693:
1.119 daniel 694: ctxt = (xmlParserCtxtPtr) xmlMalloc(sizeof(xmlParserCtxt));
1.97 daniel 695: if (ctxt == NULL) {
696: fprintf(stderr, "xmlNewParserCtxt : cannot allocate context\n");
697: perror("malloc");
698: return(NULL);
699: }
700: xmlInitParserCtxt(ctxt);
701: return(ctxt);
702: }
703:
704: /**
705: * xmlClearParserCtxt:
706: * @ctxt: an XML parser context
707: *
708: * Clear (release owned resources) and reinitialize a parser context
709: */
710:
711: void
712: xmlClearParserCtxt(xmlParserCtxtPtr ctxt)
713: {
714: xmlClearNodeInfoSeq(&ctxt->node_seq);
715: xmlInitParserCtxt(ctxt);
716: }
717:
718: /************************************************************************
719: * *
1.77 daniel 720: * Commodity functions to handle entities *
721: * *
722: ************************************************************************/
723:
1.97 daniel 724: void xmlParserHandleReference(xmlParserCtxtPtr ctxt);
725: void xmlParserHandlePEReference(xmlParserCtxtPtr ctxt);
726:
727: /**
728: * xmlParseCharRef:
729: * @ctxt: an XML parser context
730: *
731: * parse Reference declarations
732: *
733: * [66] CharRef ::= '&#' [0-9]+ ';' |
734: * '&#x' [0-9a-fA-F]+ ';'
735: *
1.98 daniel 736: * [ WFC: Legal Character ]
737: * Characters referred to using character references must match the
738: * production for Char.
739: *
1.97 daniel 740: * Returns the value parsed (as an int)
1.77 daniel 741: */
1.97 daniel 742: int
743: xmlParseCharRef(xmlParserCtxtPtr ctxt) {
744: int val = 0;
745:
1.111 daniel 746: if (ctxt->token != 0) {
1.126 daniel 747: fprintf(stderr, "xmlParseCharRef : ctxt->token != 0\n");
1.111 daniel 748: val = ctxt->token;
749: ctxt->token = 0;
750: return(val);
751: }
1.97 daniel 752: if ((CUR == '&') && (NXT(1) == '#') &&
753: (NXT(2) == 'x')) {
754: SKIP(3);
755: while (CUR != ';') {
756: if ((CUR >= '0') && (CUR <= '9'))
757: val = val * 16 + (CUR - '0');
758: else if ((CUR >= 'a') && (CUR <= 'f'))
759: val = val * 16 + (CUR - 'a') + 10;
760: else if ((CUR >= 'A') && (CUR <= 'F'))
761: val = val * 16 + (CUR - 'A') + 10;
762: else {
1.123 daniel 763: ctxt->errNo = XML_ERR_INVALID_HEX_CHARREF;
1.97 daniel 764: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
765: ctxt->sax->error(ctxt->userData,
766: "xmlParseCharRef: invalid hexadecimal value\n");
767: ctxt->wellFormed = 0;
768: val = 0;
769: break;
770: }
771: NEXT;
772: }
773: if (CUR == ';')
1.126 daniel 774: SKIP(1); /* on purpose to avoid reentrancy problems with NEXT */
1.97 daniel 775: } else if ((CUR == '&') && (NXT(1) == '#')) {
776: SKIP(2);
777: while (CUR != ';') {
778: if ((CUR >= '0') && (CUR <= '9'))
779: val = val * 10 + (CUR - '0');
780: else {
1.123 daniel 781: ctxt->errNo = XML_ERR_INVALID_DEC_CHARREF;
1.97 daniel 782: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
783: ctxt->sax->error(ctxt->userData,
784: "xmlParseCharRef: invalid decimal value\n");
785: ctxt->wellFormed = 0;
786: val = 0;
787: break;
788: }
789: NEXT;
790: }
791: if (CUR == ';')
1.126 daniel 792: SKIP(1); /* on purpose to avoid reentrancy problems with NEXT */
1.97 daniel 793: } else {
1.123 daniel 794: ctxt->errNo = XML_ERR_INVALID_CHARREF;
1.97 daniel 795: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.98 daniel 796: ctxt->sax->error(ctxt->userData,
797: "xmlParseCharRef: invalid value\n");
1.97 daniel 798: ctxt->wellFormed = 0;
799: }
1.98 daniel 800:
1.97 daniel 801: /*
1.98 daniel 802: * [ WFC: Legal Character ]
803: * Characters referred to using character references must match the
804: * production for Char.
1.97 daniel 805: */
806: if (IS_CHAR(val)) {
807: return(val);
808: } else {
1.123 daniel 809: ctxt->errNo = XML_ERR_INVALID_CHAR;
1.97 daniel 810: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.123 daniel 811: ctxt->sax->error(ctxt->userData, "CharRef: invalid xmlChar value %d\n",
1.97 daniel 812: val);
813: ctxt->wellFormed = 0;
814: }
815: return(0);
1.77 daniel 816: }
817:
1.96 daniel 818: /**
819: * xmlParserHandleReference:
820: * @ctxt: the parser context
821: *
1.97 daniel 822: * [67] Reference ::= EntityRef | CharRef
823: *
1.96 daniel 824: * [68] EntityRef ::= '&' Name ';'
825: *
1.98 daniel 826: * [ WFC: Entity Declared ]
827: * the Name given in the entity reference must match that in an entity
828: * declaration, except that well-formed documents need not declare any
829: * of the following entities: amp, lt, gt, apos, quot.
830: *
831: * [ WFC: Parsed Entity ]
832: * An entity reference must not contain the name of an unparsed entity
833: *
1.97 daniel 834: * [66] CharRef ::= '&#' [0-9]+ ';' |
835: * '&#x' [0-9a-fA-F]+ ';'
836: *
1.96 daniel 837: * A PEReference may have been detectect in the current input stream
838: * the handling is done accordingly to
839: * http://www.w3.org/TR/REC-xml#entproc
840: */
841: void
842: xmlParserHandleReference(xmlParserCtxtPtr ctxt) {
1.97 daniel 843: xmlParserInputPtr input;
1.123 daniel 844: xmlChar *name;
1.97 daniel 845: xmlEntityPtr ent = NULL;
846:
1.126 daniel 847: if (ctxt->token != 0) {
848: fprintf(stderr, "xmlParserHandleReference : ctxt->token != 0\n");
849: return;
850: }
1.97 daniel 851: if (CUR != '&') return;
852: GROW;
853: if ((CUR == '&') && (NXT(1) == '#')) {
854: switch(ctxt->instate) {
1.109 daniel 855: case XML_PARSER_CDATA_SECTION:
856: return;
1.97 daniel 857: case XML_PARSER_COMMENT:
858: return;
859: case XML_PARSER_EOF:
1.123 daniel 860: ctxt->errNo = XML_ERR_CHARREF_AT_EOF;
1.97 daniel 861: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
862: ctxt->sax->error(ctxt->userData, "CharRef at EOF\n");
863: ctxt->wellFormed = 0;
864: return;
865: case XML_PARSER_PROLOG:
1.123 daniel 866: ctxt->errNo = XML_ERR_CHARREF_IN_PROLOG;
1.97 daniel 867: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
868: ctxt->sax->error(ctxt->userData, "CharRef in prolog!\n");
869: ctxt->wellFormed = 0;
870: return;
871: case XML_PARSER_EPILOG:
1.123 daniel 872: ctxt->errNo = XML_ERR_CHARREF_IN_EPILOG;
1.97 daniel 873: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
874: ctxt->sax->error(ctxt->userData, "CharRef in epilog!\n");
875: ctxt->wellFormed = 0;
876: return;
877: case XML_PARSER_DTD:
1.123 daniel 878: ctxt->errNo = XML_ERR_CHARREF_IN_DTD;
1.97 daniel 879: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
880: ctxt->sax->error(ctxt->userData,
881: "CharRef are forbiden in DTDs!\n");
882: ctxt->wellFormed = 0;
883: return;
884: case XML_PARSER_ENTITY_DECL:
885: /* we just ignore it there */
886: return;
887: case XML_PARSER_ENTITY_VALUE:
888: /*
889: * NOTE: in the case of entity values, we don't do the
1.127 daniel 890: * substitution here since we need the literal
1.97 daniel 891: * entity value to be able to save the internal
892: * subset of the document.
893: * This will be handled by xmlDecodeEntities
894: */
895: return;
896: case XML_PARSER_CONTENT:
897: case XML_PARSER_ATTRIBUTE_VALUE:
1.116 daniel 898: /* !!! this may not be Ok for UTF-8, multibyte sequence */
1.97 daniel 899: ctxt->token = xmlParseCharRef(ctxt);
900: return;
901: }
902: return;
903: }
904:
905: switch(ctxt->instate) {
1.109 daniel 906: case XML_PARSER_CDATA_SECTION:
907: return;
1.97 daniel 908: case XML_PARSER_COMMENT:
909: return;
910: case XML_PARSER_EOF:
1.123 daniel 911: ctxt->errNo = XML_ERR_ENTITYREF_AT_EOF;
1.97 daniel 912: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
913: ctxt->sax->error(ctxt->userData, "Reference at EOF\n");
914: ctxt->wellFormed = 0;
915: return;
916: case XML_PARSER_PROLOG:
1.123 daniel 917: ctxt->errNo = XML_ERR_ENTITYREF_IN_PROLOG;
1.97 daniel 918: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
919: ctxt->sax->error(ctxt->userData, "Reference in prolog!\n");
920: ctxt->wellFormed = 0;
921: return;
922: case XML_PARSER_EPILOG:
1.123 daniel 923: ctxt->errNo = XML_ERR_ENTITYREF_IN_EPILOG;
1.97 daniel 924: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
925: ctxt->sax->error(ctxt->userData, "Reference in epilog!\n");
926: ctxt->wellFormed = 0;
927: return;
928: case XML_PARSER_ENTITY_VALUE:
929: /*
930: * NOTE: in the case of entity values, we don't do the
1.127 daniel 931: * substitution here since we need the literal
1.97 daniel 932: * entity value to be able to save the internal
933: * subset of the document.
934: * This will be handled by xmlDecodeEntities
935: */
936: return;
937: case XML_PARSER_ATTRIBUTE_VALUE:
938: /*
939: * NOTE: in the case of attributes values, we don't do the
940: * substitution here unless we are in a mode where
941: * the parser is explicitely asked to substitute
942: * entities. The SAX callback is called with values
943: * without entity substitution.
944: * This will then be handled by xmlDecodeEntities
945: */
1.113 daniel 946: return;
1.97 daniel 947: case XML_PARSER_ENTITY_DECL:
948: /*
949: * we just ignore it there
950: * the substitution will be done once the entity is referenced
951: */
952: return;
953: case XML_PARSER_DTD:
1.123 daniel 954: ctxt->errNo = XML_ERR_ENTITYREF_IN_DTD;
1.97 daniel 955: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
956: ctxt->sax->error(ctxt->userData,
957: "Entity references are forbiden in DTDs!\n");
958: ctxt->wellFormed = 0;
959: return;
960: case XML_PARSER_CONTENT:
1.113 daniel 961: return;
1.97 daniel 962: }
963:
964: NEXT;
965: name = xmlScanName(ctxt);
966: if (name == NULL) {
1.123 daniel 967: ctxt->errNo = XML_ERR_ENTITYREF_NO_NAME;
1.97 daniel 968: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
969: ctxt->sax->error(ctxt->userData, "Entity reference: no name\n");
970: ctxt->wellFormed = 0;
971: ctxt->token = '&';
972: return;
973: }
974: if (NXT(xmlStrlen(name)) != ';') {
1.123 daniel 975: ctxt->errNo = XML_ERR_ENTITYREF_SEMICOL_MISSING;
1.97 daniel 976: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
977: ctxt->sax->error(ctxt->userData,
978: "Entity reference: ';' expected\n");
979: ctxt->wellFormed = 0;
980: ctxt->token = '&';
1.119 daniel 981: xmlFree(name);
1.97 daniel 982: return;
983: }
984: SKIP(xmlStrlen(name) + 1);
985: if (ctxt->sax != NULL) {
986: if (ctxt->sax->getEntity != NULL)
987: ent = ctxt->sax->getEntity(ctxt->userData, name);
988: }
1.98 daniel 989:
990: /*
991: * [ WFC: Entity Declared ]
992: * the Name given in the entity reference must match that in an entity
993: * declaration, except that well-formed documents need not declare any
994: * of the following entities: amp, lt, gt, apos, quot.
995: */
1.97 daniel 996: if (ent == NULL)
997: ent = xmlGetPredefinedEntity(name);
998: if (ent == NULL) {
1.123 daniel 999: ctxt->errNo = XML_ERR_UNDECLARED_ENTITY;
1.97 daniel 1000: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1001: ctxt->sax->error(ctxt->userData,
1.98 daniel 1002: "Entity reference: entity %s not declared\n",
1003: name);
1.97 daniel 1004: ctxt->wellFormed = 0;
1.119 daniel 1005: xmlFree(name);
1.97 daniel 1006: return;
1007: }
1.98 daniel 1008:
1009: /*
1010: * [ WFC: Parsed Entity ]
1011: * An entity reference must not contain the name of an unparsed entity
1012: */
1013: if (ent->type == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
1.123 daniel 1014: ctxt->errNo = XML_ERR_UNPARSED_ENTITY;
1.98 daniel 1015: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1016: ctxt->sax->error(ctxt->userData,
1017: "Entity reference to unparsed entity %s\n", name);
1018: ctxt->wellFormed = 0;
1019: }
1020:
1.97 daniel 1021: if (ent->type == XML_INTERNAL_PREDEFINED_ENTITY) {
1022: ctxt->token = ent->content[0];
1.119 daniel 1023: xmlFree(name);
1.97 daniel 1024: return;
1025: }
1026: input = xmlNewEntityInputStream(ctxt, ent);
1027: xmlPushInput(ctxt, input);
1.119 daniel 1028: xmlFree(name);
1.96 daniel 1029: return;
1030: }
1031:
1032: /**
1033: * xmlParserHandlePEReference:
1034: * @ctxt: the parser context
1035: *
1036: * [69] PEReference ::= '%' Name ';'
1037: *
1.98 daniel 1038: * [ WFC: No Recursion ]
1039: * TODO A parsed entity must not contain a recursive
1040: * reference to itself, either directly or indirectly.
1041: *
1042: * [ WFC: Entity Declared ]
1043: * In a document without any DTD, a document with only an internal DTD
1044: * subset which contains no parameter entity references, or a document
1045: * with "standalone='yes'", ... ... The declaration of a parameter
1046: * entity must precede any reference to it...
1047: *
1048: * [ VC: Entity Declared ]
1049: * In a document with an external subset or external parameter entities
1050: * with "standalone='no'", ... ... The declaration of a parameter entity
1051: * must precede any reference to it...
1052: *
1053: * [ WFC: In DTD ]
1054: * Parameter-entity references may only appear in the DTD.
1055: * NOTE: misleading but this is handled.
1056: *
1057: * A PEReference may have been detected in the current input stream
1.96 daniel 1058: * the handling is done accordingly to
1059: * http://www.w3.org/TR/REC-xml#entproc
1060: * i.e.
1061: * - Included in literal in entity values
1062: * - Included as Paraemeter Entity reference within DTDs
1063: */
1064: void
1065: xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
1.123 daniel 1066: xmlChar *name;
1.96 daniel 1067: xmlEntityPtr entity = NULL;
1068: xmlParserInputPtr input;
1069:
1.126 daniel 1070: if (ctxt->token != 0) {
1071: fprintf(stderr, "xmlParserHandlePEReference : ctxt->token != 0\n");
1072: return;
1073: }
1.111 daniel 1074: if (CUR != '%') return;
1.96 daniel 1075: switch(ctxt->instate) {
1.109 daniel 1076: case XML_PARSER_CDATA_SECTION:
1077: return;
1.97 daniel 1078: case XML_PARSER_COMMENT:
1079: return;
1.96 daniel 1080: case XML_PARSER_EOF:
1.123 daniel 1081: ctxt->errNo = XML_ERR_PEREF_AT_EOF;
1.96 daniel 1082: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1083: ctxt->sax->error(ctxt->userData, "PEReference at EOF\n");
1084: ctxt->wellFormed = 0;
1085: return;
1086: case XML_PARSER_PROLOG:
1.123 daniel 1087: ctxt->errNo = XML_ERR_PEREF_IN_PROLOG;
1.96 daniel 1088: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1089: ctxt->sax->error(ctxt->userData, "PEReference in prolog!\n");
1090: ctxt->wellFormed = 0;
1091: return;
1.97 daniel 1092: case XML_PARSER_ENTITY_DECL:
1.96 daniel 1093: case XML_PARSER_CONTENT:
1094: case XML_PARSER_ATTRIBUTE_VALUE:
1095: /* we just ignore it there */
1096: return;
1097: case XML_PARSER_EPILOG:
1.123 daniel 1098: ctxt->errNo = XML_ERR_PEREF_IN_EPILOG;
1.96 daniel 1099: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.97 daniel 1100: ctxt->sax->error(ctxt->userData, "PEReference in epilog!\n");
1.96 daniel 1101: ctxt->wellFormed = 0;
1102: return;
1.97 daniel 1103: case XML_PARSER_ENTITY_VALUE:
1104: /*
1105: * NOTE: in the case of entity values, we don't do the
1.127 daniel 1106: * substitution here since we need the literal
1.97 daniel 1107: * entity value to be able to save the internal
1108: * subset of the document.
1109: * This will be handled by xmlDecodeEntities
1110: */
1111: return;
1.96 daniel 1112: case XML_PARSER_DTD:
1.98 daniel 1113: /*
1114: * [WFC: Well-Formedness Constraint: PEs in Internal Subset]
1115: * In the internal DTD subset, parameter-entity references
1116: * can occur only where markup declarations can occur, not
1117: * within markup declarations.
1118: * In that case this is handled in xmlParseMarkupDecl
1119: */
1120: if ((ctxt->external == 0) && (ctxt->inputNr == 1))
1121: return;
1.96 daniel 1122: }
1123:
1124: NEXT;
1125: name = xmlParseName(ctxt);
1126: if (name == NULL) {
1.123 daniel 1127: ctxt->errNo = XML_ERR_PEREF_NO_NAME;
1.96 daniel 1128: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1129: ctxt->sax->error(ctxt->userData, "xmlHandlePEReference: no name\n");
1130: ctxt->wellFormed = 0;
1131: } else {
1132: if (CUR == ';') {
1133: NEXT;
1.98 daniel 1134: if ((ctxt->sax != NULL) && (ctxt->sax->getParameterEntity != NULL))
1135: entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
1.96 daniel 1136: if (entity == NULL) {
1.98 daniel 1137:
1138: /*
1139: * [ WFC: Entity Declared ]
1140: * In a document without any DTD, a document with only an
1141: * internal DTD subset which contains no parameter entity
1142: * references, or a document with "standalone='yes'", ...
1143: * ... The declaration of a parameter entity must precede
1144: * any reference to it...
1145: */
1146: if ((ctxt->standalone == 1) ||
1147: ((ctxt->hasExternalSubset == 0) &&
1148: (ctxt->hasPErefs == 0))) {
1149: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1150: ctxt->sax->error(ctxt->userData,
1151: "PEReference: %%%s; not found\n", name);
1152: ctxt->wellFormed = 0;
1153: } else {
1154: /*
1155: * [ VC: Entity Declared ]
1156: * In a document with an external subset or external
1157: * parameter entities with "standalone='no'", ...
1158: * ... The declaration of a parameter entity must precede
1159: * any reference to it...
1160: */
1161: if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1162: ctxt->sax->warning(ctxt->userData,
1163: "PEReference: %%%s; not found\n", name);
1164: ctxt->valid = 0;
1165: }
1.96 daniel 1166: } else {
1167: if ((entity->type == XML_INTERNAL_PARAMETER_ENTITY) ||
1168: (entity->type == XML_EXTERNAL_PARAMETER_ENTITY)) {
1169: /*
1170: * TODO !!!! handle the extra spaces added before and after
1171: * c.f. http://www.w3.org/TR/REC-xml#as-PE
1172: * TODO !!!! Avoid quote processing in parameters value
1173: * c.f. http://www.w3.org/TR/REC-xml#inliteral
1174: */
1175: input = xmlNewEntityInputStream(ctxt, entity);
1176: xmlPushInput(ctxt, input);
1177: } else {
1178: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1179: ctxt->sax->error(ctxt->userData,
1180: "xmlHandlePEReference: %s is not a parameter entity\n",
1181: name);
1182: ctxt->wellFormed = 0;
1183: }
1184: }
1185: } else {
1.123 daniel 1186: ctxt->errNo = XML_ERR_PEREF_SEMICOL_MISSING;
1.96 daniel 1187: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1188: ctxt->sax->error(ctxt->userData,
1189: "xmlHandlePEReference: expecting ';'\n");
1190: ctxt->wellFormed = 0;
1191: }
1.119 daniel 1192: xmlFree(name);
1.97 daniel 1193: }
1194: }
1195:
1196: /*
1197: * Macro used to grow the current buffer.
1198: */
1199: #define growBuffer(buffer) { \
1200: buffer##_size *= 2; \
1.123 daniel 1201: buffer = (xmlChar *) xmlRealloc(buffer, buffer##_size * sizeof(xmlChar)); \
1.97 daniel 1202: if (buffer == NULL) { \
1203: perror("realloc failed"); \
1204: exit(1); \
1205: } \
1.96 daniel 1206: }
1.77 daniel 1207:
1208: /**
1209: * xmlDecodeEntities:
1210: * @ctxt: the parser context
1211: * @what: combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
1212: * @len: the len to decode (in bytes !), -1 for no size limit
1.123 daniel 1213: * @end: an end marker xmlChar, 0 if none
1214: * @end2: an end marker xmlChar, 0 if none
1215: * @end3: an end marker xmlChar, 0 if none
1.77 daniel 1216: *
1217: * [67] Reference ::= EntityRef | CharRef
1218: *
1219: * [69] PEReference ::= '%' Name ';'
1220: *
1221: * Returns A newly allocated string with the substitution done. The caller
1222: * must deallocate it !
1223: */
1.123 daniel 1224: xmlChar *
1.77 daniel 1225: xmlDecodeEntities(xmlParserCtxtPtr ctxt, int len, int what,
1.123 daniel 1226: xmlChar end, xmlChar end2, xmlChar end3) {
1227: xmlChar *buffer = NULL;
1.78 daniel 1228: int buffer_size = 0;
1.123 daniel 1229: xmlChar *out = NULL;
1.78 daniel 1230:
1.123 daniel 1231: xmlChar *current = NULL;
1.77 daniel 1232: xmlEntityPtr ent;
1.91 daniel 1233: int nbchars = 0;
1.77 daniel 1234: unsigned int max = (unsigned int) len;
1.123 daniel 1235: xmlChar cur;
1.77 daniel 1236:
1237: /*
1238: * allocate a translation buffer.
1239: */
1240: buffer_size = 1000;
1.123 daniel 1241: buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
1.77 daniel 1242: if (buffer == NULL) {
1243: perror("xmlDecodeEntities: malloc failed");
1244: return(NULL);
1245: }
1246: out = buffer;
1247:
1.78 daniel 1248: /*
1249: * Ok loop until we reach one of the ending char or a size limit.
1250: */
1.97 daniel 1251: cur = CUR;
1252: while ((nbchars < max) && (cur != end) &&
1253: (cur != end2) && (cur != end3)) {
1.77 daniel 1254:
1.98 daniel 1255: if (cur == 0) break;
1256: if ((cur == '&') && (NXT(1) == '#')) {
1257: int val = xmlParseCharRef(ctxt);
1258: *out++ = val;
1259: nbchars += 3;
1260: } else if ((cur == '&') && (what & XML_SUBSTITUTE_REF)) {
1261: ent = xmlParseEntityRef(ctxt);
1262: if ((ent != NULL) &&
1263: (ctxt->replaceEntities != 0)) {
1264: current = ent->content;
1265: while (*current != 0) {
1266: *out++ = *current++;
1267: if (out - buffer > buffer_size - 100) {
1268: int index = out - buffer;
1269:
1270: growBuffer(buffer);
1271: out = &buffer[index];
1.77 daniel 1272: }
1273: }
1.98 daniel 1274: nbchars += 3 + xmlStrlen(ent->name);
1275: } else if (ent != NULL) {
1276: int i = xmlStrlen(ent->name);
1.123 daniel 1277: const xmlChar *cur = ent->name;
1.98 daniel 1278:
1279: nbchars += i + 2;
1280: *out++ = '&';
1281: if (out - buffer > buffer_size - i - 100) {
1282: int index = out - buffer;
1283:
1284: growBuffer(buffer);
1285: out = &buffer[index];
1286: }
1287: for (;i > 0;i--)
1288: *out++ = *cur++;
1289: *out++ = ';';
1.77 daniel 1290: }
1.97 daniel 1291: } else if (cur == '%' && (what & XML_SUBSTITUTE_PEREF)) {
1292: /*
1.77 daniel 1293: * a PEReference induce to switch the entity flow,
1294: * we break here to flush the current set of chars
1295: * parsed if any. We will be called back later.
1.97 daniel 1296: */
1.91 daniel 1297: if (nbchars != 0) break;
1.77 daniel 1298:
1299: xmlParsePEReference(ctxt);
1.79 daniel 1300:
1.97 daniel 1301: /*
1.79 daniel 1302: * Pop-up of finished entities.
1.97 daniel 1303: */
1.79 daniel 1304: while ((CUR == 0) && (ctxt->inputNr > 1))
1305: xmlPopInput(ctxt);
1306:
1.98 daniel 1307: break;
1.77 daniel 1308: } else {
1.116 daniel 1309: /* invalid for UTF-8 , use COPY(out); !!!!!! */
1.97 daniel 1310: *out++ = cur;
1.91 daniel 1311: nbchars++;
1.86 daniel 1312: if (out - buffer > buffer_size - 100) {
1313: int index = out - buffer;
1314:
1315: growBuffer(buffer);
1316: out = &buffer[index];
1317: }
1.77 daniel 1318: NEXT;
1319: }
1.97 daniel 1320: cur = CUR;
1.77 daniel 1321: }
1322: *out++ = 0;
1323: return(buffer);
1324: }
1325:
1.1 veillard 1326:
1.28 daniel 1327: /************************************************************************
1328: * *
1.75 daniel 1329: * Commodity functions to handle encodings *
1330: * *
1331: ************************************************************************/
1332:
1333: /**
1334: * xmlSwitchEncoding:
1335: * @ctxt: the parser context
1.124 daniel 1336: * @enc: the encoding value (number)
1.75 daniel 1337: *
1338: * change the input functions when discovering the character encoding
1339: * of a given entity.
1340: */
1341: void
1342: xmlSwitchEncoding(xmlParserCtxtPtr ctxt, xmlCharEncoding enc)
1343: {
1344: switch (enc) {
1345: case XML_CHAR_ENCODING_ERROR:
1.123 daniel 1346: ctxt->errNo = XML_ERR_UNKNOWN_ENCODING;
1.75 daniel 1347: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1348: ctxt->sax->error(ctxt->userData, "encoding unknown\n");
1349: ctxt->wellFormed = 0;
1350: break;
1351: case XML_CHAR_ENCODING_NONE:
1352: /* let's assume it's UTF-8 without the XML decl */
1353: return;
1354: case XML_CHAR_ENCODING_UTF8:
1355: /* default encoding, no conversion should be needed */
1356: return;
1357: case XML_CHAR_ENCODING_UTF16LE:
1.123 daniel 1358: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 1359: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1360: ctxt->sax->error(ctxt->userData,
1361: "char encoding UTF16 little endian not supported\n");
1362: break;
1363: case XML_CHAR_ENCODING_UTF16BE:
1.123 daniel 1364: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 1365: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1366: ctxt->sax->error(ctxt->userData,
1367: "char encoding UTF16 big endian not supported\n");
1368: break;
1369: case XML_CHAR_ENCODING_UCS4LE:
1.123 daniel 1370: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 1371: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1372: ctxt->sax->error(ctxt->userData,
1373: "char encoding USC4 little endian not supported\n");
1374: break;
1375: case XML_CHAR_ENCODING_UCS4BE:
1.123 daniel 1376: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 1377: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1378: ctxt->sax->error(ctxt->userData,
1379: "char encoding USC4 big endian not supported\n");
1380: break;
1381: case XML_CHAR_ENCODING_EBCDIC:
1.123 daniel 1382: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 1383: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1384: ctxt->sax->error(ctxt->userData,
1385: "char encoding EBCDIC not supported\n");
1386: break;
1387: case XML_CHAR_ENCODING_UCS4_2143:
1.123 daniel 1388: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 1389: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1390: ctxt->sax->error(ctxt->userData,
1391: "char encoding UCS4 2143 not supported\n");
1392: break;
1393: case XML_CHAR_ENCODING_UCS4_3412:
1.123 daniel 1394: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 1395: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1396: ctxt->sax->error(ctxt->userData,
1397: "char encoding UCS4 3412 not supported\n");
1398: break;
1399: case XML_CHAR_ENCODING_UCS2:
1.123 daniel 1400: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 1401: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1402: ctxt->sax->error(ctxt->userData,
1403: "char encoding UCS2 not supported\n");
1404: break;
1405: case XML_CHAR_ENCODING_8859_1:
1.123 daniel 1406: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 1407: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1408: ctxt->sax->error(ctxt->userData,
1409: "char encoding ISO_8859_1 ISO Latin 1 not supported\n");
1410: break;
1411: case XML_CHAR_ENCODING_8859_2:
1.123 daniel 1412: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 1413: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1414: ctxt->sax->error(ctxt->userData,
1415: "char encoding ISO_8859_2 ISO Latin 2 not supported\n");
1416: break;
1417: case XML_CHAR_ENCODING_8859_3:
1.123 daniel 1418: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 1419: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1420: ctxt->sax->error(ctxt->userData,
1421: "char encoding ISO_8859_3 not supported\n");
1422: break;
1423: case XML_CHAR_ENCODING_8859_4:
1.123 daniel 1424: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 1425: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1426: ctxt->sax->error(ctxt->userData,
1427: "char encoding ISO_8859_4 not supported\n");
1428: break;
1429: case XML_CHAR_ENCODING_8859_5:
1.123 daniel 1430: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 1431: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1432: ctxt->sax->error(ctxt->userData,
1433: "char encoding ISO_8859_5 not supported\n");
1434: break;
1435: case XML_CHAR_ENCODING_8859_6:
1.123 daniel 1436: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 1437: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1438: ctxt->sax->error(ctxt->userData,
1439: "char encoding ISO_8859_6 not supported\n");
1440: break;
1441: case XML_CHAR_ENCODING_8859_7:
1.123 daniel 1442: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 1443: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1444: ctxt->sax->error(ctxt->userData,
1445: "char encoding ISO_8859_7 not supported\n");
1446: break;
1447: case XML_CHAR_ENCODING_8859_8:
1.123 daniel 1448: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 1449: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1450: ctxt->sax->error(ctxt->userData,
1451: "char encoding ISO_8859_8 not supported\n");
1452: break;
1453: case XML_CHAR_ENCODING_8859_9:
1.123 daniel 1454: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 1455: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1456: ctxt->sax->error(ctxt->userData,
1457: "char encoding ISO_8859_9 not supported\n");
1458: break;
1459: case XML_CHAR_ENCODING_2022_JP:
1.123 daniel 1460: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 1461: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1462: ctxt->sax->error(ctxt->userData,
1463: "char encoding ISO-2022-JPnot supported\n");
1464: break;
1465: case XML_CHAR_ENCODING_SHIFT_JIS:
1.123 daniel 1466: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 1467: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1468: ctxt->sax->error(ctxt->userData,
1469: "char encoding Shift_JISnot supported\n");
1470: break;
1471: case XML_CHAR_ENCODING_EUC_JP:
1.123 daniel 1472: ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75 daniel 1473: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1474: ctxt->sax->error(ctxt->userData,
1475: "char encoding EUC-JPnot supported\n");
1476: break;
1477: }
1478: }
1479:
1480: /************************************************************************
1481: * *
1.123 daniel 1482: * Commodity functions to handle xmlChars *
1.28 daniel 1483: * *
1484: ************************************************************************/
1485:
1.50 daniel 1486: /**
1487: * xmlStrndup:
1.123 daniel 1488: * @cur: the input xmlChar *
1.50 daniel 1489: * @len: the len of @cur
1490: *
1.123 daniel 1491: * a strndup for array of xmlChar's
1.68 daniel 1492: *
1.123 daniel 1493: * Returns a new xmlChar * or NULL
1.1 veillard 1494: */
1.123 daniel 1495: xmlChar *
1496: xmlStrndup(const xmlChar *cur, int len) {
1497: xmlChar *ret = xmlMalloc((len + 1) * sizeof(xmlChar));
1.1 veillard 1498:
1499: if (ret == NULL) {
1.86 daniel 1500: fprintf(stderr, "malloc of %ld byte failed\n",
1.123 daniel 1501: (len + 1) * (long)sizeof(xmlChar));
1.1 veillard 1502: return(NULL);
1503: }
1.123 daniel 1504: memcpy(ret, cur, len * sizeof(xmlChar));
1.1 veillard 1505: ret[len] = 0;
1506: return(ret);
1507: }
1508:
1.50 daniel 1509: /**
1510: * xmlStrdup:
1.123 daniel 1511: * @cur: the input xmlChar *
1.50 daniel 1512: *
1.123 daniel 1513: * a strdup for array of xmlChar's
1.68 daniel 1514: *
1.123 daniel 1515: * Returns a new xmlChar * or NULL
1.1 veillard 1516: */
1.123 daniel 1517: xmlChar *
1518: xmlStrdup(const xmlChar *cur) {
1519: const xmlChar *p = cur;
1.1 veillard 1520:
1521: while (IS_CHAR(*p)) p++;
1522: return(xmlStrndup(cur, p - cur));
1523: }
1524:
1.50 daniel 1525: /**
1526: * xmlCharStrndup:
1527: * @cur: the input char *
1528: * @len: the len of @cur
1529: *
1.123 daniel 1530: * a strndup for char's to xmlChar's
1.68 daniel 1531: *
1.123 daniel 1532: * Returns a new xmlChar * or NULL
1.45 daniel 1533: */
1534:
1.123 daniel 1535: xmlChar *
1.55 daniel 1536: xmlCharStrndup(const char *cur, int len) {
1.45 daniel 1537: int i;
1.123 daniel 1538: xmlChar *ret = xmlMalloc((len + 1) * sizeof(xmlChar));
1.45 daniel 1539:
1540: if (ret == NULL) {
1.86 daniel 1541: fprintf(stderr, "malloc of %ld byte failed\n",
1.123 daniel 1542: (len + 1) * (long)sizeof(xmlChar));
1.45 daniel 1543: return(NULL);
1544: }
1545: for (i = 0;i < len;i++)
1.123 daniel 1546: ret[i] = (xmlChar) cur[i];
1.45 daniel 1547: ret[len] = 0;
1548: return(ret);
1549: }
1550:
1.50 daniel 1551: /**
1552: * xmlCharStrdup:
1553: * @cur: the input char *
1554: * @len: the len of @cur
1555: *
1.123 daniel 1556: * a strdup for char's to xmlChar's
1.68 daniel 1557: *
1.123 daniel 1558: * Returns a new xmlChar * or NULL
1.45 daniel 1559: */
1560:
1.123 daniel 1561: xmlChar *
1.55 daniel 1562: xmlCharStrdup(const char *cur) {
1.45 daniel 1563: const char *p = cur;
1564:
1565: while (*p != '\0') p++;
1566: return(xmlCharStrndup(cur, p - cur));
1567: }
1568:
1.50 daniel 1569: /**
1570: * xmlStrcmp:
1.123 daniel 1571: * @str1: the first xmlChar *
1572: * @str2: the second xmlChar *
1.50 daniel 1573: *
1.123 daniel 1574: * a strcmp for xmlChar's
1.68 daniel 1575: *
1576: * Returns the integer result of the comparison
1.14 veillard 1577: */
1578:
1.55 daniel 1579: int
1.123 daniel 1580: xmlStrcmp(const xmlChar *str1, const xmlChar *str2) {
1.14 veillard 1581: register int tmp;
1582:
1583: do {
1584: tmp = *str1++ - *str2++;
1585: if (tmp != 0) return(tmp);
1586: } while ((*str1 != 0) && (*str2 != 0));
1587: return (*str1 - *str2);
1588: }
1589:
1.50 daniel 1590: /**
1591: * xmlStrncmp:
1.123 daniel 1592: * @str1: the first xmlChar *
1593: * @str2: the second xmlChar *
1.50 daniel 1594: * @len: the max comparison length
1595: *
1.123 daniel 1596: * a strncmp for xmlChar's
1.68 daniel 1597: *
1598: * Returns the integer result of the comparison
1.14 veillard 1599: */
1600:
1.55 daniel 1601: int
1.123 daniel 1602: xmlStrncmp(const xmlChar *str1, const xmlChar *str2, int len) {
1.14 veillard 1603: register int tmp;
1604:
1605: if (len <= 0) return(0);
1606: do {
1607: tmp = *str1++ - *str2++;
1608: if (tmp != 0) return(tmp);
1609: len--;
1610: if (len <= 0) return(0);
1611: } while ((*str1 != 0) && (*str2 != 0));
1612: return (*str1 - *str2);
1613: }
1614:
1.50 daniel 1615: /**
1616: * xmlStrchr:
1.123 daniel 1617: * @str: the xmlChar * array
1618: * @val: the xmlChar to search
1.50 daniel 1619: *
1.123 daniel 1620: * a strchr for xmlChar's
1.68 daniel 1621: *
1.123 daniel 1622: * Returns the xmlChar * for the first occurence or NULL.
1.14 veillard 1623: */
1624:
1.123 daniel 1625: const xmlChar *
1626: xmlStrchr(const xmlChar *str, xmlChar val) {
1.14 veillard 1627: while (*str != 0) {
1.123 daniel 1628: if (*str == val) return((xmlChar *) str);
1.14 veillard 1629: str++;
1630: }
1631: return(NULL);
1.89 daniel 1632: }
1633:
1634: /**
1635: * xmlStrstr:
1.123 daniel 1636: * @str: the xmlChar * array (haystack)
1637: * @val: the xmlChar to search (needle)
1.89 daniel 1638: *
1.123 daniel 1639: * a strstr for xmlChar's
1.89 daniel 1640: *
1.123 daniel 1641: * Returns the xmlChar * for the first occurence or NULL.
1.89 daniel 1642: */
1643:
1.123 daniel 1644: const xmlChar *
1645: xmlStrstr(const xmlChar *str, xmlChar *val) {
1.89 daniel 1646: int n;
1647:
1648: if (str == NULL) return(NULL);
1649: if (val == NULL) return(NULL);
1650: n = xmlStrlen(val);
1651:
1652: if (n == 0) return(str);
1653: while (*str != 0) {
1654: if (*str == *val) {
1.123 daniel 1655: if (!xmlStrncmp(str, val, n)) return((const xmlChar *) str);
1.89 daniel 1656: }
1657: str++;
1658: }
1659: return(NULL);
1660: }
1661:
1662: /**
1663: * xmlStrsub:
1.123 daniel 1664: * @str: the xmlChar * array (haystack)
1.89 daniel 1665: * @start: the index of the first char (zero based)
1666: * @len: the length of the substring
1667: *
1668: * Extract a substring of a given string
1669: *
1.123 daniel 1670: * Returns the xmlChar * for the first occurence or NULL.
1.89 daniel 1671: */
1672:
1.123 daniel 1673: xmlChar *
1674: xmlStrsub(const xmlChar *str, int start, int len) {
1.89 daniel 1675: int i;
1676:
1677: if (str == NULL) return(NULL);
1678: if (start < 0) return(NULL);
1.90 daniel 1679: if (len < 0) return(NULL);
1.89 daniel 1680:
1681: for (i = 0;i < start;i++) {
1682: if (*str == 0) return(NULL);
1683: str++;
1684: }
1685: if (*str == 0) return(NULL);
1686: return(xmlStrndup(str, len));
1.14 veillard 1687: }
1.28 daniel 1688:
1.50 daniel 1689: /**
1690: * xmlStrlen:
1.123 daniel 1691: * @str: the xmlChar * array
1.50 daniel 1692: *
1.127 daniel 1693: * length of a xmlChar's string
1.68 daniel 1694: *
1.123 daniel 1695: * Returns the number of xmlChar contained in the ARRAY.
1.45 daniel 1696: */
1697:
1.55 daniel 1698: int
1.123 daniel 1699: xmlStrlen(const xmlChar *str) {
1.45 daniel 1700: int len = 0;
1701:
1702: if (str == NULL) return(0);
1703: while (*str != 0) {
1704: str++;
1705: len++;
1706: }
1707: return(len);
1708: }
1709:
1.50 daniel 1710: /**
1711: * xmlStrncat:
1.123 daniel 1712: * @cur: the original xmlChar * array
1713: * @add: the xmlChar * array added
1.50 daniel 1714: * @len: the length of @add
1715: *
1.123 daniel 1716: * a strncat for array of xmlChar's
1.68 daniel 1717: *
1.123 daniel 1718: * Returns a new xmlChar * containing the concatenated string.
1.45 daniel 1719: */
1720:
1.123 daniel 1721: xmlChar *
1722: xmlStrncat(xmlChar *cur, const xmlChar *add, int len) {
1.45 daniel 1723: int size;
1.123 daniel 1724: xmlChar *ret;
1.45 daniel 1725:
1726: if ((add == NULL) || (len == 0))
1727: return(cur);
1728: if (cur == NULL)
1729: return(xmlStrndup(add, len));
1730:
1731: size = xmlStrlen(cur);
1.123 daniel 1732: ret = xmlRealloc(cur, (size + len + 1) * sizeof(xmlChar));
1.45 daniel 1733: if (ret == NULL) {
1.86 daniel 1734: fprintf(stderr, "xmlStrncat: realloc of %ld byte failed\n",
1.123 daniel 1735: (size + len + 1) * (long)sizeof(xmlChar));
1.45 daniel 1736: return(cur);
1737: }
1.123 daniel 1738: memcpy(&ret[size], add, len * sizeof(xmlChar));
1.45 daniel 1739: ret[size + len] = 0;
1740: return(ret);
1741: }
1742:
1.50 daniel 1743: /**
1744: * xmlStrcat:
1.123 daniel 1745: * @cur: the original xmlChar * array
1746: * @add: the xmlChar * array added
1.50 daniel 1747: *
1.123 daniel 1748: * a strcat for array of xmlChar's
1.68 daniel 1749: *
1.123 daniel 1750: * Returns a new xmlChar * containing the concatenated string.
1.45 daniel 1751: */
1.123 daniel 1752: xmlChar *
1753: xmlStrcat(xmlChar *cur, const xmlChar *add) {
1754: const xmlChar *p = add;
1.45 daniel 1755:
1756: if (add == NULL) return(cur);
1757: if (cur == NULL)
1758: return(xmlStrdup(add));
1759:
1760: while (IS_CHAR(*p)) p++;
1761: return(xmlStrncat(cur, add, p - add));
1762: }
1763:
1764: /************************************************************************
1765: * *
1766: * Commodity functions, cleanup needed ? *
1767: * *
1768: ************************************************************************/
1769:
1.50 daniel 1770: /**
1771: * areBlanks:
1772: * @ctxt: an XML parser context
1.123 daniel 1773: * @str: a xmlChar *
1.50 daniel 1774: * @len: the size of @str
1775: *
1.45 daniel 1776: * Is this a sequence of blank chars that one can ignore ?
1.50 daniel 1777: *
1.99 daniel 1778: * TODO: Whether white space are significant has to be checked accordingly
1779: * to DTD informations if available
1.68 daniel 1780: *
1781: * Returns 1 if ignorable 0 otherwise.
1.45 daniel 1782: */
1783:
1.123 daniel 1784: static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
1.104 daniel 1785: int i, ret;
1.45 daniel 1786: xmlNodePtr lastChild;
1787:
1788: for (i = 0;i < len;i++)
1789: if (!(IS_BLANK(str[i]))) return(0);
1790:
1791: if (CUR != '<') return(0);
1.72 daniel 1792: if (ctxt->node == NULL) return(0);
1.104 daniel 1793: if (ctxt->myDoc != NULL) {
1794: ret = xmlIsMixedElement(ctxt->myDoc, ctxt->node->name);
1795: if (ret == 0) return(1);
1796: if (ret == 1) return(0);
1797: }
1798: /*
1799: * heuristic
1800: */
1.45 daniel 1801: lastChild = xmlGetLastChild(ctxt->node);
1802: if (lastChild == NULL) {
1803: if (ctxt->node->content != NULL) return(0);
1804: } else if (xmlNodeIsText(lastChild))
1805: return(0);
1.104 daniel 1806: else if ((ctxt->node->childs != NULL) &&
1807: (xmlNodeIsText(ctxt->node->childs)))
1808: return(0);
1.45 daniel 1809: return(1);
1810: }
1811:
1.50 daniel 1812: /**
1813: * xmlHandleEntity:
1814: * @ctxt: an XML parser context
1815: * @entity: an XML entity pointer.
1816: *
1817: * Default handling of defined entities, when should we define a new input
1.45 daniel 1818: * stream ? When do we just handle that as a set of chars ?
1.99 daniel 1819: *
1820: * OBSOLETE: to be removed at some point.
1.45 daniel 1821: */
1822:
1.55 daniel 1823: void
1824: xmlHandleEntity(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
1.45 daniel 1825: int len;
1.50 daniel 1826: xmlParserInputPtr input;
1.45 daniel 1827:
1828: if (entity->content == NULL) {
1.123 daniel 1829: ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1.55 daniel 1830: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 1831: ctxt->sax->error(ctxt->userData, "xmlHandleEntity %s: content == NULL\n",
1.45 daniel 1832: entity->name);
1.59 daniel 1833: ctxt->wellFormed = 0;
1.45 daniel 1834: return;
1835: }
1836: len = xmlStrlen(entity->content);
1837: if (len <= 2) goto handle_as_char;
1838:
1839: /*
1840: * Redefine its content as an input stream.
1841: */
1.50 daniel 1842: input = xmlNewEntityInputStream(ctxt, entity);
1843: xmlPushInput(ctxt, input);
1.45 daniel 1844: return;
1845:
1846: handle_as_char:
1847: /*
1848: * Just handle the content as a set of chars.
1849: */
1.72 daniel 1850: if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
1.74 daniel 1851: ctxt->sax->characters(ctxt->userData, entity->content, len);
1.45 daniel 1852:
1853: }
1854:
1855: /*
1856: * Forward definition for recusive behaviour.
1857: */
1.77 daniel 1858: void xmlParsePEReference(xmlParserCtxtPtr ctxt);
1859: void xmlParseReference(xmlParserCtxtPtr ctxt);
1.45 daniel 1860:
1.28 daniel 1861: /************************************************************************
1862: * *
1863: * Extra stuff for namespace support *
1864: * Relates to http://www.w3.org/TR/WD-xml-names *
1865: * *
1866: ************************************************************************/
1867:
1.50 daniel 1868: /**
1869: * xmlNamespaceParseNCName:
1870: * @ctxt: an XML parser context
1871: *
1872: * parse an XML namespace name.
1.28 daniel 1873: *
1874: * [NS 3] NCName ::= (Letter | '_') (NCNameChar)*
1875: *
1876: * [NS 4] NCNameChar ::= Letter | Digit | '.' | '-' | '_' |
1877: * CombiningChar | Extender
1.68 daniel 1878: *
1879: * Returns the namespace name or NULL
1.28 daniel 1880: */
1881:
1.123 daniel 1882: xmlChar *
1.55 daniel 1883: xmlNamespaceParseNCName(xmlParserCtxtPtr ctxt) {
1.123 daniel 1884: xmlChar buf[XML_MAX_NAMELEN];
1.91 daniel 1885: int len = 0;
1.28 daniel 1886:
1.40 daniel 1887: if (!IS_LETTER(CUR) && (CUR != '_')) return(NULL);
1.28 daniel 1888:
1.40 daniel 1889: while ((IS_LETTER(CUR)) || (IS_DIGIT(CUR)) ||
1890: (CUR == '.') || (CUR == '-') ||
1891: (CUR == '_') ||
1892: (IS_COMBINING(CUR)) ||
1.91 daniel 1893: (IS_EXTENDER(CUR))) {
1894: buf[len++] = CUR;
1.40 daniel 1895: NEXT;
1.91 daniel 1896: if (len >= XML_MAX_NAMELEN) {
1897: fprintf(stderr,
1898: "xmlNamespaceParseNCName: reached XML_MAX_NAMELEN limit\n");
1899: while ((IS_LETTER(CUR)) || (IS_DIGIT(CUR)) ||
1900: (CUR == '.') || (CUR == '-') ||
1901: (CUR == '_') ||
1902: (IS_COMBINING(CUR)) ||
1903: (IS_EXTENDER(CUR)))
1904: NEXT;
1905: break;
1906: }
1907: }
1908: return(xmlStrndup(buf, len));
1.28 daniel 1909: }
1910:
1.50 daniel 1911: /**
1912: * xmlNamespaceParseQName:
1913: * @ctxt: an XML parser context
1.123 daniel 1914: * @prefix: a xmlChar **
1.50 daniel 1915: *
1916: * parse an XML qualified name
1.28 daniel 1917: *
1918: * [NS 5] QName ::= (Prefix ':')? LocalPart
1919: *
1920: * [NS 6] Prefix ::= NCName
1921: *
1922: * [NS 7] LocalPart ::= NCName
1.68 daniel 1923: *
1.127 daniel 1924: * Returns the local part, and prefix is updated
1.50 daniel 1925: * to get the Prefix if any.
1.28 daniel 1926: */
1927:
1.123 daniel 1928: xmlChar *
1929: xmlNamespaceParseQName(xmlParserCtxtPtr ctxt, xmlChar **prefix) {
1930: xmlChar *ret = NULL;
1.28 daniel 1931:
1932: *prefix = NULL;
1933: ret = xmlNamespaceParseNCName(ctxt);
1.40 daniel 1934: if (CUR == ':') {
1.28 daniel 1935: *prefix = ret;
1.40 daniel 1936: NEXT;
1.28 daniel 1937: ret = xmlNamespaceParseNCName(ctxt);
1938: }
1939:
1940: return(ret);
1941: }
1942:
1.50 daniel 1943: /**
1.72 daniel 1944: * xmlSplitQName:
1945: * @name: an XML parser context
1.123 daniel 1946: * @prefix: a xmlChar **
1.72 daniel 1947: *
1948: * parse an XML qualified name string
1949: *
1950: * [NS 5] QName ::= (Prefix ':')? LocalPart
1951: *
1952: * [NS 6] Prefix ::= NCName
1953: *
1954: * [NS 7] LocalPart ::= NCName
1955: *
1.127 daniel 1956: * Returns the local part, and prefix is updated
1.72 daniel 1957: * to get the Prefix if any.
1958: */
1959:
1.123 daniel 1960: xmlChar *
1961: xmlSplitQName(const xmlChar *name, xmlChar **prefix) {
1962: xmlChar *ret = NULL;
1963: const xmlChar *q;
1964: const xmlChar *cur = name;
1.72 daniel 1965:
1966: *prefix = NULL;
1.113 daniel 1967:
1968: /* xml: prefix is not really a namespace */
1969: if ((cur[0] == 'x') && (cur[1] == 'm') &&
1970: (cur[2] == 'l') && (cur[3] == ':'))
1971: return(xmlStrdup(name));
1972:
1.72 daniel 1973: if (!IS_LETTER(*cur) && (*cur != '_')) return(NULL);
1974: q = cur++;
1975:
1976: while ((IS_LETTER(*cur)) || (IS_DIGIT(*cur)) ||
1977: (*cur == '.') || (*cur == '-') ||
1978: (*cur == '_') ||
1979: (IS_COMBINING(*cur)) ||
1980: (IS_EXTENDER(*cur)))
1981: cur++;
1982:
1983: ret = xmlStrndup(q, cur - q);
1984:
1985: if (*cur == ':') {
1986: cur++;
1987: if (!IS_LETTER(*cur) && (*cur != '_')) return(ret);
1988: *prefix = ret;
1989:
1990: q = cur++;
1991:
1992: while ((IS_LETTER(*cur)) || (IS_DIGIT(*cur)) ||
1993: (*cur == '.') || (*cur == '-') ||
1994: (*cur == '_') ||
1995: (IS_COMBINING(*cur)) ||
1996: (IS_EXTENDER(*cur)))
1997: cur++;
1998:
1999: ret = xmlStrndup(q, cur - q);
2000: }
2001:
2002: return(ret);
2003: }
2004: /**
1.50 daniel 2005: * xmlNamespaceParseNSDef:
2006: * @ctxt: an XML parser context
2007: *
2008: * parse a namespace prefix declaration
1.28 daniel 2009: *
2010: * [NS 1] NSDef ::= PrefixDef Eq SystemLiteral
2011: *
2012: * [NS 2] PrefixDef ::= 'xmlns' (':' NCName)?
1.68 daniel 2013: *
2014: * Returns the namespace name
1.28 daniel 2015: */
2016:
1.123 daniel 2017: xmlChar *
1.55 daniel 2018: xmlNamespaceParseNSDef(xmlParserCtxtPtr ctxt) {
1.123 daniel 2019: xmlChar *name = NULL;
1.28 daniel 2020:
1.40 daniel 2021: if ((CUR == 'x') && (NXT(1) == 'm') &&
2022: (NXT(2) == 'l') && (NXT(3) == 'n') &&
2023: (NXT(4) == 's')) {
2024: SKIP(5);
2025: if (CUR == ':') {
2026: NEXT;
1.28 daniel 2027: name = xmlNamespaceParseNCName(ctxt);
2028: }
2029: }
1.39 daniel 2030: return(name);
1.28 daniel 2031: }
2032:
1.50 daniel 2033: /**
2034: * xmlParseQuotedString:
2035: * @ctxt: an XML parser context
2036: *
1.45 daniel 2037: * [OLD] Parse and return a string between quotes or doublequotes
1.110 daniel 2038: * To be removed at next drop of binary compatibility
1.68 daniel 2039: *
2040: * Returns the string parser or NULL.
1.45 daniel 2041: */
1.123 daniel 2042: xmlChar *
1.55 daniel 2043: xmlParseQuotedString(xmlParserCtxtPtr ctxt) {
1.123 daniel 2044: xmlChar *ret = NULL;
2045: const xmlChar *q;
1.45 daniel 2046:
2047: if (CUR == '"') {
2048: NEXT;
2049: q = CUR_PTR;
2050: while (IS_CHAR(CUR) && (CUR != '"')) NEXT;
1.55 daniel 2051: if (CUR != '"') {
1.123 daniel 2052: ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
1.55 daniel 2053: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 2054: ctxt->sax->error(ctxt->userData, "String not closed \"%.50s\"\n", q);
1.59 daniel 2055: ctxt->wellFormed = 0;
1.55 daniel 2056: } else {
1.45 daniel 2057: ret = xmlStrndup(q, CUR_PTR - q);
2058: NEXT;
2059: }
2060: } else if (CUR == '\''){
2061: NEXT;
2062: q = CUR_PTR;
2063: while (IS_CHAR(CUR) && (CUR != '\'')) NEXT;
1.55 daniel 2064: if (CUR != '\'') {
1.123 daniel 2065: ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
1.55 daniel 2066: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 2067: ctxt->sax->error(ctxt->userData, "String not closed \"%.50s\"\n", q);
1.59 daniel 2068: ctxt->wellFormed = 0;
1.55 daniel 2069: } else {
1.45 daniel 2070: ret = xmlStrndup(q, CUR_PTR - q);
2071: NEXT;
2072: }
2073: }
2074: return(ret);
2075: }
2076:
1.50 daniel 2077: /**
2078: * xmlParseNamespace:
2079: * @ctxt: an XML parser context
2080: *
1.45 daniel 2081: * [OLD] xmlParseNamespace: parse specific PI '<?namespace ...' constructs.
2082: *
2083: * This is what the older xml-name Working Draft specified, a bunch of
2084: * other stuff may still rely on it, so support is still here as
1.127 daniel 2085: * if it was declared on the root of the Tree:-(
1.110 daniel 2086: *
2087: * To be removed at next drop of binary compatibility
1.45 daniel 2088: */
2089:
1.55 daniel 2090: void
2091: xmlParseNamespace(xmlParserCtxtPtr ctxt) {
1.123 daniel 2092: xmlChar *href = NULL;
2093: xmlChar *prefix = NULL;
1.45 daniel 2094: int garbage = 0;
2095:
2096: /*
2097: * We just skipped "namespace" or "xml:namespace"
2098: */
2099: SKIP_BLANKS;
2100:
2101: while (IS_CHAR(CUR) && (CUR != '>')) {
2102: /*
2103: * We can have "ns" or "prefix" attributes
2104: * Old encoding as 'href' or 'AS' attributes is still supported
2105: */
2106: if ((CUR == 'n') && (NXT(1) == 's')) {
2107: garbage = 0;
2108: SKIP(2);
2109: SKIP_BLANKS;
2110:
2111: if (CUR != '=') continue;
2112: NEXT;
2113: SKIP_BLANKS;
2114:
2115: href = xmlParseQuotedString(ctxt);
2116: SKIP_BLANKS;
2117: } else if ((CUR == 'h') && (NXT(1) == 'r') &&
2118: (NXT(2) == 'e') && (NXT(3) == 'f')) {
2119: garbage = 0;
2120: SKIP(4);
2121: SKIP_BLANKS;
2122:
2123: if (CUR != '=') continue;
2124: NEXT;
2125: SKIP_BLANKS;
2126:
2127: href = xmlParseQuotedString(ctxt);
2128: SKIP_BLANKS;
2129: } else if ((CUR == 'p') && (NXT(1) == 'r') &&
2130: (NXT(2) == 'e') && (NXT(3) == 'f') &&
2131: (NXT(4) == 'i') && (NXT(5) == 'x')) {
2132: garbage = 0;
2133: SKIP(6);
2134: SKIP_BLANKS;
2135:
2136: if (CUR != '=') continue;
2137: NEXT;
2138: SKIP_BLANKS;
2139:
2140: prefix = xmlParseQuotedString(ctxt);
2141: SKIP_BLANKS;
2142: } else if ((CUR == 'A') && (NXT(1) == 'S')) {
2143: garbage = 0;
2144: SKIP(2);
2145: SKIP_BLANKS;
2146:
2147: if (CUR != '=') continue;
2148: NEXT;
2149: SKIP_BLANKS;
2150:
2151: prefix = xmlParseQuotedString(ctxt);
2152: SKIP_BLANKS;
2153: } else if ((CUR == '?') && (NXT(1) == '>')) {
2154: garbage = 0;
1.91 daniel 2155: NEXT;
1.45 daniel 2156: } else {
2157: /*
2158: * Found garbage when parsing the namespace
2159: */
1.122 daniel 2160: if (!garbage) {
1.55 daniel 2161: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 2162: ctxt->sax->error(ctxt->userData,
2163: "xmlParseNamespace found garbage\n");
2164: }
1.123 daniel 2165: ctxt->errNo = XML_ERR_NS_DECL_ERROR;
1.59 daniel 2166: ctxt->wellFormed = 0;
1.45 daniel 2167: NEXT;
2168: }
2169: }
2170:
2171: MOVETO_ENDTAG(CUR_PTR);
2172: NEXT;
2173:
2174: /*
2175: * Register the DTD.
1.72 daniel 2176: if (href != NULL)
2177: if ((ctxt->sax != NULL) && (ctxt->sax->globalNamespace != NULL))
1.74 daniel 2178: ctxt->sax->globalNamespace(ctxt->userData, href, prefix);
1.45 daniel 2179: */
2180:
1.119 daniel 2181: if (prefix != NULL) xmlFree(prefix);
2182: if (href != NULL) xmlFree(href);
1.45 daniel 2183: }
2184:
1.28 daniel 2185: /************************************************************************
2186: * *
2187: * The parser itself *
2188: * Relates to http://www.w3.org/TR/REC-xml *
2189: * *
2190: ************************************************************************/
1.14 veillard 2191:
1.50 daniel 2192: /**
1.97 daniel 2193: * xmlScanName:
2194: * @ctxt: an XML parser context
2195: *
2196: * Trickery: parse an XML name but without consuming the input flow
2197: * Needed for rollback cases.
2198: *
2199: * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
2200: * CombiningChar | Extender
2201: *
2202: * [5] Name ::= (Letter | '_' | ':') (NameChar)*
2203: *
2204: * [6] Names ::= Name (S Name)*
2205: *
2206: * Returns the Name parsed or NULL
2207: */
2208:
1.123 daniel 2209: xmlChar *
1.97 daniel 2210: xmlScanName(xmlParserCtxtPtr ctxt) {
1.123 daniel 2211: xmlChar buf[XML_MAX_NAMELEN];
1.97 daniel 2212: int len = 0;
2213:
2214: GROW;
2215: if (!IS_LETTER(CUR) && (CUR != '_') &&
2216: (CUR != ':')) {
2217: return(NULL);
2218: }
2219:
2220: while ((IS_LETTER(NXT(len))) || (IS_DIGIT(NXT(len))) ||
2221: (NXT(len) == '.') || (NXT(len) == '-') ||
2222: (NXT(len) == '_') || (NXT(len) == ':') ||
2223: (IS_COMBINING(NXT(len))) ||
2224: (IS_EXTENDER(NXT(len)))) {
2225: buf[len] = NXT(len);
2226: len++;
2227: if (len >= XML_MAX_NAMELEN) {
2228: fprintf(stderr,
2229: "xmlScanName: reached XML_MAX_NAMELEN limit\n");
2230: while ((IS_LETTER(NXT(len))) || (IS_DIGIT(NXT(len))) ||
2231: (NXT(len) == '.') || (NXT(len) == '-') ||
2232: (NXT(len) == '_') || (NXT(len) == ':') ||
2233: (IS_COMBINING(NXT(len))) ||
2234: (IS_EXTENDER(NXT(len))))
2235: len++;
2236: break;
2237: }
2238: }
2239: return(xmlStrndup(buf, len));
2240: }
2241:
2242: /**
1.50 daniel 2243: * xmlParseName:
2244: * @ctxt: an XML parser context
2245: *
2246: * parse an XML name.
1.22 daniel 2247: *
2248: * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
2249: * CombiningChar | Extender
2250: *
2251: * [5] Name ::= (Letter | '_' | ':') (NameChar)*
2252: *
2253: * [6] Names ::= Name (S Name)*
1.68 daniel 2254: *
2255: * Returns the Name parsed or NULL
1.1 veillard 2256: */
2257:
1.123 daniel 2258: xmlChar *
1.55 daniel 2259: xmlParseName(xmlParserCtxtPtr ctxt) {
1.123 daniel 2260: xmlChar buf[XML_MAX_NAMELEN];
1.91 daniel 2261: int len = 0;
1.123 daniel 2262: xmlChar cur;
1.1 veillard 2263:
1.91 daniel 2264: GROW;
1.97 daniel 2265: cur = CUR;
2266: if (!IS_LETTER(cur) && (cur != '_') &&
2267: (cur != ':')) {
1.91 daniel 2268: return(NULL);
2269: }
1.40 daniel 2270:
1.97 daniel 2271: while ((IS_LETTER(cur)) || (IS_DIGIT(cur)) ||
2272: (cur == '.') || (cur == '-') ||
2273: (cur == '_') || (cur == ':') ||
2274: (IS_COMBINING(cur)) ||
2275: (IS_EXTENDER(cur))) {
2276: buf[len++] = cur;
1.40 daniel 2277: NEXT;
1.97 daniel 2278: cur = CUR;
1.91 daniel 2279: if (len >= XML_MAX_NAMELEN) {
2280: fprintf(stderr,
2281: "xmlParseName: reached XML_MAX_NAMELEN limit\n");
1.97 daniel 2282: while ((IS_LETTER(cur)) || (IS_DIGIT(cur)) ||
2283: (cur == '.') || (cur == '-') ||
2284: (cur == '_') || (cur == ':') ||
2285: (IS_COMBINING(cur)) ||
2286: (IS_EXTENDER(cur))) {
2287: NEXT;
2288: cur = CUR;
2289: }
1.91 daniel 2290: break;
2291: }
2292: }
2293: return(xmlStrndup(buf, len));
1.22 daniel 2294: }
2295:
1.50 daniel 2296: /**
2297: * xmlParseNmtoken:
2298: * @ctxt: an XML parser context
2299: *
2300: * parse an XML Nmtoken.
1.22 daniel 2301: *
2302: * [7] Nmtoken ::= (NameChar)+
2303: *
2304: * [8] Nmtokens ::= Nmtoken (S Nmtoken)*
1.68 daniel 2305: *
2306: * Returns the Nmtoken parsed or NULL
1.22 daniel 2307: */
2308:
1.123 daniel 2309: xmlChar *
1.55 daniel 2310: xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
1.123 daniel 2311: xmlChar buf[XML_MAX_NAMELEN];
1.91 daniel 2312: int len = 0;
1.22 daniel 2313:
1.91 daniel 2314: GROW;
1.40 daniel 2315: while ((IS_LETTER(CUR)) || (IS_DIGIT(CUR)) ||
2316: (CUR == '.') || (CUR == '-') ||
2317: (CUR == '_') || (CUR == ':') ||
2318: (IS_COMBINING(CUR)) ||
1.91 daniel 2319: (IS_EXTENDER(CUR))) {
2320: buf[len++] = CUR;
1.40 daniel 2321: NEXT;
1.91 daniel 2322: if (len >= XML_MAX_NAMELEN) {
2323: fprintf(stderr,
2324: "xmlParseNmtoken: reached XML_MAX_NAMELEN limit\n");
2325: while ((IS_LETTER(CUR)) || (IS_DIGIT(CUR)) ||
2326: (CUR == '.') || (CUR == '-') ||
2327: (CUR == '_') || (CUR == ':') ||
2328: (IS_COMBINING(CUR)) ||
2329: (IS_EXTENDER(CUR)))
2330: NEXT;
2331: break;
2332: }
2333: }
2334: return(xmlStrndup(buf, len));
1.1 veillard 2335: }
2336:
1.50 daniel 2337: /**
2338: * xmlParseEntityValue:
2339: * @ctxt: an XML parser context
1.78 daniel 2340: * @orig: if non-NULL store a copy of the original entity value
1.50 daniel 2341: *
2342: * parse a value for ENTITY decl.
1.24 daniel 2343: *
2344: * [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' |
2345: * "'" ([^%&'] | PEReference | Reference)* "'"
1.68 daniel 2346: *
1.78 daniel 2347: * Returns the EntityValue parsed with reference substitued or NULL
1.24 daniel 2348: */
2349:
1.123 daniel 2350: xmlChar *
2351: xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
2352: xmlChar *ret = NULL;
2353: const xmlChar *org = NULL;
2354: const xmlChar *tst = NULL;
2355: const xmlChar *temp = NULL;
1.98 daniel 2356: xmlParserInputPtr input;
1.24 daniel 2357:
1.91 daniel 2358: SHRINK;
1.40 daniel 2359: if (CUR == '"') {
1.96 daniel 2360: ctxt->instate = XML_PARSER_ENTITY_VALUE;
1.98 daniel 2361: input = ctxt->input;
1.40 daniel 2362: NEXT;
1.78 daniel 2363: org = CUR_PTR;
1.98 daniel 2364: /*
2365: * NOTE: 4.4.5 Included in Literal
2366: * When a parameter entity reference appears in a literal entity
2367: * value, ... a single or double quote character in the replacement
2368: * text is always treated as a normal data character and will not
2369: * terminate the literal.
2370: * In practice it means we stop the loop only when back at parsing
2371: * the initial entity and the quote is found
2372: */
2373: while ((CUR != '"') || (ctxt->input != input)) {
1.79 daniel 2374: tst = CUR_PTR;
1.98 daniel 2375: /*
2376: * NOTE: 4.4.7 Bypassed
2377: * When a general entity reference appears in the EntityValue in
2378: * an entity declaration, it is bypassed and left as is.
2379: * so XML_SUBSTITUTE_REF is not set.
2380: */
2381: if (ctxt->input != input)
2382: temp = xmlDecodeEntities(ctxt, -1, XML_SUBSTITUTE_PEREF,
2383: 0, 0, 0);
2384: else
2385: temp = xmlDecodeEntities(ctxt, -1, XML_SUBSTITUTE_PEREF,
2386: '"', 0, 0);
1.94 daniel 2387:
2388: /*
2389: * Pop-up of finished entities.
2390: */
2391: while ((CUR == 0) && (ctxt->inputNr > 1))
2392: xmlPopInput(ctxt);
2393:
2394: if ((temp == NULL) && (tst == CUR_PTR)) {
1.123 daniel 2395: ret = xmlStrndup((xmlChar *) "", 0);
1.94 daniel 2396: break;
2397: }
2398: if ((temp[0] == 0) && (tst == CUR_PTR)) {
1.119 daniel 2399: xmlFree((char *)temp);
1.123 daniel 2400: ret = xmlStrndup((xmlChar *) "", 0);
1.94 daniel 2401: break;
2402: }
1.79 daniel 2403: ret = xmlStrcat(ret, temp);
1.119 daniel 2404: if (temp != NULL) xmlFree((char *)temp);
1.94 daniel 2405: GROW;
1.79 daniel 2406: }
1.77 daniel 2407: if (CUR != '"') {
1.123 daniel 2408: ctxt->errNo = XML_ERR_ENTITY_NOT_FINISHED;
1.55 daniel 2409: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.79 daniel 2410: ctxt->sax->error(ctxt->userData, "EntityValue: \" expected\n");
1.59 daniel 2411: ctxt->wellFormed = 0;
1.78 daniel 2412: } else {
1.99 daniel 2413: if (orig != NULL) /* !!!!!!!!! */
1.78 daniel 2414: *orig = xmlStrndup(org, CUR_PTR - org);
1.94 daniel 2415: if (ret == NULL)
1.123 daniel 2416: ret = xmlStrndup((xmlChar *) "", 0);
1.40 daniel 2417: NEXT;
1.78 daniel 2418: }
1.40 daniel 2419: } else if (CUR == '\'') {
1.96 daniel 2420: ctxt->instate = XML_PARSER_ENTITY_VALUE;
1.98 daniel 2421: input = ctxt->input;
1.40 daniel 2422: NEXT;
1.78 daniel 2423: org = CUR_PTR;
1.98 daniel 2424: /*
2425: * NOTE: 4.4.5 Included in Literal
2426: * When a parameter entity reference appears in a literal entity
2427: * value, ... a single or double quote character in the replacement
2428: * text is always treated as a normal data character and will not
2429: * terminate the literal.
2430: * In practice it means we stop the loop only when back at parsing
2431: * the initial entity and the quote is found
2432: */
2433: while ((CUR != '\'') || (ctxt->input != input)) {
1.79 daniel 2434: tst = CUR_PTR;
1.98 daniel 2435: /*
2436: * NOTE: 4.4.7 Bypassed
2437: * When a general entity reference appears in the EntityValue in
2438: * an entity declaration, it is bypassed and left as is.
2439: * so XML_SUBSTITUTE_REF is not set.
2440: */
2441: if (ctxt->input != input)
2442: temp = xmlDecodeEntities(ctxt, -1, XML_SUBSTITUTE_PEREF,
2443: 0, 0, 0);
2444: else
2445: temp = xmlDecodeEntities(ctxt, -1, XML_SUBSTITUTE_PEREF,
2446: '\'', 0, 0);
1.94 daniel 2447:
2448: /*
2449: * Pop-up of finished entities.
2450: */
2451: while ((CUR == 0) && (ctxt->inputNr > 1))
2452: xmlPopInput(ctxt);
2453:
2454: if ((temp == NULL) && (tst == CUR_PTR)) {
1.123 daniel 2455: ret = xmlStrndup((xmlChar *) "", 0);
1.94 daniel 2456: break;
2457: }
2458: if ((temp[0] == 0) && (tst == CUR_PTR)) {
1.119 daniel 2459: xmlFree((char *)temp);
1.123 daniel 2460: ret = xmlStrndup((xmlChar *) "", 0);
1.94 daniel 2461: break;
2462: }
1.79 daniel 2463: ret = xmlStrcat(ret, temp);
1.119 daniel 2464: if (temp != NULL) xmlFree((char *)temp);
1.94 daniel 2465: GROW;
1.79 daniel 2466: }
1.77 daniel 2467: if (CUR != '\'') {
1.123 daniel 2468: ctxt->errNo = XML_ERR_ENTITY_NOT_FINISHED;
1.55 daniel 2469: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.77 daniel 2470: ctxt->sax->error(ctxt->userData, "EntityValue: ' expected\n");
1.59 daniel 2471: ctxt->wellFormed = 0;
1.78 daniel 2472: } else {
1.99 daniel 2473: if (orig != NULL) /* !!!!!!!!! */
1.78 daniel 2474: *orig = xmlStrndup(org, CUR_PTR - org);
1.94 daniel 2475: if (ret == NULL)
1.123 daniel 2476: ret = xmlStrndup((xmlChar *) "", 0);
1.40 daniel 2477: NEXT;
1.78 daniel 2478: }
1.24 daniel 2479: } else {
1.123 daniel 2480: ctxt->errNo = XML_ERR_ENTITY_NOT_STARTED;
1.55 daniel 2481: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.77 daniel 2482: ctxt->sax->error(ctxt->userData, "EntityValue: \" or ' expected\n");
1.59 daniel 2483: ctxt->wellFormed = 0;
1.24 daniel 2484: }
2485:
2486: return(ret);
2487: }
2488:
1.50 daniel 2489: /**
2490: * xmlParseAttValue:
2491: * @ctxt: an XML parser context
2492: *
2493: * parse a value for an attribute
1.78 daniel 2494: * Note: the parser won't do substitution of entities here, this
1.113 daniel 2495: * will be handled later in xmlStringGetNodeList
1.29 daniel 2496: *
2497: * [10] AttValue ::= '"' ([^<&"] | Reference)* '"' |
2498: * "'" ([^<&'] | Reference)* "'"
1.68 daniel 2499: *
1.129 daniel 2500: * 3.3.3 Attribute-Value Normalization:
2501: * Before the value of an attribute is passed to the application or
2502: * checked for validity, the XML processor must normalize it as follows:
2503: * - a character reference is processed by appending the referenced
2504: * character to the attribute value
2505: * - an entity reference is processed by recursively processing the
2506: * replacement text of the entity
2507: * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
2508: * appending #x20 to the normalized value, except that only a single
2509: * #x20 is appended for a "#xD#xA" sequence that is part of an external
2510: * parsed entity or the literal entity value of an internal parsed entity
2511: * - other characters are processed by appending them to the normalized value
1.130 daniel 2512: * If the declared value is not CDATA, then the XML processor must further
2513: * process the normalized attribute value by discarding any leading and
2514: * trailing space (#x20) characters, and by replacing sequences of space
2515: * (#x20) characters by a single space (#x20) character.
2516: * All attributes for which no declaration has been read should be treated
2517: * by a non-validating parser as if declared CDATA.
1.129 daniel 2518: *
2519: * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
1.29 daniel 2520: */
2521:
1.123 daniel 2522: xmlChar *
1.55 daniel 2523: xmlParseAttValue(xmlParserCtxtPtr ctxt) {
1.129 daniel 2524: xmlChar limit = 0;
2525: xmlChar *buffer = NULL;
2526: int buffer_size = 0;
2527: xmlChar *out = NULL;
2528:
2529: xmlChar *current = NULL;
2530: xmlEntityPtr ent;
2531: xmlChar cur;
2532:
1.29 daniel 2533:
1.91 daniel 2534: SHRINK;
1.40 daniel 2535: if (CUR == '"') {
1.96 daniel 2536: ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
1.129 daniel 2537: limit = '"';
1.40 daniel 2538: NEXT;
2539: } else if (CUR == '\'') {
1.129 daniel 2540: limit = '\'';
1.96 daniel 2541: ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
1.40 daniel 2542: NEXT;
1.29 daniel 2543: } else {
1.123 daniel 2544: ctxt->errNo = XML_ERR_ATTRIBUTE_NOT_STARTED;
1.55 daniel 2545: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 2546: ctxt->sax->error(ctxt->userData, "AttValue: \" or ' expected\n");
1.59 daniel 2547: ctxt->wellFormed = 0;
1.129 daniel 2548: return(NULL);
1.29 daniel 2549: }
2550:
1.129 daniel 2551: /*
2552: * allocate a translation buffer.
2553: */
2554: buffer_size = 100;
2555: buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
2556: if (buffer == NULL) {
2557: perror("xmlParseAttValue: malloc failed");
2558: return(NULL);
2559: }
2560: out = buffer;
2561:
2562: /*
2563: * Ok loop until we reach one of the ending char or a size limit.
2564: */
2565: cur = CUR;
2566: while ((cur != limit) && (cur != '<')) {
2567:
2568: if (cur == 0) break;
2569: if ((cur == '&') && (NXT(1) == '#')) {
2570: int val = xmlParseCharRef(ctxt);
2571: *out++ = val;
2572: } else if (cur == '&') {
2573: ent = xmlParseEntityRef(ctxt);
2574: if ((ent != NULL) &&
2575: (ctxt->replaceEntities != 0)) {
2576: current = ent->content;
2577: while (*current != 0) {
2578: *out++ = *current++;
2579: if (out - buffer > buffer_size - 10) {
2580: int index = out - buffer;
2581:
2582: growBuffer(buffer);
2583: out = &buffer[index];
2584: }
2585: }
2586: } else if (ent != NULL) {
2587: int i = xmlStrlen(ent->name);
2588: const xmlChar *cur = ent->name;
2589:
2590: *out++ = '&';
2591: if (out - buffer > buffer_size - i - 10) {
2592: int index = out - buffer;
2593:
2594: growBuffer(buffer);
2595: out = &buffer[index];
2596: }
2597: for (;i > 0;i--)
2598: *out++ = *cur++;
2599: *out++ = ';';
2600: }
2601: } else {
2602: /* invalid for UTF-8 , use COPY(out); !!!!!! */
2603: if ((cur == 0x20) || (cur == 0xD) || (cur == 0xA) || (cur == 0x9)) {
1.130 daniel 2604: *out++ = 0x20;
2605: if (out - buffer > buffer_size - 10) {
2606: int index = out - buffer;
2607:
2608: growBuffer(buffer);
2609: out = &buffer[index];
1.129 daniel 2610: }
2611: } else {
2612: *out++ = cur;
2613: if (out - buffer > buffer_size - 10) {
2614: int index = out - buffer;
2615:
2616: growBuffer(buffer);
2617: out = &buffer[index];
2618: }
2619: }
2620: NEXT;
2621: }
2622: cur = CUR;
2623: }
2624: *out++ = 0;
2625: if (CUR == '<') {
2626: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2627: ctxt->sax->error(ctxt->userData,
2628: "Unescaped '<' not allowed in attributes values\n");
2629: ctxt->errNo = XML_ERR_LT_IN_ATTRIBUTE;
2630: ctxt->wellFormed = 0;
2631: } else if (CUR != limit) {
2632: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2633: ctxt->sax->error(ctxt->userData, "AttValue: ' expected\n");
2634: ctxt->errNo = XML_ERR_ATTRIBUTE_NOT_FINISHED;
2635: ctxt->wellFormed = 0;
2636: } else
2637: NEXT;
2638: return(buffer);
1.29 daniel 2639: }
2640:
1.50 daniel 2641: /**
2642: * xmlParseSystemLiteral:
2643: * @ctxt: an XML parser context
2644: *
2645: * parse an XML Literal
1.21 daniel 2646: *
1.22 daniel 2647: * [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
1.68 daniel 2648: *
2649: * Returns the SystemLiteral parsed or NULL
1.21 daniel 2650: */
2651:
1.123 daniel 2652: xmlChar *
1.55 daniel 2653: xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
1.123 daniel 2654: const xmlChar *q;
2655: xmlChar *ret = NULL;
1.21 daniel 2656:
1.91 daniel 2657: SHRINK;
1.40 daniel 2658: if (CUR == '"') {
2659: NEXT;
2660: q = CUR_PTR;
2661: while ((IS_CHAR(CUR)) && (CUR != '"'))
2662: NEXT;
2663: if (!IS_CHAR(CUR)) {
1.55 daniel 2664: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 2665: ctxt->sax->error(ctxt->userData, "Unfinished SystemLiteral\n");
1.123 daniel 2666: ctxt->errNo = XML_ERR_LITERAL_NOT_FINISHED;
1.59 daniel 2667: ctxt->wellFormed = 0;
1.21 daniel 2668: } else {
1.40 daniel 2669: ret = xmlStrndup(q, CUR_PTR - q);
2670: NEXT;
1.21 daniel 2671: }
1.40 daniel 2672: } else if (CUR == '\'') {
2673: NEXT;
2674: q = CUR_PTR;
2675: while ((IS_CHAR(CUR)) && (CUR != '\''))
2676: NEXT;
2677: if (!IS_CHAR(CUR)) {
1.55 daniel 2678: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 2679: ctxt->sax->error(ctxt->userData, "Unfinished SystemLiteral\n");
1.123 daniel 2680: ctxt->errNo = XML_ERR_LITERAL_NOT_FINISHED;
1.59 daniel 2681: ctxt->wellFormed = 0;
1.21 daniel 2682: } else {
1.40 daniel 2683: ret = xmlStrndup(q, CUR_PTR - q);
2684: NEXT;
1.21 daniel 2685: }
2686: } else {
1.55 daniel 2687: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 2688: ctxt->sax->error(ctxt->userData,
2689: "SystemLiteral \" or ' expected\n");
1.123 daniel 2690: ctxt->errNo = XML_ERR_LITERAL_NOT_STARTED;
1.59 daniel 2691: ctxt->wellFormed = 0;
1.21 daniel 2692: }
2693:
2694: return(ret);
2695: }
2696:
1.50 daniel 2697: /**
2698: * xmlParsePubidLiteral:
2699: * @ctxt: an XML parser context
1.21 daniel 2700: *
1.50 daniel 2701: * parse an XML public literal
1.68 daniel 2702: *
2703: * [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
2704: *
2705: * Returns the PubidLiteral parsed or NULL.
1.21 daniel 2706: */
2707:
1.123 daniel 2708: xmlChar *
1.55 daniel 2709: xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) {
1.123 daniel 2710: const xmlChar *q;
2711: xmlChar *ret = NULL;
1.125 daniel 2712:
1.91 daniel 2713: SHRINK;
1.40 daniel 2714: if (CUR == '"') {
2715: NEXT;
2716: q = CUR_PTR;
2717: while (IS_PUBIDCHAR(CUR)) NEXT;
2718: if (CUR != '"') {
1.55 daniel 2719: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 2720: ctxt->sax->error(ctxt->userData, "Unfinished PubidLiteral\n");
1.123 daniel 2721: ctxt->errNo = XML_ERR_LITERAL_NOT_FINISHED;
1.59 daniel 2722: ctxt->wellFormed = 0;
1.21 daniel 2723: } else {
1.40 daniel 2724: ret = xmlStrndup(q, CUR_PTR - q);
2725: NEXT;
1.21 daniel 2726: }
1.40 daniel 2727: } else if (CUR == '\'') {
2728: NEXT;
2729: q = CUR_PTR;
1.125 daniel 2730: while (IS_PUBIDCHAR(CUR)) NEXT;
2731: if (CUR != '\'') {
2732: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 2733: ctxt->sax->error(ctxt->userData, "Unfinished PubidLiteral\n");
1.123 daniel 2734: ctxt->errNo = XML_ERR_LITERAL_NOT_FINISHED;
1.59 daniel 2735: ctxt->wellFormed = 0;
1.21 daniel 2736: } else {
1.40 daniel 2737: ret = xmlStrndup(q, CUR_PTR - q);
2738: NEXT;
1.21 daniel 2739: }
2740: } else {
1.55 daniel 2741: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 2742: ctxt->sax->error(ctxt->userData,
2743: "SystemLiteral \" or ' expected\n");
1.123 daniel 2744: ctxt->errNo = XML_ERR_LITERAL_NOT_STARTED;
1.59 daniel 2745: ctxt->wellFormed = 0;
1.21 daniel 2746: }
2747:
2748: return(ret);
2749: }
2750:
1.50 daniel 2751: /**
2752: * xmlParseCharData:
2753: * @ctxt: an XML parser context
2754: * @cdata: int indicating whether we are within a CDATA section
2755: *
2756: * parse a CharData section.
2757: * if we are within a CDATA section ']]>' marks an end of section.
1.27 daniel 2758: *
2759: * [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
2760: */
2761:
1.55 daniel 2762: void
2763: xmlParseCharData(xmlParserCtxtPtr ctxt, int cdata) {
1.123 daniel 2764: xmlChar buf[1000];
1.91 daniel 2765: int nbchar = 0;
1.123 daniel 2766: xmlChar cur;
1.27 daniel 2767:
1.91 daniel 2768: SHRINK;
1.97 daniel 2769: /*
2770: * !!!!!!!!!!!!
2771: * NOTE: NXT(0) is used here to avoid breaking on < or &
2772: * entities substitutions.
2773: */
2774: cur = CUR;
2775: while ((IS_CHAR(cur)) && (cur != '<') &&
2776: (cur != '&')) {
2777: if ((cur == ']') && (NXT(1) == ']') &&
1.59 daniel 2778: (NXT(2) == '>')) {
2779: if (cdata) break;
2780: else {
2781: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 2782: ctxt->sax->error(ctxt->userData,
1.59 daniel 2783: "Sequence ']]>' not allowed in content\n");
1.123 daniel 2784: ctxt->errNo = XML_ERR_MISPLACED_CDATA_END;
1.59 daniel 2785: ctxt->wellFormed = 0;
2786: }
2787: }
1.91 daniel 2788: buf[nbchar++] = CUR;
2789: if (nbchar == 1000) {
2790: /*
2791: * Ok the segment is to be consumed as chars.
2792: */
2793: if (ctxt->sax != NULL) {
2794: if (areBlanks(ctxt, buf, nbchar)) {
2795: if (ctxt->sax->ignorableWhitespace != NULL)
2796: ctxt->sax->ignorableWhitespace(ctxt->userData,
2797: buf, nbchar);
2798: } else {
2799: if (ctxt->sax->characters != NULL)
2800: ctxt->sax->characters(ctxt->userData, buf, nbchar);
2801: }
2802: }
2803: nbchar = 0;
2804: }
1.40 daniel 2805: NEXT;
1.97 daniel 2806: cur = CUR;
1.27 daniel 2807: }
1.91 daniel 2808: if (nbchar != 0) {
2809: /*
2810: * Ok the segment is to be consumed as chars.
2811: */
2812: if (ctxt->sax != NULL) {
2813: if (areBlanks(ctxt, buf, nbchar)) {
2814: if (ctxt->sax->ignorableWhitespace != NULL)
2815: ctxt->sax->ignorableWhitespace(ctxt->userData, buf, nbchar);
2816: } else {
2817: if (ctxt->sax->characters != NULL)
2818: ctxt->sax->characters(ctxt->userData, buf, nbchar);
2819: }
2820: }
1.45 daniel 2821: }
1.27 daniel 2822: }
2823:
1.50 daniel 2824: /**
2825: * xmlParseExternalID:
2826: * @ctxt: an XML parser context
1.123 daniel 2827: * @publicID: a xmlChar** receiving PubidLiteral
1.67 daniel 2828: * @strict: indicate whether we should restrict parsing to only
2829: * production [75], see NOTE below
1.50 daniel 2830: *
1.67 daniel 2831: * Parse an External ID or a Public ID
2832: *
2833: * NOTE: Productions [75] and [83] interract badly since [75] can generate
2834: * 'PUBLIC' S PubidLiteral S SystemLiteral
1.22 daniel 2835: *
2836: * [75] ExternalID ::= 'SYSTEM' S SystemLiteral
2837: * | 'PUBLIC' S PubidLiteral S SystemLiteral
1.67 daniel 2838: *
2839: * [83] PublicID ::= 'PUBLIC' S PubidLiteral
2840: *
1.68 daniel 2841: * Returns the function returns SystemLiteral and in the second
1.67 daniel 2842: * case publicID receives PubidLiteral, is strict is off
2843: * it is possible to return NULL and have publicID set.
1.22 daniel 2844: */
2845:
1.123 daniel 2846: xmlChar *
2847: xmlParseExternalID(xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict) {
2848: xmlChar *URI = NULL;
1.22 daniel 2849:
1.91 daniel 2850: SHRINK;
1.40 daniel 2851: if ((CUR == 'S') && (NXT(1) == 'Y') &&
2852: (NXT(2) == 'S') && (NXT(3) == 'T') &&
2853: (NXT(4) == 'E') && (NXT(5) == 'M')) {
2854: SKIP(6);
1.59 daniel 2855: if (!IS_BLANK(CUR)) {
2856: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 2857: ctxt->sax->error(ctxt->userData,
1.59 daniel 2858: "Space required after 'SYSTEM'\n");
1.123 daniel 2859: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 2860: ctxt->wellFormed = 0;
2861: }
1.42 daniel 2862: SKIP_BLANKS;
1.39 daniel 2863: URI = xmlParseSystemLiteral(ctxt);
1.59 daniel 2864: if (URI == NULL) {
1.55 daniel 2865: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 2866: ctxt->sax->error(ctxt->userData,
1.39 daniel 2867: "xmlParseExternalID: SYSTEM, no URI\n");
1.123 daniel 2868: ctxt->errNo = XML_ERR_URI_REQUIRED;
1.59 daniel 2869: ctxt->wellFormed = 0;
2870: }
1.40 daniel 2871: } else if ((CUR == 'P') && (NXT(1) == 'U') &&
2872: (NXT(2) == 'B') && (NXT(3) == 'L') &&
2873: (NXT(4) == 'I') && (NXT(5) == 'C')) {
2874: SKIP(6);
1.59 daniel 2875: if (!IS_BLANK(CUR)) {
2876: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 2877: ctxt->sax->error(ctxt->userData,
1.59 daniel 2878: "Space required after 'PUBLIC'\n");
1.123 daniel 2879: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 2880: ctxt->wellFormed = 0;
2881: }
1.42 daniel 2882: SKIP_BLANKS;
1.39 daniel 2883: *publicID = xmlParsePubidLiteral(ctxt);
1.59 daniel 2884: if (*publicID == NULL) {
1.55 daniel 2885: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 2886: ctxt->sax->error(ctxt->userData,
1.39 daniel 2887: "xmlParseExternalID: PUBLIC, no Public Identifier\n");
1.123 daniel 2888: ctxt->errNo = XML_ERR_PUBID_REQUIRED;
1.59 daniel 2889: ctxt->wellFormed = 0;
2890: }
1.67 daniel 2891: if (strict) {
2892: /*
2893: * We don't handle [83] so "S SystemLiteral" is required.
2894: */
2895: if (!IS_BLANK(CUR)) {
2896: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 2897: ctxt->sax->error(ctxt->userData,
1.67 daniel 2898: "Space required after the Public Identifier\n");
1.123 daniel 2899: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.67 daniel 2900: ctxt->wellFormed = 0;
2901: }
2902: } else {
2903: /*
2904: * We handle [83] so we return immediately, if
2905: * "S SystemLiteral" is not detected. From a purely parsing
2906: * point of view that's a nice mess.
2907: */
1.123 daniel 2908: const xmlChar *ptr = CUR_PTR;
1.67 daniel 2909: if (!IS_BLANK(*ptr)) return(NULL);
2910:
2911: while (IS_BLANK(*ptr)) ptr++;
2912: if ((*ptr != '\'') || (*ptr != '"')) return(NULL);
1.59 daniel 2913: }
1.42 daniel 2914: SKIP_BLANKS;
1.39 daniel 2915: URI = xmlParseSystemLiteral(ctxt);
1.59 daniel 2916: if (URI == NULL) {
1.55 daniel 2917: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 2918: ctxt->sax->error(ctxt->userData,
1.39 daniel 2919: "xmlParseExternalID: PUBLIC, no URI\n");
1.123 daniel 2920: ctxt->errNo = XML_ERR_URI_REQUIRED;
1.59 daniel 2921: ctxt->wellFormed = 0;
2922: }
1.22 daniel 2923: }
1.39 daniel 2924: return(URI);
1.22 daniel 2925: }
2926:
1.50 daniel 2927: /**
2928: * xmlParseComment:
1.69 daniel 2929: * @ctxt: an XML parser context
1.50 daniel 2930: *
1.3 veillard 2931: * Skip an XML (SGML) comment <!-- .... -->
1.38 daniel 2932: * The spec says that "For compatibility, the string "--" (double-hyphen)
2933: * must not occur within comments. "
1.22 daniel 2934: *
2935: * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
1.3 veillard 2936: */
1.72 daniel 2937: void
1.114 daniel 2938: xmlParseComment(xmlParserCtxtPtr ctxt) {
1.123 daniel 2939: const xmlChar *q, *start;
2940: const xmlChar *r;
2941: xmlChar *val;
1.3 veillard 2942:
2943: /*
1.22 daniel 2944: * Check that there is a comment right here.
1.3 veillard 2945: */
1.40 daniel 2946: if ((CUR != '<') || (NXT(1) != '!') ||
1.72 daniel 2947: (NXT(2) != '-') || (NXT(3) != '-')) return;
1.3 veillard 2948:
1.97 daniel 2949: ctxt->instate = XML_PARSER_COMMENT;
1.91 daniel 2950: SHRINK;
1.40 daniel 2951: SKIP(4);
2952: start = q = CUR_PTR;
2953: NEXT;
2954: r = CUR_PTR;
2955: NEXT;
2956: while (IS_CHAR(CUR) &&
2957: ((CUR == ':') || (CUR != '>') ||
1.16 daniel 2958: (*r != '-') || (*q != '-'))) {
1.59 daniel 2959: if ((*r == '-') && (*q == '-')) {
1.55 daniel 2960: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 2961: ctxt->sax->error(ctxt->userData,
1.38 daniel 2962: "Comment must not contain '--' (double-hyphen)`\n");
1.123 daniel 2963: ctxt->errNo = XML_ERR_HYPHEN_IN_COMMENT;
1.59 daniel 2964: ctxt->wellFormed = 0;
2965: }
1.40 daniel 2966: NEXT;r++;q++;
1.3 veillard 2967: }
1.40 daniel 2968: if (!IS_CHAR(CUR)) {
1.55 daniel 2969: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 2970: ctxt->sax->error(ctxt->userData,
2971: "Comment not terminated \n<!--%.50s\n", start);
1.123 daniel 2972: ctxt->errNo = XML_ERR_COMMENT_NOT_FINISHED;
1.59 daniel 2973: ctxt->wellFormed = 0;
1.3 veillard 2974: } else {
1.40 daniel 2975: NEXT;
1.114 daniel 2976: val = xmlStrndup(start, q - start);
2977: if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL))
2978: ctxt->sax->comment(ctxt->userData, val);
1.119 daniel 2979: xmlFree(val);
1.3 veillard 2980: }
2981: }
2982:
1.50 daniel 2983: /**
2984: * xmlParsePITarget:
2985: * @ctxt: an XML parser context
2986: *
2987: * parse the name of a PI
1.22 daniel 2988: *
2989: * [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
1.68 daniel 2990: *
2991: * Returns the PITarget name or NULL
1.22 daniel 2992: */
2993:
1.123 daniel 2994: xmlChar *
1.55 daniel 2995: xmlParsePITarget(xmlParserCtxtPtr ctxt) {
1.123 daniel 2996: xmlChar *name;
1.22 daniel 2997:
2998: name = xmlParseName(ctxt);
2999: if ((name != NULL) && (name[3] == 0) &&
3000: ((name[0] == 'x') || (name[0] == 'X')) &&
1.31 daniel 3001: ((name[1] == 'm') || (name[1] == 'M')) &&
3002: ((name[2] == 'l') || (name[2] == 'L'))) {
1.122 daniel 3003: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) {
3004: ctxt->sax->error(ctxt->userData,
3005: "xmlParsePItarget: invalid name prefix 'xml'\n");
1.123 daniel 3006: ctxt->errNo = XML_ERR_RESERVED_XML_NAME;
1.122 daniel 3007: /* ctxt->wellFormed = 0; !!! ? */
3008: }
1.22 daniel 3009: return(NULL);
3010: }
3011: return(name);
3012: }
3013:
1.50 daniel 3014: /**
3015: * xmlParsePI:
3016: * @ctxt: an XML parser context
3017: *
3018: * parse an XML Processing Instruction.
1.22 daniel 3019: *
3020: * [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
1.68 daniel 3021: *
1.69 daniel 3022: * The processing is transfered to SAX once parsed.
1.3 veillard 3023: */
3024:
1.55 daniel 3025: void
3026: xmlParsePI(xmlParserCtxtPtr ctxt) {
1.123 daniel 3027: xmlChar *target;
1.22 daniel 3028:
1.40 daniel 3029: if ((CUR == '<') && (NXT(1) == '?')) {
1.3 veillard 3030: /*
3031: * this is a Processing Instruction.
3032: */
1.40 daniel 3033: SKIP(2);
1.91 daniel 3034: SHRINK;
1.3 veillard 3035:
3036: /*
1.22 daniel 3037: * Parse the target name and check for special support like
3038: * namespace.
1.3 veillard 3039: */
1.22 daniel 3040: target = xmlParsePITarget(ctxt);
3041: if (target != NULL) {
1.123 daniel 3042: const xmlChar *q;
1.72 daniel 3043:
1.114 daniel 3044: if (!IS_BLANK(CUR)) {
3045: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
3046: ctxt->sax->error(ctxt->userData,
3047: "xmlParsePI: PI %s space expected\n", target);
1.123 daniel 3048: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.114 daniel 3049: ctxt->wellFormed = 0;
3050: }
3051: SKIP_BLANKS;
3052: q = CUR_PTR;
1.72 daniel 3053: while (IS_CHAR(CUR) &&
3054: ((CUR != '?') || (NXT(1) != '>')))
3055: NEXT;
3056: if (!IS_CHAR(CUR)) {
3057: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3058: ctxt->sax->error(ctxt->userData,
1.72 daniel 3059: "xmlParsePI: PI %s never end ...\n", target);
1.123 daniel 3060: ctxt->errNo = XML_ERR_PI_NOT_FINISHED;
1.72 daniel 3061: ctxt->wellFormed = 0;
1.22 daniel 3062: } else {
1.123 daniel 3063: xmlChar *data;
1.44 daniel 3064:
1.72 daniel 3065: data = xmlStrndup(q, CUR_PTR - q);
3066: SKIP(2);
1.44 daniel 3067:
1.72 daniel 3068: /*
3069: * SAX: PI detected.
3070: */
3071: if ((ctxt->sax) &&
3072: (ctxt->sax->processingInstruction != NULL))
1.99 daniel 3073: ctxt->sax->processingInstruction(ctxt->userData,
3074: target, data);
1.119 daniel 3075: xmlFree(data);
1.22 daniel 3076: }
1.119 daniel 3077: xmlFree(target);
1.3 veillard 3078: } else {
1.55 daniel 3079: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.99 daniel 3080: ctxt->sax->error(ctxt->userData,
3081: "xmlParsePI : no target name\n");
1.123 daniel 3082: ctxt->errNo = XML_ERR_PI_NOT_STARTED;
1.59 daniel 3083: ctxt->wellFormed = 0;
1.22 daniel 3084: }
3085: }
3086: }
3087:
1.50 daniel 3088: /**
3089: * xmlParseNotationDecl:
3090: * @ctxt: an XML parser context
3091: *
3092: * parse a notation declaration
1.22 daniel 3093: *
3094: * [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID | PublicID) S? '>'
3095: *
3096: * Hence there is actually 3 choices:
3097: * 'PUBLIC' S PubidLiteral
3098: * 'PUBLIC' S PubidLiteral S SystemLiteral
3099: * and 'SYSTEM' S SystemLiteral
1.50 daniel 3100: *
1.67 daniel 3101: * See the NOTE on xmlParseExternalID().
1.22 daniel 3102: */
3103:
1.55 daniel 3104: void
3105: xmlParseNotationDecl(xmlParserCtxtPtr ctxt) {
1.123 daniel 3106: xmlChar *name;
3107: xmlChar *Pubid;
3108: xmlChar *Systemid;
1.22 daniel 3109:
1.40 daniel 3110: if ((CUR == '<') && (NXT(1) == '!') &&
3111: (NXT(2) == 'N') && (NXT(3) == 'O') &&
3112: (NXT(4) == 'T') && (NXT(5) == 'A') &&
3113: (NXT(6) == 'T') && (NXT(7) == 'I') &&
1.67 daniel 3114: (NXT(8) == 'O') && (NXT(9) == 'N')) {
1.91 daniel 3115: SHRINK;
1.40 daniel 3116: SKIP(10);
1.67 daniel 3117: if (!IS_BLANK(CUR)) {
3118: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 3119: ctxt->sax->error(ctxt->userData,
3120: "Space required after '<!NOTATION'\n");
1.123 daniel 3121: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.67 daniel 3122: ctxt->wellFormed = 0;
3123: return;
3124: }
3125: SKIP_BLANKS;
1.22 daniel 3126:
3127: name = xmlParseName(ctxt);
3128: if (name == NULL) {
1.55 daniel 3129: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 3130: ctxt->sax->error(ctxt->userData,
3131: "NOTATION: Name expected here\n");
1.123 daniel 3132: ctxt->errNo = XML_ERR_NOTATION_NOT_STARTED;
1.67 daniel 3133: ctxt->wellFormed = 0;
3134: return;
3135: }
3136: if (!IS_BLANK(CUR)) {
3137: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3138: ctxt->sax->error(ctxt->userData,
1.67 daniel 3139: "Space required after the NOTATION name'\n");
1.123 daniel 3140: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 3141: ctxt->wellFormed = 0;
1.22 daniel 3142: return;
3143: }
1.42 daniel 3144: SKIP_BLANKS;
1.67 daniel 3145:
1.22 daniel 3146: /*
1.67 daniel 3147: * Parse the IDs.
1.22 daniel 3148: */
1.67 daniel 3149: Systemid = xmlParseExternalID(ctxt, &Pubid, 1);
3150: SKIP_BLANKS;
3151:
3152: if (CUR == '>') {
1.40 daniel 3153: NEXT;
1.72 daniel 3154: if ((ctxt->sax != NULL) && (ctxt->sax->notationDecl != NULL))
1.74 daniel 3155: ctxt->sax->notationDecl(ctxt->userData, name, Pubid, Systemid);
1.67 daniel 3156: } else {
3157: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3158: ctxt->sax->error(ctxt->userData,
1.67 daniel 3159: "'>' required to close NOTATION declaration\n");
1.123 daniel 3160: ctxt->errNo = XML_ERR_NOTATION_NOT_FINISHED;
1.67 daniel 3161: ctxt->wellFormed = 0;
3162: }
1.119 daniel 3163: xmlFree(name);
3164: if (Systemid != NULL) xmlFree(Systemid);
3165: if (Pubid != NULL) xmlFree(Pubid);
1.22 daniel 3166: }
3167: }
3168:
1.50 daniel 3169: /**
3170: * xmlParseEntityDecl:
3171: * @ctxt: an XML parser context
3172: *
3173: * parse <!ENTITY declarations
1.22 daniel 3174: *
3175: * [70] EntityDecl ::= GEDecl | PEDecl
3176: *
3177: * [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
3178: *
3179: * [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
3180: *
3181: * [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
3182: *
3183: * [74] PEDef ::= EntityValue | ExternalID
1.24 daniel 3184: *
3185: * [76] NDataDecl ::= S 'NDATA' S Name
1.99 daniel 3186: *
3187: * [ VC: Notation Declared ]
1.116 daniel 3188: * The Name must match the declared name of a notation.
1.22 daniel 3189: */
3190:
1.55 daniel 3191: void
3192: xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
1.123 daniel 3193: xmlChar *name = NULL;
3194: xmlChar *value = NULL;
3195: xmlChar *URI = NULL, *literal = NULL;
3196: xmlChar *ndata = NULL;
1.39 daniel 3197: int isParameter = 0;
1.123 daniel 3198: xmlChar *orig = NULL;
1.22 daniel 3199:
1.94 daniel 3200: GROW;
1.40 daniel 3201: if ((CUR == '<') && (NXT(1) == '!') &&
3202: (NXT(2) == 'E') && (NXT(3) == 'N') &&
3203: (NXT(4) == 'T') && (NXT(5) == 'I') &&
1.59 daniel 3204: (NXT(6) == 'T') && (NXT(7) == 'Y')) {
1.96 daniel 3205: ctxt->instate = XML_PARSER_ENTITY_DECL;
1.91 daniel 3206: SHRINK;
1.40 daniel 3207: SKIP(8);
1.59 daniel 3208: if (!IS_BLANK(CUR)) {
3209: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 3210: ctxt->sax->error(ctxt->userData,
3211: "Space required after '<!ENTITY'\n");
1.123 daniel 3212: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 3213: ctxt->wellFormed = 0;
3214: }
3215: SKIP_BLANKS;
1.40 daniel 3216:
3217: if (CUR == '%') {
3218: NEXT;
1.59 daniel 3219: if (!IS_BLANK(CUR)) {
3220: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 3221: ctxt->sax->error(ctxt->userData,
3222: "Space required after '%'\n");
1.123 daniel 3223: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 3224: ctxt->wellFormed = 0;
3225: }
1.42 daniel 3226: SKIP_BLANKS;
1.39 daniel 3227: isParameter = 1;
1.22 daniel 3228: }
3229:
3230: name = xmlParseName(ctxt);
1.24 daniel 3231: if (name == NULL) {
1.55 daniel 3232: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3233: ctxt->sax->error(ctxt->userData, "xmlParseEntityDecl: no name\n");
1.123 daniel 3234: ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.59 daniel 3235: ctxt->wellFormed = 0;
1.24 daniel 3236: return;
3237: }
1.59 daniel 3238: if (!IS_BLANK(CUR)) {
3239: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3240: ctxt->sax->error(ctxt->userData,
1.59 daniel 3241: "Space required after the entity name\n");
1.123 daniel 3242: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 3243: ctxt->wellFormed = 0;
3244: }
1.42 daniel 3245: SKIP_BLANKS;
1.24 daniel 3246:
1.22 daniel 3247: /*
1.68 daniel 3248: * handle the various case of definitions...
1.22 daniel 3249: */
1.39 daniel 3250: if (isParameter) {
1.40 daniel 3251: if ((CUR == '"') || (CUR == '\''))
1.78 daniel 3252: value = xmlParseEntityValue(ctxt, &orig);
1.39 daniel 3253: if (value) {
1.72 daniel 3254: if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
1.74 daniel 3255: ctxt->sax->entityDecl(ctxt->userData, name,
1.39 daniel 3256: XML_INTERNAL_PARAMETER_ENTITY,
3257: NULL, NULL, value);
3258: }
1.24 daniel 3259: else {
1.67 daniel 3260: URI = xmlParseExternalID(ctxt, &literal, 1);
1.39 daniel 3261: if (URI) {
1.72 daniel 3262: if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
1.74 daniel 3263: ctxt->sax->entityDecl(ctxt->userData, name,
1.39 daniel 3264: XML_EXTERNAL_PARAMETER_ENTITY,
3265: literal, URI, NULL);
3266: }
1.24 daniel 3267: }
3268: } else {
1.40 daniel 3269: if ((CUR == '"') || (CUR == '\'')) {
1.78 daniel 3270: value = xmlParseEntityValue(ctxt, &orig);
1.72 daniel 3271: if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
1.74 daniel 3272: ctxt->sax->entityDecl(ctxt->userData, name,
1.39 daniel 3273: XML_INTERNAL_GENERAL_ENTITY,
3274: NULL, NULL, value);
3275: } else {
1.67 daniel 3276: URI = xmlParseExternalID(ctxt, &literal, 1);
1.59 daniel 3277: if ((CUR != '>') && (!IS_BLANK(CUR))) {
3278: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3279: ctxt->sax->error(ctxt->userData,
1.59 daniel 3280: "Space required before 'NDATA'\n");
1.123 daniel 3281: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 3282: ctxt->wellFormed = 0;
3283: }
1.42 daniel 3284: SKIP_BLANKS;
1.40 daniel 3285: if ((CUR == 'N') && (NXT(1) == 'D') &&
3286: (NXT(2) == 'A') && (NXT(3) == 'T') &&
3287: (NXT(4) == 'A')) {
3288: SKIP(5);
1.59 daniel 3289: if (!IS_BLANK(CUR)) {
3290: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3291: ctxt->sax->error(ctxt->userData,
1.59 daniel 3292: "Space required after 'NDATA'\n");
1.123 daniel 3293: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 3294: ctxt->wellFormed = 0;
3295: }
1.42 daniel 3296: SKIP_BLANKS;
1.24 daniel 3297: ndata = xmlParseName(ctxt);
1.116 daniel 3298: if ((ctxt->sax != NULL) &&
3299: (ctxt->sax->unparsedEntityDecl != NULL))
3300: ctxt->sax->unparsedEntityDecl(ctxt->userData, name,
1.39 daniel 3301: literal, URI, ndata);
3302: } else {
1.72 daniel 3303: if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
1.74 daniel 3304: ctxt->sax->entityDecl(ctxt->userData, name,
1.39 daniel 3305: XML_EXTERNAL_GENERAL_PARSED_ENTITY,
3306: literal, URI, NULL);
1.24 daniel 3307: }
3308: }
3309: }
1.42 daniel 3310: SKIP_BLANKS;
1.40 daniel 3311: if (CUR != '>') {
1.55 daniel 3312: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3313: ctxt->sax->error(ctxt->userData,
1.31 daniel 3314: "xmlParseEntityDecl: entity %s not terminated\n", name);
1.123 daniel 3315: ctxt->errNo = XML_ERR_ENTITY_NOT_FINISHED;
1.59 daniel 3316: ctxt->wellFormed = 0;
1.24 daniel 3317: } else
1.40 daniel 3318: NEXT;
1.78 daniel 3319: if (orig != NULL) {
3320: /*
1.98 daniel 3321: * Ugly mechanism to save the raw entity value.
1.78 daniel 3322: */
3323: xmlEntityPtr cur = NULL;
3324:
1.98 daniel 3325: if (isParameter) {
3326: if ((ctxt->sax != NULL) &&
3327: (ctxt->sax->getParameterEntity != NULL))
1.120 daniel 3328: cur = ctxt->sax->getParameterEntity(ctxt->userData, name);
1.98 daniel 3329: } else {
3330: if ((ctxt->sax != NULL) &&
3331: (ctxt->sax->getEntity != NULL))
1.120 daniel 3332: cur = ctxt->sax->getEntity(ctxt->userData, name);
1.98 daniel 3333: }
3334: if (cur != NULL) {
3335: if (cur->orig != NULL)
1.119 daniel 3336: xmlFree(orig);
1.98 daniel 3337: else
3338: cur->orig = orig;
3339: } else
1.119 daniel 3340: xmlFree(orig);
1.78 daniel 3341: }
1.119 daniel 3342: if (name != NULL) xmlFree(name);
3343: if (value != NULL) xmlFree(value);
3344: if (URI != NULL) xmlFree(URI);
3345: if (literal != NULL) xmlFree(literal);
3346: if (ndata != NULL) xmlFree(ndata);
1.22 daniel 3347: }
3348: }
3349:
1.50 daniel 3350: /**
1.59 daniel 3351: * xmlParseDefaultDecl:
3352: * @ctxt: an XML parser context
3353: * @value: Receive a possible fixed default value for the attribute
3354: *
3355: * Parse an attribute default declaration
3356: *
3357: * [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
3358: *
1.99 daniel 3359: * [ VC: Required Attribute ]
1.117 daniel 3360: * if the default declaration is the keyword #REQUIRED, then the
3361: * attribute must be specified for all elements of the type in the
3362: * attribute-list declaration.
1.99 daniel 3363: *
3364: * [ VC: Attribute Default Legal ]
1.102 daniel 3365: * The declared default value must meet the lexical constraints of
3366: * the declared attribute type c.f. xmlValidateAttributeDecl()
1.99 daniel 3367: *
3368: * [ VC: Fixed Attribute Default ]
1.117 daniel 3369: * if an attribute has a default value declared with the #FIXED
3370: * keyword, instances of that attribute must match the default value.
1.99 daniel 3371: *
3372: * [ WFC: No < in Attribute Values ]
3373: * handled in xmlParseAttValue()
3374: *
1.59 daniel 3375: * returns: XML_ATTRIBUTE_NONE, XML_ATTRIBUTE_REQUIRED, XML_ATTRIBUTE_IMPLIED
3376: * or XML_ATTRIBUTE_FIXED.
3377: */
3378:
3379: int
1.123 daniel 3380: xmlParseDefaultDecl(xmlParserCtxtPtr ctxt, xmlChar **value) {
1.59 daniel 3381: int val;
1.123 daniel 3382: xmlChar *ret;
1.59 daniel 3383:
3384: *value = NULL;
3385: if ((CUR == '#') && (NXT(1) == 'R') &&
3386: (NXT(2) == 'E') && (NXT(3) == 'Q') &&
3387: (NXT(4) == 'U') && (NXT(5) == 'I') &&
3388: (NXT(6) == 'R') && (NXT(7) == 'E') &&
3389: (NXT(8) == 'D')) {
3390: SKIP(9);
3391: return(XML_ATTRIBUTE_REQUIRED);
3392: }
3393: if ((CUR == '#') && (NXT(1) == 'I') &&
3394: (NXT(2) == 'M') && (NXT(3) == 'P') &&
3395: (NXT(4) == 'L') && (NXT(5) == 'I') &&
3396: (NXT(6) == 'E') && (NXT(7) == 'D')) {
3397: SKIP(8);
3398: return(XML_ATTRIBUTE_IMPLIED);
3399: }
3400: val = XML_ATTRIBUTE_NONE;
3401: if ((CUR == '#') && (NXT(1) == 'F') &&
3402: (NXT(2) == 'I') && (NXT(3) == 'X') &&
3403: (NXT(4) == 'E') && (NXT(5) == 'D')) {
3404: SKIP(6);
3405: val = XML_ATTRIBUTE_FIXED;
3406: if (!IS_BLANK(CUR)) {
3407: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 3408: ctxt->sax->error(ctxt->userData,
3409: "Space required after '#FIXED'\n");
1.123 daniel 3410: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 3411: ctxt->wellFormed = 0;
3412: }
3413: SKIP_BLANKS;
3414: }
3415: ret = xmlParseAttValue(ctxt);
1.96 daniel 3416: ctxt->instate = XML_PARSER_DTD;
1.59 daniel 3417: if (ret == NULL) {
3418: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3419: ctxt->sax->error(ctxt->userData,
1.59 daniel 3420: "Attribute default value declaration error\n");
3421: ctxt->wellFormed = 0;
3422: } else
3423: *value = ret;
3424: return(val);
3425: }
3426:
3427: /**
1.66 daniel 3428: * xmlParseNotationType:
3429: * @ctxt: an XML parser context
3430: *
3431: * parse an Notation attribute type.
3432: *
1.99 daniel 3433: * Note: the leading 'NOTATION' S part has already being parsed...
3434: *
1.66 daniel 3435: * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
3436: *
1.99 daniel 3437: * [ VC: Notation Attributes ]
1.117 daniel 3438: * Values of this type must match one of the notation names included
1.99 daniel 3439: * in the declaration; all notation names in the declaration must be declared.
1.66 daniel 3440: *
3441: * Returns: the notation attribute tree built while parsing
3442: */
3443:
3444: xmlEnumerationPtr
3445: xmlParseNotationType(xmlParserCtxtPtr ctxt) {
1.123 daniel 3446: xmlChar *name;
1.66 daniel 3447: xmlEnumerationPtr ret = NULL, last = NULL, cur;
3448:
3449: if (CUR != '(') {
3450: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 3451: ctxt->sax->error(ctxt->userData,
3452: "'(' required to start 'NOTATION'\n");
1.123 daniel 3453: ctxt->errNo = XML_ERR_NOTATION_NOT_STARTED;
1.66 daniel 3454: ctxt->wellFormed = 0;
3455: return(NULL);
3456: }
1.91 daniel 3457: SHRINK;
1.66 daniel 3458: do {
3459: NEXT;
3460: SKIP_BLANKS;
3461: name = xmlParseName(ctxt);
3462: if (name == NULL) {
3463: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3464: ctxt->sax->error(ctxt->userData,
1.66 daniel 3465: "Name expected in NOTATION declaration\n");
1.123 daniel 3466: ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.66 daniel 3467: ctxt->wellFormed = 0;
3468: return(ret);
3469: }
3470: cur = xmlCreateEnumeration(name);
1.119 daniel 3471: xmlFree(name);
1.66 daniel 3472: if (cur == NULL) return(ret);
3473: if (last == NULL) ret = last = cur;
3474: else {
3475: last->next = cur;
3476: last = cur;
3477: }
3478: SKIP_BLANKS;
3479: } while (CUR == '|');
3480: if (CUR != ')') {
3481: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3482: ctxt->sax->error(ctxt->userData,
1.66 daniel 3483: "')' required to finish NOTATION declaration\n");
1.123 daniel 3484: ctxt->errNo = XML_ERR_NOTATION_NOT_FINISHED;
1.66 daniel 3485: ctxt->wellFormed = 0;
3486: return(ret);
3487: }
3488: NEXT;
3489: return(ret);
3490: }
3491:
3492: /**
3493: * xmlParseEnumerationType:
3494: * @ctxt: an XML parser context
3495: *
3496: * parse an Enumeration attribute type.
3497: *
3498: * [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
3499: *
1.99 daniel 3500: * [ VC: Enumeration ]
1.117 daniel 3501: * Values of this type must match one of the Nmtoken tokens in
1.99 daniel 3502: * the declaration
3503: *
1.66 daniel 3504: * Returns: the enumeration attribute tree built while parsing
3505: */
3506:
3507: xmlEnumerationPtr
3508: xmlParseEnumerationType(xmlParserCtxtPtr ctxt) {
1.123 daniel 3509: xmlChar *name;
1.66 daniel 3510: xmlEnumerationPtr ret = NULL, last = NULL, cur;
3511:
3512: if (CUR != '(') {
3513: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3514: ctxt->sax->error(ctxt->userData,
1.66 daniel 3515: "'(' required to start ATTLIST enumeration\n");
1.123 daniel 3516: ctxt->errNo = XML_ERR_ATTLIST_NOT_STARTED;
1.66 daniel 3517: ctxt->wellFormed = 0;
3518: return(NULL);
3519: }
1.91 daniel 3520: SHRINK;
1.66 daniel 3521: do {
3522: NEXT;
3523: SKIP_BLANKS;
3524: name = xmlParseNmtoken(ctxt);
3525: if (name == NULL) {
3526: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3527: ctxt->sax->error(ctxt->userData,
1.66 daniel 3528: "NmToken expected in ATTLIST enumeration\n");
1.123 daniel 3529: ctxt->errNo = XML_ERR_NMTOKEN_REQUIRED;
1.66 daniel 3530: ctxt->wellFormed = 0;
3531: return(ret);
3532: }
3533: cur = xmlCreateEnumeration(name);
1.119 daniel 3534: xmlFree(name);
1.66 daniel 3535: if (cur == NULL) return(ret);
3536: if (last == NULL) ret = last = cur;
3537: else {
3538: last->next = cur;
3539: last = cur;
3540: }
3541: SKIP_BLANKS;
3542: } while (CUR == '|');
3543: if (CUR != ')') {
3544: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3545: ctxt->sax->error(ctxt->userData,
1.66 daniel 3546: "')' required to finish ATTLIST enumeration\n");
1.123 daniel 3547: ctxt->errNo = XML_ERR_ATTLIST_NOT_FINISHED;
1.66 daniel 3548: ctxt->wellFormed = 0;
3549: return(ret);
3550: }
3551: NEXT;
3552: return(ret);
3553: }
3554:
3555: /**
1.50 daniel 3556: * xmlParseEnumeratedType:
3557: * @ctxt: an XML parser context
1.66 daniel 3558: * @tree: the enumeration tree built while parsing
1.50 daniel 3559: *
1.66 daniel 3560: * parse an Enumerated attribute type.
1.22 daniel 3561: *
3562: * [57] EnumeratedType ::= NotationType | Enumeration
3563: *
3564: * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
3565: *
1.50 daniel 3566: *
1.66 daniel 3567: * Returns: XML_ATTRIBUTE_ENUMERATION or XML_ATTRIBUTE_NOTATION
1.22 daniel 3568: */
3569:
1.66 daniel 3570: int
3571: xmlParseEnumeratedType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
3572: if ((CUR == 'N') && (NXT(1) == 'O') &&
3573: (NXT(2) == 'T') && (NXT(3) == 'A') &&
3574: (NXT(4) == 'T') && (NXT(5) == 'I') &&
3575: (NXT(6) == 'O') && (NXT(7) == 'N')) {
3576: SKIP(8);
3577: if (!IS_BLANK(CUR)) {
3578: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 3579: ctxt->sax->error(ctxt->userData,
3580: "Space required after 'NOTATION'\n");
1.123 daniel 3581: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.66 daniel 3582: ctxt->wellFormed = 0;
3583: return(0);
3584: }
3585: SKIP_BLANKS;
3586: *tree = xmlParseNotationType(ctxt);
3587: if (*tree == NULL) return(0);
3588: return(XML_ATTRIBUTE_NOTATION);
3589: }
3590: *tree = xmlParseEnumerationType(ctxt);
3591: if (*tree == NULL) return(0);
3592: return(XML_ATTRIBUTE_ENUMERATION);
1.22 daniel 3593: }
3594:
1.50 daniel 3595: /**
3596: * xmlParseAttributeType:
3597: * @ctxt: an XML parser context
1.66 daniel 3598: * @tree: the enumeration tree built while parsing
1.50 daniel 3599: *
1.59 daniel 3600: * parse the Attribute list def for an element
1.22 daniel 3601: *
3602: * [54] AttType ::= StringType | TokenizedType | EnumeratedType
3603: *
3604: * [55] StringType ::= 'CDATA'
3605: *
3606: * [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' |
3607: * 'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'
1.50 daniel 3608: *
1.102 daniel 3609: * Validity constraints for attribute values syntax are checked in
3610: * xmlValidateAttributeValue()
3611: *
1.99 daniel 3612: * [ VC: ID ]
1.117 daniel 3613: * Values of type ID must match the Name production. A name must not
1.99 daniel 3614: * appear more than once in an XML document as a value of this type;
3615: * i.e., ID values must uniquely identify the elements which bear them.
3616: *
3617: * [ VC: One ID per Element Type ]
1.117 daniel 3618: * No element type may have more than one ID attribute specified.
1.99 daniel 3619: *
3620: * [ VC: ID Attribute Default ]
1.117 daniel 3621: * An ID attribute must have a declared default of #IMPLIED or #REQUIRED.
1.99 daniel 3622: *
3623: * [ VC: IDREF ]
1.102 daniel 3624: * Values of type IDREF must match the Name production, and values
1.117 daniel 3625: * of type IDREFS must match Names; TODO each IDREF Name must match the value
3626: * of an ID attribute on some element in the XML document; i.e. IDREF
1.99 daniel 3627: * values must match the value of some ID attribute.
3628: *
3629: * [ VC: Entity Name ]
1.102 daniel 3630: * Values of type ENTITY must match the Name production, values
1.117 daniel 3631: * of type ENTITIES must match Names; TODO each Entity Name must match the
3632: * name of an unparsed entity declared in the DTD.
1.99 daniel 3633: *
3634: * [ VC: Name Token ]
1.102 daniel 3635: * Values of type NMTOKEN must match the Nmtoken production; values
1.99 daniel 3636: * of type NMTOKENS must match Nmtokens.
3637: *
1.69 daniel 3638: * Returns the attribute type
1.22 daniel 3639: */
1.59 daniel 3640: int
1.66 daniel 3641: xmlParseAttributeType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
1.91 daniel 3642: SHRINK;
1.40 daniel 3643: if ((CUR == 'C') && (NXT(1) == 'D') &&
3644: (NXT(2) == 'A') && (NXT(3) == 'T') &&
3645: (NXT(4) == 'A')) {
3646: SKIP(5);
1.66 daniel 3647: return(XML_ATTRIBUTE_CDATA);
1.40 daniel 3648: } else if ((CUR == 'I') && (NXT(1) == 'D') &&
3649: (NXT(2) == 'R') && (NXT(3) == 'E') &&
1.97 daniel 3650: (NXT(4) == 'F') && (NXT(5) == 'S')) {
3651: SKIP(6);
3652: return(XML_ATTRIBUTE_IDREFS);
3653: } else if ((CUR == 'I') && (NXT(1) == 'D') &&
3654: (NXT(2) == 'R') && (NXT(3) == 'E') &&
1.40 daniel 3655: (NXT(4) == 'F')) {
3656: SKIP(5);
1.59 daniel 3657: return(XML_ATTRIBUTE_IDREF);
1.66 daniel 3658: } else if ((CUR == 'I') && (NXT(1) == 'D')) {
3659: SKIP(2);
3660: return(XML_ATTRIBUTE_ID);
1.40 daniel 3661: } else if ((CUR == 'E') && (NXT(1) == 'N') &&
3662: (NXT(2) == 'T') && (NXT(3) == 'I') &&
3663: (NXT(4) == 'T') && (NXT(5) == 'Y')) {
3664: SKIP(6);
1.59 daniel 3665: return(XML_ATTRIBUTE_ENTITY);
1.40 daniel 3666: } else if ((CUR == 'E') && (NXT(1) == 'N') &&
3667: (NXT(2) == 'T') && (NXT(3) == 'I') &&
3668: (NXT(4) == 'T') && (NXT(5) == 'I') &&
3669: (NXT(6) == 'E') && (NXT(7) == 'S')) {
3670: SKIP(8);
1.59 daniel 3671: return(XML_ATTRIBUTE_ENTITIES);
1.40 daniel 3672: } else if ((CUR == 'N') && (NXT(1) == 'M') &&
3673: (NXT(2) == 'T') && (NXT(3) == 'O') &&
3674: (NXT(4) == 'K') && (NXT(5) == 'E') &&
1.66 daniel 3675: (NXT(6) == 'N') && (NXT(7) == 'S')) {
3676: SKIP(8);
3677: return(XML_ATTRIBUTE_NMTOKENS);
3678: } else if ((CUR == 'N') && (NXT(1) == 'M') &&
3679: (NXT(2) == 'T') && (NXT(3) == 'O') &&
3680: (NXT(4) == 'K') && (NXT(5) == 'E') &&
1.40 daniel 3681: (NXT(6) == 'N')) {
3682: SKIP(7);
1.59 daniel 3683: return(XML_ATTRIBUTE_NMTOKEN);
1.22 daniel 3684: }
1.66 daniel 3685: return(xmlParseEnumeratedType(ctxt, tree));
1.22 daniel 3686: }
3687:
1.50 daniel 3688: /**
3689: * xmlParseAttributeListDecl:
3690: * @ctxt: an XML parser context
3691: *
3692: * : parse the Attribute list def for an element
1.22 daniel 3693: *
3694: * [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
3695: *
3696: * [53] AttDef ::= S Name S AttType S DefaultDecl
1.50 daniel 3697: *
1.22 daniel 3698: */
1.55 daniel 3699: void
3700: xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
1.123 daniel 3701: xmlChar *elemName;
3702: xmlChar *attrName;
1.103 daniel 3703: xmlEnumerationPtr tree;
1.22 daniel 3704:
1.40 daniel 3705: if ((CUR == '<') && (NXT(1) == '!') &&
3706: (NXT(2) == 'A') && (NXT(3) == 'T') &&
3707: (NXT(4) == 'T') && (NXT(5) == 'L') &&
3708: (NXT(6) == 'I') && (NXT(7) == 'S') &&
1.59 daniel 3709: (NXT(8) == 'T')) {
1.40 daniel 3710: SKIP(9);
1.59 daniel 3711: if (!IS_BLANK(CUR)) {
3712: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 3713: ctxt->sax->error(ctxt->userData,
3714: "Space required after '<!ATTLIST'\n");
1.123 daniel 3715: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 3716: ctxt->wellFormed = 0;
3717: }
1.42 daniel 3718: SKIP_BLANKS;
1.59 daniel 3719: elemName = xmlParseName(ctxt);
3720: if (elemName == NULL) {
1.55 daniel 3721: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 3722: ctxt->sax->error(ctxt->userData,
3723: "ATTLIST: no name for Element\n");
1.123 daniel 3724: ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.59 daniel 3725: ctxt->wellFormed = 0;
1.22 daniel 3726: return;
3727: }
1.42 daniel 3728: SKIP_BLANKS;
1.40 daniel 3729: while (CUR != '>') {
1.123 daniel 3730: const xmlChar *check = CUR_PTR;
1.59 daniel 3731: int type;
3732: int def;
1.123 daniel 3733: xmlChar *defaultValue = NULL;
1.59 daniel 3734:
1.103 daniel 3735: tree = NULL;
1.59 daniel 3736: attrName = xmlParseName(ctxt);
3737: if (attrName == NULL) {
3738: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 3739: ctxt->sax->error(ctxt->userData,
3740: "ATTLIST: no name for Attribute\n");
1.123 daniel 3741: ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.59 daniel 3742: ctxt->wellFormed = 0;
3743: break;
3744: }
1.97 daniel 3745: GROW;
1.59 daniel 3746: if (!IS_BLANK(CUR)) {
3747: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3748: ctxt->sax->error(ctxt->userData,
1.59 daniel 3749: "Space required after the attribute name\n");
1.123 daniel 3750: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 3751: ctxt->wellFormed = 0;
3752: break;
3753: }
3754: SKIP_BLANKS;
3755:
1.66 daniel 3756: type = xmlParseAttributeType(ctxt, &tree);
1.59 daniel 3757: if (type <= 0) break;
1.22 daniel 3758:
1.97 daniel 3759: GROW;
1.59 daniel 3760: if (!IS_BLANK(CUR)) {
3761: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3762: ctxt->sax->error(ctxt->userData,
1.59 daniel 3763: "Space required after the attribute type\n");
1.123 daniel 3764: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 3765: ctxt->wellFormed = 0;
3766: break;
3767: }
1.42 daniel 3768: SKIP_BLANKS;
1.59 daniel 3769:
3770: def = xmlParseDefaultDecl(ctxt, &defaultValue);
3771: if (def <= 0) break;
3772:
1.97 daniel 3773: GROW;
1.59 daniel 3774: if (CUR != '>') {
3775: if (!IS_BLANK(CUR)) {
3776: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3777: ctxt->sax->error(ctxt->userData,
1.59 daniel 3778: "Space required after the attribute default value\n");
1.123 daniel 3779: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 3780: ctxt->wellFormed = 0;
3781: break;
3782: }
3783: SKIP_BLANKS;
3784: }
1.40 daniel 3785: if (check == CUR_PTR) {
1.55 daniel 3786: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3787: ctxt->sax->error(ctxt->userData,
1.59 daniel 3788: "xmlParseAttributeListDecl: detected internal error\n");
1.123 daniel 3789: ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1.22 daniel 3790: break;
3791: }
1.72 daniel 3792: if ((ctxt->sax != NULL) && (ctxt->sax->attributeDecl != NULL))
1.74 daniel 3793: ctxt->sax->attributeDecl(ctxt->userData, elemName, attrName,
1.66 daniel 3794: type, def, defaultValue, tree);
1.59 daniel 3795: if (attrName != NULL)
1.119 daniel 3796: xmlFree(attrName);
1.59 daniel 3797: if (defaultValue != NULL)
1.119 daniel 3798: xmlFree(defaultValue);
1.97 daniel 3799: GROW;
1.22 daniel 3800: }
1.40 daniel 3801: if (CUR == '>')
3802: NEXT;
1.22 daniel 3803:
1.119 daniel 3804: xmlFree(elemName);
1.22 daniel 3805: }
3806: }
3807:
1.50 daniel 3808: /**
1.61 daniel 3809: * xmlParseElementMixedContentDecl:
3810: * @ctxt: an XML parser context
3811: *
3812: * parse the declaration for a Mixed Element content
3813: * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
3814: *
3815: * [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' |
3816: * '(' S? '#PCDATA' S? ')'
3817: *
1.99 daniel 3818: * [ VC: Proper Group/PE Nesting ] applies to [51] too (see [49])
3819: *
3820: * [ VC: No Duplicate Types ]
1.117 daniel 3821: * The same name must not appear more than once in a single
3822: * mixed-content declaration.
1.99 daniel 3823: *
1.61 daniel 3824: * returns: the list of the xmlElementContentPtr describing the element choices
3825: */
3826: xmlElementContentPtr
1.62 daniel 3827: xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt) {
1.64 daniel 3828: xmlElementContentPtr ret = NULL, cur = NULL, n;
1.123 daniel 3829: xmlChar *elem = NULL;
1.61 daniel 3830:
1.97 daniel 3831: GROW;
1.61 daniel 3832: if ((CUR == '#') && (NXT(1) == 'P') &&
3833: (NXT(2) == 'C') && (NXT(3) == 'D') &&
3834: (NXT(4) == 'A') && (NXT(5) == 'T') &&
3835: (NXT(6) == 'A')) {
3836: SKIP(7);
3837: SKIP_BLANKS;
1.91 daniel 3838: SHRINK;
1.63 daniel 3839: if (CUR == ')') {
3840: NEXT;
3841: ret = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_PCDATA);
3842: return(ret);
3843: }
1.61 daniel 3844: if ((CUR == '(') || (CUR == '|')) {
3845: ret = cur = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_PCDATA);
3846: if (ret == NULL) return(NULL);
1.99 daniel 3847: }
1.61 daniel 3848: while (CUR == '|') {
1.64 daniel 3849: NEXT;
1.61 daniel 3850: if (elem == NULL) {
3851: ret = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_OR);
3852: if (ret == NULL) return(NULL);
3853: ret->c1 = cur;
1.64 daniel 3854: cur = ret;
1.61 daniel 3855: } else {
1.64 daniel 3856: n = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_OR);
3857: if (n == NULL) return(NULL);
3858: n->c1 = xmlNewElementContent(elem, XML_ELEMENT_CONTENT_ELEMENT);
3859: cur->c2 = n;
3860: cur = n;
1.119 daniel 3861: xmlFree(elem);
1.61 daniel 3862: }
3863: SKIP_BLANKS;
3864: elem = xmlParseName(ctxt);
3865: if (elem == NULL) {
3866: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3867: ctxt->sax->error(ctxt->userData,
1.61 daniel 3868: "xmlParseElementMixedContentDecl : Name expected\n");
1.123 daniel 3869: ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.61 daniel 3870: ctxt->wellFormed = 0;
3871: xmlFreeElementContent(cur);
3872: return(NULL);
3873: }
3874: SKIP_BLANKS;
1.97 daniel 3875: GROW;
1.61 daniel 3876: }
1.63 daniel 3877: if ((CUR == ')') && (NXT(1) == '*')) {
1.66 daniel 3878: if (elem != NULL) {
1.61 daniel 3879: cur->c2 = xmlNewElementContent(elem,
3880: XML_ELEMENT_CONTENT_ELEMENT);
1.119 daniel 3881: xmlFree(elem);
1.66 daniel 3882: }
1.65 daniel 3883: ret->ocur = XML_ELEMENT_CONTENT_MULT;
1.64 daniel 3884: SKIP(2);
1.61 daniel 3885: } else {
1.119 daniel 3886: if (elem != NULL) xmlFree(elem);
1.61 daniel 3887: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3888: ctxt->sax->error(ctxt->userData,
1.63 daniel 3889: "xmlParseElementMixedContentDecl : '|' or ')*' expected\n");
1.123 daniel 3890: ctxt->errNo = XML_ERR_MIXED_NOT_STARTED;
1.61 daniel 3891: ctxt->wellFormed = 0;
3892: xmlFreeElementContent(ret);
3893: return(NULL);
3894: }
3895:
3896: } else {
3897: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3898: ctxt->sax->error(ctxt->userData,
1.61 daniel 3899: "xmlParseElementMixedContentDecl : '#PCDATA' expected\n");
1.123 daniel 3900: ctxt->errNo = XML_ERR_PCDATA_REQUIRED;
1.61 daniel 3901: ctxt->wellFormed = 0;
3902: }
3903: return(ret);
3904: }
3905:
3906: /**
3907: * xmlParseElementChildrenContentDecl:
1.50 daniel 3908: * @ctxt: an XML parser context
3909: *
1.61 daniel 3910: * parse the declaration for a Mixed Element content
3911: * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
1.22 daniel 3912: *
1.61 daniel 3913: *
1.22 daniel 3914: * [47] children ::= (choice | seq) ('?' | '*' | '+')?
3915: *
3916: * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
3917: *
3918: * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
3919: *
3920: * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
3921: *
1.99 daniel 3922: * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
3923: * TODO Parameter-entity replacement text must be properly nested
3924: * with parenthetized groups. That is to say, if either of the
3925: * opening or closing parentheses in a choice, seq, or Mixed
3926: * construct is contained in the replacement text for a parameter
3927: * entity, both must be contained in the same replacement text. For
3928: * interoperability, if a parameter-entity reference appears in a
3929: * choice, seq, or Mixed construct, its replacement text should not
3930: * be empty, and neither the first nor last non-blank character of
3931: * the replacement text should be a connector (| or ,).
3932: *
1.62 daniel 3933: * returns: the tree of xmlElementContentPtr describing the element
1.61 daniel 3934: * hierarchy.
3935: */
3936: xmlElementContentPtr
1.62 daniel 3937: xmlParseElementChildrenContentDecl(xmlParserCtxtPtr ctxt) {
1.63 daniel 3938: xmlElementContentPtr ret = NULL, cur = NULL, last = NULL, op = NULL;
1.123 daniel 3939: xmlChar *elem;
3940: xmlChar type = 0;
1.62 daniel 3941:
3942: SKIP_BLANKS;
1.94 daniel 3943: GROW;
1.62 daniel 3944: if (CUR == '(') {
1.63 daniel 3945: /* Recurse on first child */
1.62 daniel 3946: NEXT;
3947: SKIP_BLANKS;
3948: cur = ret = xmlParseElementChildrenContentDecl(ctxt);
3949: SKIP_BLANKS;
1.101 daniel 3950: GROW;
1.62 daniel 3951: } else {
3952: elem = xmlParseName(ctxt);
3953: if (elem == NULL) {
3954: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3955: ctxt->sax->error(ctxt->userData,
1.62 daniel 3956: "xmlParseElementChildrenContentDecl : Name or '(' expected\n");
1.123 daniel 3957: ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
1.62 daniel 3958: ctxt->wellFormed = 0;
3959: return(NULL);
3960: }
3961: cur = ret = xmlNewElementContent(elem, XML_ELEMENT_CONTENT_ELEMENT);
1.101 daniel 3962: GROW;
1.62 daniel 3963: if (CUR == '?') {
1.104 daniel 3964: cur->ocur = XML_ELEMENT_CONTENT_OPT;
1.62 daniel 3965: NEXT;
3966: } else if (CUR == '*') {
1.104 daniel 3967: cur->ocur = XML_ELEMENT_CONTENT_MULT;
1.62 daniel 3968: NEXT;
3969: } else if (CUR == '+') {
1.104 daniel 3970: cur->ocur = XML_ELEMENT_CONTENT_PLUS;
1.62 daniel 3971: NEXT;
3972: } else {
1.104 daniel 3973: cur->ocur = XML_ELEMENT_CONTENT_ONCE;
1.62 daniel 3974: }
1.119 daniel 3975: xmlFree(elem);
1.101 daniel 3976: GROW;
1.62 daniel 3977: }
3978: SKIP_BLANKS;
1.91 daniel 3979: SHRINK;
1.62 daniel 3980: while (CUR != ')') {
1.63 daniel 3981: /*
3982: * Each loop we parse one separator and one element.
3983: */
1.62 daniel 3984: if (CUR == ',') {
3985: if (type == 0) type = CUR;
3986:
3987: /*
3988: * Detect "Name | Name , Name" error
3989: */
3990: else if (type != CUR) {
3991: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 3992: ctxt->sax->error(ctxt->userData,
1.62 daniel 3993: "xmlParseElementChildrenContentDecl : '%c' expected\n",
3994: type);
1.123 daniel 3995: ctxt->errNo = XML_ERR_SEPARATOR_REQUIRED;
1.62 daniel 3996: ctxt->wellFormed = 0;
3997: xmlFreeElementContent(ret);
3998: return(NULL);
3999: }
1.64 daniel 4000: NEXT;
1.62 daniel 4001:
1.63 daniel 4002: op = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_SEQ);
4003: if (op == NULL) {
4004: xmlFreeElementContent(ret);
4005: return(NULL);
4006: }
4007: if (last == NULL) {
4008: op->c1 = ret;
1.65 daniel 4009: ret = cur = op;
1.63 daniel 4010: } else {
4011: cur->c2 = op;
4012: op->c1 = last;
4013: cur =op;
1.65 daniel 4014: last = NULL;
1.63 daniel 4015: }
1.62 daniel 4016: } else if (CUR == '|') {
4017: if (type == 0) type = CUR;
4018:
4019: /*
1.63 daniel 4020: * Detect "Name , Name | Name" error
1.62 daniel 4021: */
4022: else if (type != CUR) {
4023: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4024: ctxt->sax->error(ctxt->userData,
1.62 daniel 4025: "xmlParseElementChildrenContentDecl : '%c' expected\n",
4026: type);
1.123 daniel 4027: ctxt->errNo = XML_ERR_SEPARATOR_REQUIRED;
1.62 daniel 4028: ctxt->wellFormed = 0;
4029: xmlFreeElementContent(ret);
4030: return(NULL);
4031: }
1.64 daniel 4032: NEXT;
1.62 daniel 4033:
1.63 daniel 4034: op = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_OR);
4035: if (op == NULL) {
4036: xmlFreeElementContent(ret);
4037: return(NULL);
4038: }
4039: if (last == NULL) {
4040: op->c1 = ret;
1.65 daniel 4041: ret = cur = op;
1.63 daniel 4042: } else {
4043: cur->c2 = op;
4044: op->c1 = last;
4045: cur =op;
1.65 daniel 4046: last = NULL;
1.63 daniel 4047: }
1.62 daniel 4048: } else {
4049: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4050: ctxt->sax->error(ctxt->userData,
1.62 daniel 4051: "xmlParseElementChildrenContentDecl : ',' '|' or ')' expected\n");
4052: ctxt->wellFormed = 0;
1.123 daniel 4053: ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_FINISHED;
1.62 daniel 4054: xmlFreeElementContent(ret);
4055: return(NULL);
4056: }
1.101 daniel 4057: GROW;
1.62 daniel 4058: SKIP_BLANKS;
1.101 daniel 4059: GROW;
1.62 daniel 4060: if (CUR == '(') {
1.63 daniel 4061: /* Recurse on second child */
1.62 daniel 4062: NEXT;
4063: SKIP_BLANKS;
1.65 daniel 4064: last = xmlParseElementChildrenContentDecl(ctxt);
1.62 daniel 4065: SKIP_BLANKS;
4066: } else {
4067: elem = xmlParseName(ctxt);
4068: if (elem == NULL) {
4069: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4070: ctxt->sax->error(ctxt->userData,
1.122 daniel 4071: "xmlParseElementChildrenContentDecl : Name or '(' expected\n");
1.123 daniel 4072: ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
1.62 daniel 4073: ctxt->wellFormed = 0;
4074: return(NULL);
4075: }
1.65 daniel 4076: last = xmlNewElementContent(elem, XML_ELEMENT_CONTENT_ELEMENT);
1.119 daniel 4077: xmlFree(elem);
1.105 daniel 4078: if (CUR == '?') {
4079: last->ocur = XML_ELEMENT_CONTENT_OPT;
4080: NEXT;
4081: } else if (CUR == '*') {
4082: last->ocur = XML_ELEMENT_CONTENT_MULT;
4083: NEXT;
4084: } else if (CUR == '+') {
4085: last->ocur = XML_ELEMENT_CONTENT_PLUS;
4086: NEXT;
4087: } else {
4088: last->ocur = XML_ELEMENT_CONTENT_ONCE;
4089: }
1.63 daniel 4090: }
4091: SKIP_BLANKS;
1.97 daniel 4092: GROW;
1.64 daniel 4093: }
1.65 daniel 4094: if ((cur != NULL) && (last != NULL)) {
4095: cur->c2 = last;
1.62 daniel 4096: }
4097: NEXT;
4098: if (CUR == '?') {
4099: ret->ocur = XML_ELEMENT_CONTENT_OPT;
4100: NEXT;
4101: } else if (CUR == '*') {
4102: ret->ocur = XML_ELEMENT_CONTENT_MULT;
4103: NEXT;
4104: } else if (CUR == '+') {
4105: ret->ocur = XML_ELEMENT_CONTENT_PLUS;
4106: NEXT;
4107: }
4108: return(ret);
1.61 daniel 4109: }
4110:
4111: /**
4112: * xmlParseElementContentDecl:
4113: * @ctxt: an XML parser context
4114: * @name: the name of the element being defined.
4115: * @result: the Element Content pointer will be stored here if any
1.22 daniel 4116: *
1.61 daniel 4117: * parse the declaration for an Element content either Mixed or Children,
4118: * the cases EMPTY and ANY are handled directly in xmlParseElementDecl
4119: *
4120: * [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
1.50 daniel 4121: *
1.61 daniel 4122: * returns: the type of element content XML_ELEMENT_TYPE_xxx
1.22 daniel 4123: */
4124:
1.61 daniel 4125: int
1.123 daniel 4126: xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, xmlChar *name,
1.61 daniel 4127: xmlElementContentPtr *result) {
4128:
4129: xmlElementContentPtr tree = NULL;
4130: int res;
4131:
4132: *result = NULL;
4133:
4134: if (CUR != '(') {
4135: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4136: ctxt->sax->error(ctxt->userData,
1.61 daniel 4137: "xmlParseElementContentDecl : '(' expected\n");
1.123 daniel 4138: ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
1.61 daniel 4139: ctxt->wellFormed = 0;
4140: return(-1);
4141: }
4142: NEXT;
1.97 daniel 4143: GROW;
1.61 daniel 4144: SKIP_BLANKS;
4145: if ((CUR == '#') && (NXT(1) == 'P') &&
4146: (NXT(2) == 'C') && (NXT(3) == 'D') &&
4147: (NXT(4) == 'A') && (NXT(5) == 'T') &&
4148: (NXT(6) == 'A')) {
1.62 daniel 4149: tree = xmlParseElementMixedContentDecl(ctxt);
1.61 daniel 4150: res = XML_ELEMENT_TYPE_MIXED;
4151: } else {
1.62 daniel 4152: tree = xmlParseElementChildrenContentDecl(ctxt);
1.61 daniel 4153: res = XML_ELEMENT_TYPE_ELEMENT;
4154: }
4155: SKIP_BLANKS;
1.63 daniel 4156: /****************************
1.61 daniel 4157: if (CUR != ')') {
4158: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4159: ctxt->sax->error(ctxt->userData,
1.61 daniel 4160: "xmlParseElementContentDecl : ')' expected\n");
4161: ctxt->wellFormed = 0;
4162: return(-1);
4163: }
1.63 daniel 4164: ****************************/
4165: *result = tree;
1.61 daniel 4166: return(res);
1.22 daniel 4167: }
4168:
1.50 daniel 4169: /**
4170: * xmlParseElementDecl:
4171: * @ctxt: an XML parser context
4172: *
4173: * parse an Element declaration.
1.22 daniel 4174: *
4175: * [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
4176: *
1.99 daniel 4177: * [ VC: Unique Element Type Declaration ]
1.117 daniel 4178: * No element type may be declared more than once
1.69 daniel 4179: *
4180: * Returns the type of the element, or -1 in case of error
1.22 daniel 4181: */
1.59 daniel 4182: int
1.55 daniel 4183: xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
1.123 daniel 4184: xmlChar *name;
1.59 daniel 4185: int ret = -1;
1.61 daniel 4186: xmlElementContentPtr content = NULL;
1.22 daniel 4187:
1.97 daniel 4188: GROW;
1.40 daniel 4189: if ((CUR == '<') && (NXT(1) == '!') &&
4190: (NXT(2) == 'E') && (NXT(3) == 'L') &&
4191: (NXT(4) == 'E') && (NXT(5) == 'M') &&
4192: (NXT(6) == 'E') && (NXT(7) == 'N') &&
1.59 daniel 4193: (NXT(8) == 'T')) {
1.40 daniel 4194: SKIP(9);
1.59 daniel 4195: if (!IS_BLANK(CUR)) {
4196: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4197: ctxt->sax->error(ctxt->userData,
1.59 daniel 4198: "Space required after 'ELEMENT'\n");
1.123 daniel 4199: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 4200: ctxt->wellFormed = 0;
4201: }
1.42 daniel 4202: SKIP_BLANKS;
1.22 daniel 4203: name = xmlParseName(ctxt);
4204: if (name == NULL) {
1.55 daniel 4205: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4206: ctxt->sax->error(ctxt->userData,
1.59 daniel 4207: "xmlParseElementDecl: no name for Element\n");
1.123 daniel 4208: ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.59 daniel 4209: ctxt->wellFormed = 0;
4210: return(-1);
4211: }
4212: if (!IS_BLANK(CUR)) {
4213: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4214: ctxt->sax->error(ctxt->userData,
1.59 daniel 4215: "Space required after the element name\n");
1.123 daniel 4216: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 4217: ctxt->wellFormed = 0;
1.22 daniel 4218: }
1.42 daniel 4219: SKIP_BLANKS;
1.40 daniel 4220: if ((CUR == 'E') && (NXT(1) == 'M') &&
4221: (NXT(2) == 'P') && (NXT(3) == 'T') &&
4222: (NXT(4) == 'Y')) {
4223: SKIP(5);
1.22 daniel 4224: /*
4225: * Element must always be empty.
4226: */
1.59 daniel 4227: ret = XML_ELEMENT_TYPE_EMPTY;
1.40 daniel 4228: } else if ((CUR == 'A') && (NXT(1) == 'N') &&
4229: (NXT(2) == 'Y')) {
4230: SKIP(3);
1.22 daniel 4231: /*
4232: * Element is a generic container.
4233: */
1.59 daniel 4234: ret = XML_ELEMENT_TYPE_ANY;
1.61 daniel 4235: } else if (CUR == '(') {
4236: ret = xmlParseElementContentDecl(ctxt, name, &content);
1.22 daniel 4237: } else {
1.98 daniel 4238: /*
4239: * [ WFC: PEs in Internal Subset ] error handling.
4240: */
4241: if ((CUR == '%') && (ctxt->external == 0) &&
4242: (ctxt->inputNr == 1)) {
4243: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4244: ctxt->sax->error(ctxt->userData,
4245: "PEReference: forbidden within markup decl in internal subset\n");
1.123 daniel 4246: ctxt->errNo = XML_ERR_PEREF_IN_INT_SUBSET;
1.98 daniel 4247: } else {
4248: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4249: ctxt->sax->error(ctxt->userData,
4250: "xmlParseElementDecl: 'EMPTY', 'ANY' or '(' expected\n");
1.123 daniel 4251: ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
1.98 daniel 4252: }
1.61 daniel 4253: ctxt->wellFormed = 0;
1.119 daniel 4254: if (name != NULL) xmlFree(name);
1.61 daniel 4255: return(-1);
1.22 daniel 4256: }
1.42 daniel 4257: SKIP_BLANKS;
1.40 daniel 4258: if (CUR != '>') {
1.55 daniel 4259: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4260: ctxt->sax->error(ctxt->userData,
1.31 daniel 4261: "xmlParseElementDecl: expected '>' at the end\n");
1.123 daniel 4262: ctxt->errNo = XML_ERR_GT_REQUIRED;
1.59 daniel 4263: ctxt->wellFormed = 0;
1.61 daniel 4264: } else {
1.40 daniel 4265: NEXT;
1.72 daniel 4266: if ((ctxt->sax != NULL) && (ctxt->sax->elementDecl != NULL))
1.76 daniel 4267: ctxt->sax->elementDecl(ctxt->userData, name, ret,
4268: content);
1.61 daniel 4269: }
1.84 daniel 4270: if (content != NULL) {
4271: xmlFreeElementContent(content);
4272: }
1.61 daniel 4273: if (name != NULL) {
1.119 daniel 4274: xmlFree(name);
1.61 daniel 4275: }
1.22 daniel 4276: }
1.59 daniel 4277: return(ret);
1.22 daniel 4278: }
4279:
1.50 daniel 4280: /**
4281: * xmlParseMarkupDecl:
4282: * @ctxt: an XML parser context
4283: *
4284: * parse Markup declarations
1.22 daniel 4285: *
4286: * [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl |
4287: * NotationDecl | PI | Comment
4288: *
1.98 daniel 4289: * [ VC: Proper Declaration/PE Nesting ]
4290: * TODO Parameter-entity replacement text must be properly nested with
4291: * markup declarations. That is to say, if either the first character
4292: * or the last character of a markup declaration (markupdecl above) is
4293: * contained in the replacement text for a parameter-entity reference,
4294: * both must be contained in the same replacement text.
4295: *
4296: * [ WFC: PEs in Internal Subset ]
4297: * In the internal DTD subset, parameter-entity references can occur
4298: * only where markup declarations can occur, not within markup declarations.
4299: * (This does not apply to references that occur in external parameter
4300: * entities or to the external subset.)
1.22 daniel 4301: */
1.55 daniel 4302: void
4303: xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
1.94 daniel 4304: GROW;
1.22 daniel 4305: xmlParseElementDecl(ctxt);
4306: xmlParseAttributeListDecl(ctxt);
4307: xmlParseEntityDecl(ctxt);
4308: xmlParseNotationDecl(ctxt);
4309: xmlParsePI(ctxt);
1.114 daniel 4310: xmlParseComment(ctxt);
1.98 daniel 4311: /*
4312: * This is only for internal subset. On external entities,
4313: * the replacement is done before parsing stage
4314: */
4315: if ((ctxt->external == 0) && (ctxt->inputNr == 1))
4316: xmlParsePEReference(ctxt);
1.97 daniel 4317: ctxt->instate = XML_PARSER_DTD;
1.22 daniel 4318: }
4319:
1.50 daniel 4320: /**
1.76 daniel 4321: * xmlParseTextDecl:
4322: * @ctxt: an XML parser context
4323: *
4324: * parse an XML declaration header for external entities
4325: *
4326: * [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
4327: *
4328: * Returns the only valuable info for an external parsed entity, the encoding
4329: */
4330:
1.123 daniel 4331: xmlChar *
1.76 daniel 4332: xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
1.123 daniel 4333: xmlChar *version;
4334: xmlChar *encoding = NULL;
1.76 daniel 4335:
4336: /*
4337: * We know that '<?xml' is here.
4338: */
4339: SKIP(5);
4340:
4341: if (!IS_BLANK(CUR)) {
4342: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 4343: ctxt->sax->error(ctxt->userData,
4344: "Space needed after '<?xml'\n");
1.123 daniel 4345: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.76 daniel 4346: ctxt->wellFormed = 0;
4347: }
4348: SKIP_BLANKS;
4349:
4350: /*
4351: * We may have the VersionInfo here.
4352: */
4353: version = xmlParseVersionInfo(ctxt);
4354: if (version == NULL)
4355: version = xmlCharStrdup(XML_DEFAULT_VERSION);
4356: ctxt->version = xmlStrdup(version);
1.119 daniel 4357: xmlFree(version);
1.76 daniel 4358:
4359: /*
4360: * We must have the encoding declaration
4361: */
4362: if (!IS_BLANK(CUR)) {
4363: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 4364: ctxt->sax->error(ctxt->userData, "Space needed here\n");
1.123 daniel 4365: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.76 daniel 4366: ctxt->wellFormed = 0;
4367: }
4368: encoding = xmlParseEncodingDecl(ctxt);
4369:
4370: SKIP_BLANKS;
4371: if ((CUR == '?') && (NXT(1) == '>')) {
4372: SKIP(2);
4373: } else if (CUR == '>') {
4374: /* Deprecated old WD ... */
4375: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 4376: ctxt->sax->error(ctxt->userData,
4377: "XML declaration must end-up with '?>'\n");
1.123 daniel 4378: ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
1.76 daniel 4379: ctxt->wellFormed = 0;
4380: NEXT;
4381: } else {
4382: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 4383: ctxt->sax->error(ctxt->userData,
4384: "parsing XML declaration: '?>' expected\n");
1.123 daniel 4385: ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
1.76 daniel 4386: ctxt->wellFormed = 0;
4387: MOVETO_ENDTAG(CUR_PTR);
4388: NEXT;
4389: }
4390: return(encoding);
4391: }
4392:
4393: /*
4394: * xmlParseConditionalSections
4395: * @ctxt: an XML parser context
4396: *
4397: * TODO : Conditionnal section are not yet supported !
4398: *
4399: * [61] conditionalSect ::= includeSect | ignoreSect
4400: * [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
4401: * [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
4402: * [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
4403: * [65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
4404: */
4405:
4406: void
4407: xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
4408: if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
4409: ctxt->sax->warning(ctxt->userData,
4410: "XML conditional section not supported\n");
4411: /*
4412: * Skip up to the end of the conditionnal section.
4413: */
4414: while ((CUR != 0) && ((CUR != ']') || (NXT(1) != ']') || (NXT(2) != '>')))
4415: NEXT;
4416: if (CUR == 0) {
4417: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4418: ctxt->sax->error(ctxt->userData,
4419: "XML conditional section not closed\n");
1.123 daniel 4420: ctxt->errNo = XML_ERR_CONDSEC_NOT_FINISHED;
1.76 daniel 4421: ctxt->wellFormed = 0;
4422: }
4423: }
4424:
4425: /**
1.124 daniel 4426: * xmlParseExternalSubset:
1.76 daniel 4427: * @ctxt: an XML parser context
1.124 daniel 4428: * @ExternalID: the external identifier
4429: * @SystemID: the system identifier (or URL)
1.76 daniel 4430: *
4431: * parse Markup declarations from an external subset
4432: *
4433: * [30] extSubset ::= textDecl? extSubsetDecl
4434: *
4435: * [31] extSubsetDecl ::= (markupdecl | conditionalSect | PEReference | S) *
4436: */
4437: void
1.123 daniel 4438: xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
4439: const xmlChar *SystemID) {
1.76 daniel 4440: if ((CUR == '<') && (NXT(1) == '?') &&
4441: (NXT(2) == 'x') && (NXT(3) == 'm') &&
4442: (NXT(4) == 'l')) {
4443: xmlParseTextDecl(ctxt);
4444: }
1.79 daniel 4445: if (ctxt->myDoc == NULL) {
1.116 daniel 4446: ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
1.79 daniel 4447: }
4448: if ((ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset == NULL))
4449: xmlCreateIntSubset(ctxt->myDoc, NULL, ExternalID, SystemID);
4450:
1.96 daniel 4451: ctxt->instate = XML_PARSER_DTD;
1.101 daniel 4452: ctxt->external = 1;
1.76 daniel 4453: while (((CUR == '<') && (NXT(1) == '?')) ||
4454: ((CUR == '<') && (NXT(1) == '!')) ||
4455: IS_BLANK(CUR)) {
1.123 daniel 4456: const xmlChar *check = CUR_PTR;
1.115 daniel 4457: int cons = ctxt->input->consumed;
4458:
1.76 daniel 4459: if ((CUR == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
4460: xmlParseConditionalSections(ctxt);
4461: } else if (IS_BLANK(CUR)) {
4462: NEXT;
4463: } else if (CUR == '%') {
4464: xmlParsePEReference(ctxt);
4465: } else
4466: xmlParseMarkupDecl(ctxt);
1.77 daniel 4467:
4468: /*
4469: * Pop-up of finished entities.
4470: */
4471: while ((CUR == 0) && (ctxt->inputNr > 1))
4472: xmlPopInput(ctxt);
4473:
1.115 daniel 4474: if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
4475: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4476: ctxt->sax->error(ctxt->userData,
4477: "Content error in the external subset\n");
4478: ctxt->wellFormed = 0;
1.123 daniel 4479: ctxt->errNo = XML_ERR_EXT_SUBSET_NOT_FINISHED;
1.115 daniel 4480: break;
4481: }
1.76 daniel 4482: }
4483:
4484: if (CUR != 0) {
4485: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4486: ctxt->sax->error(ctxt->userData,
4487: "Extra content at the end of the document\n");
1.123 daniel 4488: ctxt->errNo = XML_ERR_EXT_SUBSET_NOT_FINISHED;
1.76 daniel 4489: ctxt->wellFormed = 0;
4490: }
4491:
4492: }
4493:
4494: /**
1.77 daniel 4495: * xmlParseReference:
4496: * @ctxt: an XML parser context
4497: *
4498: * parse and handle entity references in content, depending on the SAX
4499: * interface, this may end-up in a call to character() if this is a
1.79 daniel 4500: * CharRef, a predefined entity, if there is no reference() callback.
4501: * or if the parser was asked to switch to that mode.
1.77 daniel 4502: *
4503: * [67] Reference ::= EntityRef | CharRef
4504: */
4505: void
4506: xmlParseReference(xmlParserCtxtPtr ctxt) {
4507: xmlEntityPtr ent;
1.123 daniel 4508: xmlChar *val;
1.77 daniel 4509: if (CUR != '&') return;
4510:
1.113 daniel 4511: if (ctxt->inputNr > 1) {
1.123 daniel 4512: xmlChar cur[2] = { '&' , 0 } ;
1.113 daniel 4513:
4514: if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
4515: ctxt->sax->characters(ctxt->userData, cur, 1);
4516: if (ctxt->token == '&')
4517: ctxt->token = 0;
4518: else {
4519: SKIP(1);
4520: }
4521: return;
4522: }
1.77 daniel 4523: if (NXT(1) == '#') {
1.123 daniel 4524: xmlChar out[2];
1.77 daniel 4525: int val = xmlParseCharRef(ctxt);
1.117 daniel 4526: /* invalid for UTF-8 variable encoding !!!!! */
1.77 daniel 4527: out[0] = val;
4528: out[1] = 0;
4529: if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
4530: ctxt->sax->characters(ctxt->userData, out, 1);
4531: } else {
4532: ent = xmlParseEntityRef(ctxt);
4533: if (ent == NULL) return;
4534: if ((ent->name != NULL) &&
1.113 daniel 4535: (ent->type != XML_INTERNAL_PREDEFINED_ENTITY)) {
4536: if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
4537: (ctxt->replaceEntities == 0)) {
4538: /*
4539: * Create a node.
4540: */
4541: ctxt->sax->reference(ctxt->userData, ent->name);
4542: return;
4543: } else if (ctxt->replaceEntities) {
4544: xmlParserInputPtr input;
1.79 daniel 4545:
1.113 daniel 4546: input = xmlNewEntityInputStream(ctxt, ent);
4547: xmlPushInput(ctxt, input);
4548: return;
4549: }
1.77 daniel 4550: }
4551: val = ent->content;
4552: if (val == NULL) return;
4553: /*
4554: * inline the entity.
4555: */
4556: if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
4557: ctxt->sax->characters(ctxt->userData, val, xmlStrlen(val));
4558: }
1.24 daniel 4559: }
4560:
1.50 daniel 4561: /**
4562: * xmlParseEntityRef:
4563: * @ctxt: an XML parser context
4564: *
4565: * parse ENTITY references declarations
1.24 daniel 4566: *
4567: * [68] EntityRef ::= '&' Name ';'
1.68 daniel 4568: *
1.98 daniel 4569: * [ WFC: Entity Declared ]
4570: * In a document without any DTD, a document with only an internal DTD
4571: * subset which contains no parameter entity references, or a document
4572: * with "standalone='yes'", the Name given in the entity reference
4573: * must match that in an entity declaration, except that well-formed
4574: * documents need not declare any of the following entities: amp, lt,
4575: * gt, apos, quot. The declaration of a parameter entity must precede
4576: * any reference to it. Similarly, the declaration of a general entity
4577: * must precede any reference to it which appears in a default value in an
4578: * attribute-list declaration. Note that if entities are declared in the
4579: * external subset or in external parameter entities, a non-validating
4580: * processor is not obligated to read and process their declarations;
4581: * for such documents, the rule that an entity must be declared is a
4582: * well-formedness constraint only if standalone='yes'.
4583: *
4584: * [ WFC: Parsed Entity ]
4585: * An entity reference must not contain the name of an unparsed entity
4586: *
1.77 daniel 4587: * Returns the xmlEntityPtr if found, or NULL otherwise.
1.24 daniel 4588: */
1.77 daniel 4589: xmlEntityPtr
1.55 daniel 4590: xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
1.123 daniel 4591: xmlChar *name;
1.72 daniel 4592: xmlEntityPtr ent = NULL;
1.24 daniel 4593:
1.91 daniel 4594: GROW;
1.111 daniel 4595:
1.40 daniel 4596: if (CUR == '&') {
4597: NEXT;
1.24 daniel 4598: name = xmlParseName(ctxt);
4599: if (name == NULL) {
1.55 daniel 4600: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.98 daniel 4601: ctxt->sax->error(ctxt->userData,
4602: "xmlParseEntityRef: no name\n");
1.123 daniel 4603: ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.59 daniel 4604: ctxt->wellFormed = 0;
1.24 daniel 4605: } else {
1.40 daniel 4606: if (CUR == ';') {
4607: NEXT;
1.24 daniel 4608: /*
1.77 daniel 4609: * Ask first SAX for entity resolution, otherwise try the
4610: * predefined set.
4611: */
4612: if (ctxt->sax != NULL) {
4613: if (ctxt->sax->getEntity != NULL)
4614: ent = ctxt->sax->getEntity(ctxt->userData, name);
4615: if (ent == NULL)
4616: ent = xmlGetPredefinedEntity(name);
4617: }
4618: /*
1.98 daniel 4619: * [ WFC: Entity Declared ]
4620: * In a document without any DTD, a document with only an
4621: * internal DTD subset which contains no parameter entity
4622: * references, or a document with "standalone='yes'", the
4623: * Name given in the entity reference must match that in an
4624: * entity declaration, except that well-formed documents
4625: * need not declare any of the following entities: amp, lt,
4626: * gt, apos, quot.
4627: * The declaration of a parameter entity must precede any
4628: * reference to it.
4629: * Similarly, the declaration of a general entity must
4630: * precede any reference to it which appears in a default
4631: * value in an attribute-list declaration. Note that if
4632: * entities are declared in the external subset or in
4633: * external parameter entities, a non-validating processor
4634: * is not obligated to read and process their declarations;
4635: * for such documents, the rule that an entity must be
4636: * declared is a well-formedness constraint only if
4637: * standalone='yes'.
1.59 daniel 4638: */
1.77 daniel 4639: if (ent == NULL) {
1.98 daniel 4640: if ((ctxt->standalone == 1) ||
4641: ((ctxt->hasExternalSubset == 0) &&
4642: (ctxt->hasPErefs == 0))) {
4643: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.77 daniel 4644: ctxt->sax->error(ctxt->userData,
4645: "Entity '%s' not defined\n", name);
1.123 daniel 4646: ctxt->errNo = XML_ERR_UNDECLARED_ENTITY;
1.77 daniel 4647: ctxt->wellFormed = 0;
4648: } else {
1.98 daniel 4649: if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
4650: ctxt->sax->warning(ctxt->userData,
4651: "Entity '%s' not defined\n", name);
1.123 daniel 4652: ctxt->errNo = XML_WAR_UNDECLARED_ENTITY;
1.59 daniel 4653: }
1.77 daniel 4654: }
1.59 daniel 4655:
4656: /*
1.98 daniel 4657: * [ WFC: Parsed Entity ]
4658: * An entity reference must not contain the name of an
4659: * unparsed entity
4660: */
4661: else if (ent->type == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
4662: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4663: ctxt->sax->error(ctxt->userData,
4664: "Entity reference to unparsed entity %s\n", name);
1.123 daniel 4665: ctxt->errNo = XML_ERR_UNPARSED_ENTITY;
1.98 daniel 4666: ctxt->wellFormed = 0;
4667: }
4668:
4669: /*
4670: * [ WFC: No External Entity References ]
4671: * Attribute values cannot contain direct or indirect
4672: * entity references to external entities.
4673: */
4674: else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
4675: (ent->type == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
4676: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4677: ctxt->sax->error(ctxt->userData,
4678: "Attribute references external entity '%s'\n", name);
1.123 daniel 4679: ctxt->errNo = XML_ERR_ENTITY_IS_EXTERNAL;
1.98 daniel 4680: ctxt->wellFormed = 0;
4681: }
4682: /*
4683: * [ WFC: No < in Attribute Values ]
4684: * The replacement text of any entity referred to directly or
4685: * indirectly in an attribute value (other than "<") must
4686: * not contain a <.
1.59 daniel 4687: */
1.98 daniel 4688: else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
1.116 daniel 4689: (ent != NULL) &&
4690: (xmlStrcmp(ent->name, BAD_CAST "lt")) &&
1.98 daniel 4691: (ent->content != NULL) &&
4692: (xmlStrchr(ent->content, '<'))) {
4693: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4694: ctxt->sax->error(ctxt->userData,
4695: "'<' in entity '%s' is not allowed in attributes values\n", name);
1.123 daniel 4696: ctxt->errNo = XML_ERR_LT_IN_ATTRIBUTE;
1.98 daniel 4697: ctxt->wellFormed = 0;
4698: }
4699:
4700: /*
4701: * Internal check, no parameter entities here ...
4702: */
4703: else {
1.59 daniel 4704: switch (ent->type) {
4705: case XML_INTERNAL_PARAMETER_ENTITY:
4706: case XML_EXTERNAL_PARAMETER_ENTITY:
4707: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4708: ctxt->sax->error(ctxt->userData,
1.59 daniel 4709: "Attempt to reference the parameter entity '%s'\n", name);
1.123 daniel 4710: ctxt->errNo = XML_ERR_ENTITY_IS_PARAMETER;
1.59 daniel 4711: ctxt->wellFormed = 0;
4712: break;
4713: }
4714: }
4715:
4716: /*
1.98 daniel 4717: * [ WFC: No Recursion ]
1.117 daniel 4718: * TODO A parsed entity must not contain a recursive reference
4719: * to itself, either directly or indirectly.
1.59 daniel 4720: */
1.77 daniel 4721:
1.24 daniel 4722: } else {
1.55 daniel 4723: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4724: ctxt->sax->error(ctxt->userData,
1.59 daniel 4725: "xmlParseEntityRef: expecting ';'\n");
1.123 daniel 4726: ctxt->errNo = XML_ERR_ENTITYREF_SEMICOL_MISSING;
1.59 daniel 4727: ctxt->wellFormed = 0;
1.24 daniel 4728: }
1.119 daniel 4729: xmlFree(name);
1.24 daniel 4730: }
4731: }
1.77 daniel 4732: return(ent);
1.24 daniel 4733: }
4734:
1.50 daniel 4735: /**
4736: * xmlParsePEReference:
4737: * @ctxt: an XML parser context
4738: *
4739: * parse PEReference declarations
1.77 daniel 4740: * The entity content is handled directly by pushing it's content as
4741: * a new input stream.
1.22 daniel 4742: *
4743: * [69] PEReference ::= '%' Name ';'
1.68 daniel 4744: *
1.98 daniel 4745: * [ WFC: No Recursion ]
4746: * TODO A parsed entity must not contain a recursive
4747: * reference to itself, either directly or indirectly.
4748: *
4749: * [ WFC: Entity Declared ]
4750: * In a document without any DTD, a document with only an internal DTD
4751: * subset which contains no parameter entity references, or a document
4752: * with "standalone='yes'", ... ... The declaration of a parameter
4753: * entity must precede any reference to it...
4754: *
4755: * [ VC: Entity Declared ]
4756: * In a document with an external subset or external parameter entities
4757: * with "standalone='no'", ... ... The declaration of a parameter entity
4758: * must precede any reference to it...
4759: *
4760: * [ WFC: In DTD ]
4761: * Parameter-entity references may only appear in the DTD.
4762: * NOTE: misleading but this is handled.
1.22 daniel 4763: */
1.77 daniel 4764: void
1.55 daniel 4765: xmlParsePEReference(xmlParserCtxtPtr ctxt) {
1.123 daniel 4766: xmlChar *name;
1.72 daniel 4767: xmlEntityPtr entity = NULL;
1.50 daniel 4768: xmlParserInputPtr input;
1.22 daniel 4769:
1.40 daniel 4770: if (CUR == '%') {
4771: NEXT;
1.22 daniel 4772: name = xmlParseName(ctxt);
4773: if (name == NULL) {
1.55 daniel 4774: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 4775: ctxt->sax->error(ctxt->userData,
4776: "xmlParsePEReference: no name\n");
1.123 daniel 4777: ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.59 daniel 4778: ctxt->wellFormed = 0;
1.22 daniel 4779: } else {
1.40 daniel 4780: if (CUR == ';') {
4781: NEXT;
1.98 daniel 4782: if ((ctxt->sax != NULL) &&
4783: (ctxt->sax->getParameterEntity != NULL))
4784: entity = ctxt->sax->getParameterEntity(ctxt->userData,
4785: name);
1.45 daniel 4786: if (entity == NULL) {
1.98 daniel 4787: /*
4788: * [ WFC: Entity Declared ]
4789: * In a document without any DTD, a document with only an
4790: * internal DTD subset which contains no parameter entity
4791: * references, or a document with "standalone='yes'", ...
4792: * ... The declaration of a parameter entity must precede
4793: * any reference to it...
4794: */
4795: if ((ctxt->standalone == 1) ||
4796: ((ctxt->hasExternalSubset == 0) &&
4797: (ctxt->hasPErefs == 0))) {
4798: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
4799: ctxt->sax->error(ctxt->userData,
4800: "PEReference: %%%s; not found\n", name);
1.123 daniel 4801: ctxt->errNo = XML_ERR_UNDECLARED_ENTITY;
1.98 daniel 4802: ctxt->wellFormed = 0;
4803: } else {
4804: /*
4805: * [ VC: Entity Declared ]
4806: * In a document with an external subset or external
4807: * parameter entities with "standalone='no'", ...
4808: * ... The declaration of a parameter entity must precede
4809: * any reference to it...
4810: */
4811: if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
4812: ctxt->sax->warning(ctxt->userData,
4813: "PEReference: %%%s; not found\n", name);
4814: ctxt->valid = 0;
4815: }
1.50 daniel 4816: } else {
1.98 daniel 4817: /*
4818: * Internal checking in case the entity quest barfed
4819: */
4820: if ((entity->type != XML_INTERNAL_PARAMETER_ENTITY) &&
4821: (entity->type != XML_EXTERNAL_PARAMETER_ENTITY)) {
4822: if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
4823: ctxt->sax->warning(ctxt->userData,
4824: "Internal: %%%s; is not a parameter entity\n", name);
4825: } else {
4826: input = xmlNewEntityInputStream(ctxt, entity);
4827: xmlPushInput(ctxt, input);
4828: }
1.45 daniel 4829: }
1.98 daniel 4830: ctxt->hasPErefs = 1;
1.22 daniel 4831: } else {
1.55 daniel 4832: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4833: ctxt->sax->error(ctxt->userData,
1.59 daniel 4834: "xmlParsePEReference: expecting ';'\n");
1.123 daniel 4835: ctxt->errNo = XML_ERR_ENTITYREF_SEMICOL_MISSING;
1.59 daniel 4836: ctxt->wellFormed = 0;
1.22 daniel 4837: }
1.119 daniel 4838: xmlFree(name);
1.3 veillard 4839: }
4840: }
4841: }
4842:
1.50 daniel 4843: /**
4844: * xmlParseDocTypeDecl :
4845: * @ctxt: an XML parser context
4846: *
4847: * parse a DOCTYPE declaration
1.21 daniel 4848: *
1.22 daniel 4849: * [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S?
4850: * ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
1.98 daniel 4851: *
4852: * [ VC: Root Element Type ]
1.99 daniel 4853: * The Name in the document type declaration must match the element
1.98 daniel 4854: * type of the root element.
1.21 daniel 4855: */
4856:
1.55 daniel 4857: void
4858: xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt) {
1.123 daniel 4859: xmlChar *name;
4860: xmlChar *ExternalID = NULL;
4861: xmlChar *URI = NULL;
1.21 daniel 4862:
4863: /*
4864: * We know that '<!DOCTYPE' has been detected.
4865: */
1.40 daniel 4866: SKIP(9);
1.21 daniel 4867:
1.42 daniel 4868: SKIP_BLANKS;
1.21 daniel 4869:
4870: /*
4871: * Parse the DOCTYPE name.
4872: */
4873: name = xmlParseName(ctxt);
4874: if (name == NULL) {
1.55 daniel 4875: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 4876: ctxt->sax->error(ctxt->userData,
4877: "xmlParseDocTypeDecl : no DOCTYPE name !\n");
1.59 daniel 4878: ctxt->wellFormed = 0;
1.123 daniel 4879: ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.21 daniel 4880: }
4881:
1.42 daniel 4882: SKIP_BLANKS;
1.21 daniel 4883:
4884: /*
1.22 daniel 4885: * Check for SystemID and ExternalID
4886: */
1.67 daniel 4887: URI = xmlParseExternalID(ctxt, &ExternalID, 1);
1.98 daniel 4888:
4889: if ((URI != NULL) || (ExternalID != NULL)) {
4890: ctxt->hasExternalSubset = 1;
4891: }
4892:
1.42 daniel 4893: SKIP_BLANKS;
1.36 daniel 4894:
1.76 daniel 4895: /*
4896: * NOTE: the SAX callback may try to fetch the external subset
4897: * entity and fill it up !
4898: */
1.72 daniel 4899: if ((ctxt->sax != NULL) && (ctxt->sax->internalSubset != NULL))
1.74 daniel 4900: ctxt->sax->internalSubset(ctxt->userData, name, ExternalID, URI);
1.22 daniel 4901:
4902: /*
4903: * Is there any DTD definition ?
4904: */
1.40 daniel 4905: if (CUR == '[') {
1.96 daniel 4906: ctxt->instate = XML_PARSER_DTD;
1.40 daniel 4907: NEXT;
1.22 daniel 4908: /*
4909: * Parse the succession of Markup declarations and
4910: * PEReferences.
4911: * Subsequence (markupdecl | PEReference | S)*
4912: */
1.40 daniel 4913: while (CUR != ']') {
1.123 daniel 4914: const xmlChar *check = CUR_PTR;
1.115 daniel 4915: int cons = ctxt->input->consumed;
1.22 daniel 4916:
1.42 daniel 4917: SKIP_BLANKS;
1.22 daniel 4918: xmlParseMarkupDecl(ctxt);
1.50 daniel 4919: xmlParsePEReference(ctxt);
1.22 daniel 4920:
1.115 daniel 4921: /*
4922: * Pop-up of finished entities.
4923: */
4924: while ((CUR == 0) && (ctxt->inputNr > 1))
4925: xmlPopInput(ctxt);
4926:
1.118 daniel 4927: if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
1.55 daniel 4928: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4929: ctxt->sax->error(ctxt->userData,
1.31 daniel 4930: "xmlParseDocTypeDecl: error detected in Markup declaration\n");
1.59 daniel 4931: ctxt->wellFormed = 0;
1.123 daniel 4932: ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1.22 daniel 4933: break;
4934: }
4935: }
1.40 daniel 4936: if (CUR == ']') NEXT;
1.22 daniel 4937: }
4938:
4939: /*
4940: * We should be at the end of the DOCTYPE declaration.
1.21 daniel 4941: */
1.40 daniel 4942: if (CUR != '>') {
1.55 daniel 4943: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4944: ctxt->sax->error(ctxt->userData, "DOCTYPE unproperly terminated\n");
1.59 daniel 4945: ctxt->wellFormed = 0;
1.123 daniel 4946: ctxt->errNo = XML_ERR_DOCTYPE_NOT_FINISHED;
1.21 daniel 4947: }
1.40 daniel 4948: NEXT;
1.22 daniel 4949:
4950: /*
1.99 daniel 4951: * Cleanup
1.22 daniel 4952: */
1.119 daniel 4953: if (URI != NULL) xmlFree(URI);
4954: if (ExternalID != NULL) xmlFree(ExternalID);
4955: if (name != NULL) xmlFree(name);
1.21 daniel 4956: }
4957:
1.50 daniel 4958: /**
4959: * xmlParseAttribute:
4960: * @ctxt: an XML parser context
1.123 daniel 4961: * @value: a xmlChar ** used to store the value of the attribute
1.50 daniel 4962: *
4963: * parse an attribute
1.3 veillard 4964: *
1.22 daniel 4965: * [41] Attribute ::= Name Eq AttValue
4966: *
1.98 daniel 4967: * [ WFC: No External Entity References ]
4968: * Attribute values cannot contain direct or indirect entity references
4969: * to external entities.
4970: *
4971: * [ WFC: No < in Attribute Values ]
4972: * The replacement text of any entity referred to directly or indirectly in
4973: * an attribute value (other than "<") must not contain a <.
4974: *
4975: * [ VC: Attribute Value Type ]
1.117 daniel 4976: * The attribute must have been declared; the value must be of the type
1.99 daniel 4977: * declared for it.
1.98 daniel 4978: *
1.22 daniel 4979: * [25] Eq ::= S? '=' S?
4980: *
1.29 daniel 4981: * With namespace:
4982: *
4983: * [NS 11] Attribute ::= QName Eq AttValue
1.43 daniel 4984: *
4985: * Also the case QName == xmlns:??? is handled independently as a namespace
4986: * definition.
1.69 daniel 4987: *
1.72 daniel 4988: * Returns the attribute name, and the value in *value.
1.3 veillard 4989: */
4990:
1.123 daniel 4991: xmlChar *
4992: xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlChar **value) {
4993: xmlChar *name, *val;
1.3 veillard 4994:
1.72 daniel 4995: *value = NULL;
4996: name = xmlParseName(ctxt);
1.22 daniel 4997: if (name == NULL) {
1.55 daniel 4998: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 4999: ctxt->sax->error(ctxt->userData, "error parsing attribute name\n");
1.59 daniel 5000: ctxt->wellFormed = 0;
1.123 daniel 5001: ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.52 daniel 5002: return(NULL);
1.3 veillard 5003: }
5004:
5005: /*
1.29 daniel 5006: * read the value
1.3 veillard 5007: */
1.42 daniel 5008: SKIP_BLANKS;
1.40 daniel 5009: if (CUR == '=') {
5010: NEXT;
1.42 daniel 5011: SKIP_BLANKS;
1.72 daniel 5012: val = xmlParseAttValue(ctxt);
1.96 daniel 5013: ctxt->instate = XML_PARSER_CONTENT;
1.29 daniel 5014: } else {
1.55 daniel 5015: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5016: ctxt->sax->error(ctxt->userData,
1.59 daniel 5017: "Specification mandate value for attribute %s\n", name);
1.123 daniel 5018: ctxt->errNo = XML_ERR_ATTRIBUTE_WITHOUT_VALUE;
1.59 daniel 5019: ctxt->wellFormed = 0;
1.52 daniel 5020: return(NULL);
1.43 daniel 5021: }
5022:
1.72 daniel 5023: *value = val;
5024: return(name);
1.3 veillard 5025: }
5026:
1.50 daniel 5027: /**
5028: * xmlParseStartTag:
5029: * @ctxt: an XML parser context
5030: *
5031: * parse a start of tag either for rule element or
5032: * EmptyElement. In both case we don't parse the tag closing chars.
1.27 daniel 5033: *
5034: * [40] STag ::= '<' Name (S Attribute)* S? '>'
5035: *
1.98 daniel 5036: * [ WFC: Unique Att Spec ]
5037: * No attribute name may appear more than once in the same start-tag or
5038: * empty-element tag.
5039: *
1.29 daniel 5040: * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
5041: *
1.98 daniel 5042: * [ WFC: Unique Att Spec ]
5043: * No attribute name may appear more than once in the same start-tag or
5044: * empty-element tag.
5045: *
1.29 daniel 5046: * With namespace:
5047: *
5048: * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
5049: *
5050: * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
1.83 daniel 5051: *
1.129 daniel 5052: * Returne the element name parsed
1.2 veillard 5053: */
5054:
1.123 daniel 5055: xmlChar *
1.69 daniel 5056: xmlParseStartTag(xmlParserCtxtPtr ctxt) {
1.123 daniel 5057: xmlChar *name;
5058: xmlChar *attname;
5059: xmlChar *attvalue;
5060: const xmlChar **atts = NULL;
1.72 daniel 5061: int nbatts = 0;
5062: int maxatts = 0;
5063: int i;
1.2 veillard 5064:
1.83 daniel 5065: if (CUR != '<') return(NULL);
1.40 daniel 5066: NEXT;
1.3 veillard 5067:
1.72 daniel 5068: name = xmlParseName(ctxt);
1.59 daniel 5069: if (name == NULL) {
5070: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5071: ctxt->sax->error(ctxt->userData,
1.59 daniel 5072: "xmlParseStartTag: invalid element name\n");
1.123 daniel 5073: ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.59 daniel 5074: ctxt->wellFormed = 0;
1.83 daniel 5075: return(NULL);
1.50 daniel 5076: }
5077:
5078: /*
1.3 veillard 5079: * Now parse the attributes, it ends up with the ending
5080: *
5081: * (S Attribute)* S?
5082: */
1.42 daniel 5083: SKIP_BLANKS;
1.91 daniel 5084: GROW;
1.40 daniel 5085: while ((IS_CHAR(CUR)) &&
5086: (CUR != '>') &&
5087: ((CUR != '/') || (NXT(1) != '>'))) {
1.123 daniel 5088: const xmlChar *q = CUR_PTR;
1.91 daniel 5089: int cons = ctxt->input->consumed;
1.29 daniel 5090:
1.72 daniel 5091: attname = xmlParseAttribute(ctxt, &attvalue);
5092: if ((attname != NULL) && (attvalue != NULL)) {
5093: /*
1.98 daniel 5094: * [ WFC: Unique Att Spec ]
5095: * No attribute name may appear more than once in the same
5096: * start-tag or empty-element tag.
1.72 daniel 5097: */
5098: for (i = 0; i < nbatts;i += 2) {
5099: if (!xmlStrcmp(atts[i], attname)) {
5100: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.98 daniel 5101: ctxt->sax->error(ctxt->userData,
5102: "Attribute %s redefined\n",
5103: attname);
1.72 daniel 5104: ctxt->wellFormed = 0;
1.123 daniel 5105: ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
1.119 daniel 5106: xmlFree(attname);
5107: xmlFree(attvalue);
1.98 daniel 5108: goto failed;
1.72 daniel 5109: }
5110: }
5111:
5112: /*
5113: * Add the pair to atts
5114: */
5115: if (atts == NULL) {
5116: maxatts = 10;
1.123 daniel 5117: atts = (const xmlChar **) xmlMalloc(maxatts * sizeof(xmlChar *));
1.72 daniel 5118: if (atts == NULL) {
1.86 daniel 5119: fprintf(stderr, "malloc of %ld byte failed\n",
1.123 daniel 5120: maxatts * (long)sizeof(xmlChar *));
1.83 daniel 5121: return(NULL);
1.72 daniel 5122: }
1.127 daniel 5123: } else if (nbatts + 4 > maxatts) {
1.72 daniel 5124: maxatts *= 2;
1.123 daniel 5125: atts = (const xmlChar **) xmlRealloc(atts,
5126: maxatts * sizeof(xmlChar *));
1.72 daniel 5127: if (atts == NULL) {
1.86 daniel 5128: fprintf(stderr, "realloc of %ld byte failed\n",
1.123 daniel 5129: maxatts * (long)sizeof(xmlChar *));
1.83 daniel 5130: return(NULL);
1.72 daniel 5131: }
5132: }
5133: atts[nbatts++] = attname;
5134: atts[nbatts++] = attvalue;
5135: atts[nbatts] = NULL;
5136: atts[nbatts + 1] = NULL;
5137: }
5138:
1.116 daniel 5139: failed:
1.42 daniel 5140: SKIP_BLANKS;
1.91 daniel 5141: if ((cons == ctxt->input->consumed) && (q == CUR_PTR)) {
1.55 daniel 5142: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5143: ctxt->sax->error(ctxt->userData,
1.31 daniel 5144: "xmlParseStartTag: problem parsing attributes\n");
1.123 daniel 5145: ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1.59 daniel 5146: ctxt->wellFormed = 0;
1.29 daniel 5147: break;
1.3 veillard 5148: }
1.91 daniel 5149: GROW;
1.3 veillard 5150: }
5151:
1.43 daniel 5152: /*
1.72 daniel 5153: * SAX: Start of Element !
1.43 daniel 5154: */
1.72 daniel 5155: if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL))
1.74 daniel 5156: ctxt->sax->startElement(ctxt->userData, name, atts);
1.43 daniel 5157:
1.72 daniel 5158: if (atts != NULL) {
1.123 daniel 5159: for (i = 0;i < nbatts;i++) xmlFree((xmlChar *) atts[i]);
1.119 daniel 5160: xmlFree(atts);
1.72 daniel 5161: }
1.83 daniel 5162: return(name);
1.3 veillard 5163: }
5164:
1.50 daniel 5165: /**
5166: * xmlParseEndTag:
5167: * @ctxt: an XML parser context
1.83 daniel 5168: * @tagname: the tag name as parsed in the opening tag.
1.50 daniel 5169: *
5170: * parse an end of tag
1.27 daniel 5171: *
5172: * [42] ETag ::= '</' Name S? '>'
1.29 daniel 5173: *
5174: * With namespace
5175: *
1.72 daniel 5176: * [NS 9] ETag ::= '</' QName S? '>'
1.7 veillard 5177: */
5178:
1.55 daniel 5179: void
1.123 daniel 5180: xmlParseEndTag(xmlParserCtxtPtr ctxt, xmlChar *tagname) {
5181: xmlChar *name;
1.7 veillard 5182:
1.91 daniel 5183: GROW;
1.40 daniel 5184: if ((CUR != '<') || (NXT(1) != '/')) {
1.55 daniel 5185: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5186: ctxt->sax->error(ctxt->userData, "xmlParseEndTag: '</' not found\n");
1.59 daniel 5187: ctxt->wellFormed = 0;
1.123 daniel 5188: ctxt->errNo = XML_ERR_LTSLASH_REQUIRED;
1.27 daniel 5189: return;
5190: }
1.40 daniel 5191: SKIP(2);
1.7 veillard 5192:
1.72 daniel 5193: name = xmlParseName(ctxt);
1.7 veillard 5194:
5195: /*
5196: * We should definitely be at the ending "S? '>'" part
5197: */
1.91 daniel 5198: GROW;
1.42 daniel 5199: SKIP_BLANKS;
1.40 daniel 5200: if ((!IS_CHAR(CUR)) || (CUR != '>')) {
1.55 daniel 5201: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5202: ctxt->sax->error(ctxt->userData, "End tag : expected '>'\n");
1.123 daniel 5203: ctxt->errNo = XML_ERR_GT_REQUIRED;
1.59 daniel 5204: ctxt->wellFormed = 0;
1.7 veillard 5205: } else
1.40 daniel 5206: NEXT;
1.7 veillard 5207:
1.72 daniel 5208: /*
1.98 daniel 5209: * [ WFC: Element Type Match ]
5210: * The Name in an element's end-tag must match the element type in the
5211: * start-tag.
5212: *
1.83 daniel 5213: */
5214: if (xmlStrcmp(name, tagname)) {
5215: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
5216: ctxt->sax->error(ctxt->userData,
5217: "Opening and ending tag mismatch: %s and %s\n", tagname, name);
1.122 daniel 5218:
1.123 daniel 5219: ctxt->errNo = XML_ERR_TAG_NAME_MISMATCH;
1.83 daniel 5220: ctxt->wellFormed = 0;
5221: }
5222:
5223: /*
1.72 daniel 5224: * SAX: End of Tag
5225: */
5226: if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
1.74 daniel 5227: ctxt->sax->endElement(ctxt->userData, name);
1.72 daniel 5228:
5229: if (name != NULL)
1.119 daniel 5230: xmlFree(name);
1.72 daniel 5231:
1.7 veillard 5232: return;
5233: }
5234:
1.50 daniel 5235: /**
5236: * xmlParseCDSect:
5237: * @ctxt: an XML parser context
5238: *
5239: * Parse escaped pure raw content.
1.29 daniel 5240: *
5241: * [18] CDSect ::= CDStart CData CDEnd
5242: *
5243: * [19] CDStart ::= '<![CDATA['
5244: *
5245: * [20] Data ::= (Char* - (Char* ']]>' Char*))
5246: *
5247: * [21] CDEnd ::= ']]>'
1.3 veillard 5248: */
1.55 daniel 5249: void
5250: xmlParseCDSect(xmlParserCtxtPtr ctxt) {
1.123 daniel 5251: const xmlChar *base;
5252: xmlChar r, s;
5253: xmlChar cur;
1.3 veillard 5254:
1.106 daniel 5255: if ((NXT(0) == '<') && (NXT(1) == '!') &&
1.40 daniel 5256: (NXT(2) == '[') && (NXT(3) == 'C') &&
5257: (NXT(4) == 'D') && (NXT(5) == 'A') &&
5258: (NXT(6) == 'T') && (NXT(7) == 'A') &&
5259: (NXT(8) == '[')) {
5260: SKIP(9);
1.29 daniel 5261: } else
1.45 daniel 5262: return;
1.109 daniel 5263:
5264: ctxt->instate = XML_PARSER_CDATA_SECTION;
1.40 daniel 5265: base = CUR_PTR;
5266: if (!IS_CHAR(CUR)) {
1.55 daniel 5267: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 5268: ctxt->sax->error(ctxt->userData,
5269: "CData section not finished\n%.50s\n", base);
1.59 daniel 5270: ctxt->wellFormed = 0;
1.123 daniel 5271: ctxt->errNo = XML_ERR_CDATA_NOT_FINISHED;
1.109 daniel 5272: ctxt->instate = XML_PARSER_CONTENT;
1.45 daniel 5273: return;
1.3 veillard 5274: }
1.110 daniel 5275: r = CUR;
1.91 daniel 5276: NEXT;
1.40 daniel 5277: if (!IS_CHAR(CUR)) {
1.55 daniel 5278: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 5279: ctxt->sax->error(ctxt->userData,
5280: "CData section not finished\n%.50s\n", base);
1.123 daniel 5281: ctxt->errNo = XML_ERR_CDATA_NOT_FINISHED;
1.59 daniel 5282: ctxt->wellFormed = 0;
1.109 daniel 5283: ctxt->instate = XML_PARSER_CONTENT;
1.45 daniel 5284: return;
1.3 veillard 5285: }
1.110 daniel 5286: s = CUR;
1.91 daniel 5287: NEXT;
1.108 veillard 5288: cur = CUR;
5289: while (IS_CHAR(cur) &&
1.110 daniel 5290: ((r != ']') || (s != ']') || (cur != '>'))) {
5291: r = s;
5292: s = cur;
5293: NEXT;
1.108 veillard 5294: cur = CUR;
1.3 veillard 5295: }
1.109 daniel 5296: ctxt->instate = XML_PARSER_CONTENT;
1.40 daniel 5297: if (!IS_CHAR(CUR)) {
1.55 daniel 5298: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 5299: ctxt->sax->error(ctxt->userData,
5300: "CData section not finished\n%.50s\n", base);
1.123 daniel 5301: ctxt->errNo = XML_ERR_CDATA_NOT_FINISHED;
1.59 daniel 5302: ctxt->wellFormed = 0;
1.45 daniel 5303: return;
1.3 veillard 5304: }
1.107 daniel 5305: NEXT;
1.16 daniel 5306:
1.45 daniel 5307: /*
5308: * Ok the segment [base CUR_PTR] is to be consumed as chars.
5309: */
5310: if (ctxt->sax != NULL) {
1.107 daniel 5311: if (ctxt->sax->cdataBlock != NULL)
1.110 daniel 5312: ctxt->sax->cdataBlock(ctxt->userData, base, (CUR_PTR - base) - 3);
1.45 daniel 5313: }
1.2 veillard 5314: }
5315:
1.50 daniel 5316: /**
5317: * xmlParseContent:
5318: * @ctxt: an XML parser context
5319: *
5320: * Parse a content:
1.2 veillard 5321: *
1.27 daniel 5322: * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
1.2 veillard 5323: */
5324:
1.55 daniel 5325: void
5326: xmlParseContent(xmlParserCtxtPtr ctxt) {
1.97 daniel 5327: GROW;
1.40 daniel 5328: while ((CUR != '<') || (NXT(1) != '/')) {
1.123 daniel 5329: const xmlChar *test = CUR_PTR;
1.91 daniel 5330: int cons = ctxt->input->consumed;
1.123 daniel 5331: xmlChar tok = ctxt->token;
1.27 daniel 5332:
5333: /*
5334: * First case : a Processing Instruction.
5335: */
1.40 daniel 5336: if ((CUR == '<') && (NXT(1) == '?')) {
1.27 daniel 5337: xmlParsePI(ctxt);
5338: }
1.72 daniel 5339:
1.27 daniel 5340: /*
5341: * Second case : a CDSection
5342: */
1.40 daniel 5343: else if ((CUR == '<') && (NXT(1) == '!') &&
5344: (NXT(2) == '[') && (NXT(3) == 'C') &&
5345: (NXT(4) == 'D') && (NXT(5) == 'A') &&
5346: (NXT(6) == 'T') && (NXT(7) == 'A') &&
5347: (NXT(8) == '[')) {
1.45 daniel 5348: xmlParseCDSect(ctxt);
1.27 daniel 5349: }
1.72 daniel 5350:
1.27 daniel 5351: /*
5352: * Third case : a comment
5353: */
1.40 daniel 5354: else if ((CUR == '<') && (NXT(1) == '!') &&
5355: (NXT(2) == '-') && (NXT(3) == '-')) {
1.114 daniel 5356: xmlParseComment(ctxt);
1.97 daniel 5357: ctxt->instate = XML_PARSER_CONTENT;
1.27 daniel 5358: }
1.72 daniel 5359:
1.27 daniel 5360: /*
5361: * Fourth case : a sub-element.
5362: */
1.40 daniel 5363: else if (CUR == '<') {
1.72 daniel 5364: xmlParseElement(ctxt);
1.45 daniel 5365: }
1.72 daniel 5366:
1.45 daniel 5367: /*
1.50 daniel 5368: * Fifth case : a reference. If if has not been resolved,
5369: * parsing returns it's Name, create the node
1.45 daniel 5370: */
1.97 daniel 5371:
1.45 daniel 5372: else if (CUR == '&') {
1.77 daniel 5373: xmlParseReference(ctxt);
1.27 daniel 5374: }
1.72 daniel 5375:
1.27 daniel 5376: /*
5377: * Last case, text. Note that References are handled directly.
5378: */
5379: else {
1.45 daniel 5380: xmlParseCharData(ctxt, 0);
1.3 veillard 5381: }
1.14 veillard 5382:
1.91 daniel 5383: GROW;
1.14 veillard 5384: /*
1.45 daniel 5385: * Pop-up of finished entities.
1.14 veillard 5386: */
1.69 daniel 5387: while ((CUR == 0) && (ctxt->inputNr > 1))
5388: xmlPopInput(ctxt);
1.45 daniel 5389:
1.113 daniel 5390: if ((cons == ctxt->input->consumed) && (test == CUR_PTR) &&
5391: (tok == ctxt->token)) {
1.55 daniel 5392: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5393: ctxt->sax->error(ctxt->userData,
1.59 daniel 5394: "detected an error in element content\n");
1.123 daniel 5395: ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1.59 daniel 5396: ctxt->wellFormed = 0;
1.29 daniel 5397: break;
5398: }
1.3 veillard 5399: }
1.2 veillard 5400: }
5401:
1.50 daniel 5402: /**
5403: * xmlParseElement:
5404: * @ctxt: an XML parser context
5405: *
5406: * parse an XML element, this is highly recursive
1.26 daniel 5407: *
5408: * [39] element ::= EmptyElemTag | STag content ETag
5409: *
1.98 daniel 5410: * [ WFC: Element Type Match ]
5411: * The Name in an element's end-tag must match the element type in the
5412: * start-tag.
5413: *
5414: * [ VC: Element Valid ]
1.117 daniel 5415: * An element is valid if there is a declaration matching elementdecl
1.99 daniel 5416: * where the Name matches the element type and one of the following holds:
5417: * - The declaration matches EMPTY and the element has no content.
5418: * - The declaration matches children and the sequence of child elements
5419: * belongs to the language generated by the regular expression in the
5420: * content model, with optional white space (characters matching the
5421: * nonterminal S) between each pair of child elements.
5422: * - The declaration matches Mixed and the content consists of character
5423: * data and child elements whose types match names in the content model.
5424: * - The declaration matches ANY, and the types of any child elements have
5425: * been declared.
1.2 veillard 5426: */
1.26 daniel 5427:
1.72 daniel 5428: void
1.69 daniel 5429: xmlParseElement(xmlParserCtxtPtr ctxt) {
1.123 daniel 5430: const xmlChar *openTag = CUR_PTR;
5431: xmlChar *name;
1.32 daniel 5432: xmlParserNodeInfo node_info;
1.118 daniel 5433: xmlNodePtr ret;
1.2 veillard 5434:
1.32 daniel 5435: /* Capture start position */
1.118 daniel 5436: if (ctxt->record_info) {
5437: node_info.begin_pos = ctxt->input->consumed +
5438: (CUR_PTR - ctxt->input->base);
5439: node_info.begin_line = ctxt->input->line;
5440: }
1.32 daniel 5441:
1.83 daniel 5442: name = xmlParseStartTag(ctxt);
5443: if (name == NULL) {
5444: return;
5445: }
1.118 daniel 5446: ret = ctxt->node;
1.2 veillard 5447:
5448: /*
1.99 daniel 5449: * [ VC: Root Element Type ]
5450: * The Name in the document type declaration must match the element
5451: * type of the root element.
5452: */
1.105 daniel 5453: if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
5454: ctxt->node && (ctxt->node == ctxt->myDoc->root))
1.102 daniel 5455: ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
1.99 daniel 5456:
5457: /*
1.2 veillard 5458: * Check for an Empty Element.
5459: */
1.40 daniel 5460: if ((CUR == '/') && (NXT(1) == '>')) {
5461: SKIP(2);
1.72 daniel 5462: if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
1.83 daniel 5463: ctxt->sax->endElement(ctxt->userData, name);
1.119 daniel 5464: xmlFree(name);
1.72 daniel 5465: return;
1.2 veillard 5466: }
1.91 daniel 5467: if (CUR == '>') {
5468: NEXT;
5469: } else {
1.55 daniel 5470: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 5471: ctxt->sax->error(ctxt->userData,
5472: "Couldn't find end of Start Tag\n%.30s\n",
1.57 daniel 5473: openTag);
1.59 daniel 5474: ctxt->wellFormed = 0;
1.123 daniel 5475: ctxt->errNo = XML_ERR_GT_REQUIRED;
1.45 daniel 5476:
5477: /*
5478: * end of parsing of this node.
5479: */
5480: nodePop(ctxt);
1.119 daniel 5481: xmlFree(name);
1.118 daniel 5482:
5483: /*
5484: * Capture end position and add node
5485: */
5486: if ( ret != NULL && ctxt->record_info ) {
5487: node_info.end_pos = ctxt->input->consumed +
5488: (CUR_PTR - ctxt->input->base);
5489: node_info.end_line = ctxt->input->line;
5490: node_info.node = ret;
5491: xmlParserAddNodeInfo(ctxt, &node_info);
5492: }
1.72 daniel 5493: return;
1.2 veillard 5494: }
5495:
5496: /*
5497: * Parse the content of the element:
5498: */
1.45 daniel 5499: xmlParseContent(ctxt);
1.40 daniel 5500: if (!IS_CHAR(CUR)) {
1.55 daniel 5501: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5502: ctxt->sax->error(ctxt->userData,
1.57 daniel 5503: "Premature end of data in tag %.30s\n", openTag);
1.59 daniel 5504: ctxt->wellFormed = 0;
1.123 daniel 5505: ctxt->errNo = XML_ERR_TAG_NOT_FINISED;
1.45 daniel 5506:
5507: /*
5508: * end of parsing of this node.
5509: */
5510: nodePop(ctxt);
1.119 daniel 5511: xmlFree(name);
1.72 daniel 5512: return;
1.2 veillard 5513: }
5514:
5515: /*
1.27 daniel 5516: * parse the end of tag: '</' should be here.
1.2 veillard 5517: */
1.83 daniel 5518: xmlParseEndTag(ctxt, name);
1.119 daniel 5519: xmlFree(name);
1.118 daniel 5520:
5521: /*
5522: * Capture end position and add node
5523: */
5524: if ( ret != NULL && ctxt->record_info ) {
5525: node_info.end_pos = ctxt->input->consumed +
5526: (CUR_PTR - ctxt->input->base);
5527: node_info.end_line = ctxt->input->line;
5528: node_info.node = ret;
5529: xmlParserAddNodeInfo(ctxt, &node_info);
5530: }
1.2 veillard 5531: }
5532:
1.50 daniel 5533: /**
5534: * xmlParseVersionNum:
5535: * @ctxt: an XML parser context
5536: *
5537: * parse the XML version value.
1.29 daniel 5538: *
5539: * [26] VersionNum ::= ([a-zA-Z0-9_.:] | '-')+
1.68 daniel 5540: *
5541: * Returns the string giving the XML version number, or NULL
1.29 daniel 5542: */
1.123 daniel 5543: xmlChar *
1.55 daniel 5544: xmlParseVersionNum(xmlParserCtxtPtr ctxt) {
1.123 daniel 5545: const xmlChar *q = CUR_PTR;
5546: xmlChar *ret;
1.29 daniel 5547:
1.40 daniel 5548: while (IS_CHAR(CUR) &&
5549: (((CUR >= 'a') && (CUR <= 'z')) ||
5550: ((CUR >= 'A') && (CUR <= 'Z')) ||
5551: ((CUR >= '0') && (CUR <= '9')) ||
5552: (CUR == '_') || (CUR == '.') ||
5553: (CUR == ':') || (CUR == '-'))) NEXT;
5554: ret = xmlStrndup(q, CUR_PTR - q);
1.29 daniel 5555: return(ret);
5556: }
5557:
1.50 daniel 5558: /**
5559: * xmlParseVersionInfo:
5560: * @ctxt: an XML parser context
5561: *
5562: * parse the XML version.
1.29 daniel 5563: *
5564: * [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
5565: *
5566: * [25] Eq ::= S? '=' S?
1.50 daniel 5567: *
1.68 daniel 5568: * Returns the version string, e.g. "1.0"
1.29 daniel 5569: */
5570:
1.123 daniel 5571: xmlChar *
1.55 daniel 5572: xmlParseVersionInfo(xmlParserCtxtPtr ctxt) {
1.123 daniel 5573: xmlChar *version = NULL;
5574: const xmlChar *q;
1.29 daniel 5575:
1.40 daniel 5576: if ((CUR == 'v') && (NXT(1) == 'e') &&
5577: (NXT(2) == 'r') && (NXT(3) == 's') &&
5578: (NXT(4) == 'i') && (NXT(5) == 'o') &&
5579: (NXT(6) == 'n')) {
5580: SKIP(7);
1.42 daniel 5581: SKIP_BLANKS;
1.40 daniel 5582: if (CUR != '=') {
1.55 daniel 5583: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 5584: ctxt->sax->error(ctxt->userData,
5585: "xmlParseVersionInfo : expected '='\n");
1.59 daniel 5586: ctxt->wellFormed = 0;
1.123 daniel 5587: ctxt->errNo = XML_ERR_EQUAL_REQUIRED;
1.31 daniel 5588: return(NULL);
5589: }
1.40 daniel 5590: NEXT;
1.42 daniel 5591: SKIP_BLANKS;
1.40 daniel 5592: if (CUR == '"') {
5593: NEXT;
5594: q = CUR_PTR;
1.29 daniel 5595: version = xmlParseVersionNum(ctxt);
1.55 daniel 5596: if (CUR != '"') {
5597: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 5598: ctxt->sax->error(ctxt->userData,
5599: "String not closed\n%.50s\n", q);
1.59 daniel 5600: ctxt->wellFormed = 0;
1.123 daniel 5601: ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
1.55 daniel 5602: } else
1.40 daniel 5603: NEXT;
5604: } else if (CUR == '\''){
5605: NEXT;
5606: q = CUR_PTR;
1.29 daniel 5607: version = xmlParseVersionNum(ctxt);
1.55 daniel 5608: if (CUR != '\'') {
5609: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 5610: ctxt->sax->error(ctxt->userData,
5611: "String not closed\n%.50s\n", q);
1.123 daniel 5612: ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
1.59 daniel 5613: ctxt->wellFormed = 0;
1.55 daniel 5614: } else
1.40 daniel 5615: NEXT;
1.31 daniel 5616: } else {
1.55 daniel 5617: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5618: ctxt->sax->error(ctxt->userData,
1.59 daniel 5619: "xmlParseVersionInfo : expected ' or \"\n");
1.122 daniel 5620: ctxt->wellFormed = 0;
1.123 daniel 5621: ctxt->errNo = XML_ERR_STRING_NOT_STARTED;
1.29 daniel 5622: }
5623: }
5624: return(version);
5625: }
5626:
1.50 daniel 5627: /**
5628: * xmlParseEncName:
5629: * @ctxt: an XML parser context
5630: *
5631: * parse the XML encoding name
1.29 daniel 5632: *
5633: * [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
1.50 daniel 5634: *
1.68 daniel 5635: * Returns the encoding name value or NULL
1.29 daniel 5636: */
1.123 daniel 5637: xmlChar *
1.55 daniel 5638: xmlParseEncName(xmlParserCtxtPtr ctxt) {
1.123 daniel 5639: const xmlChar *q = CUR_PTR;
5640: xmlChar *ret = NULL;
1.29 daniel 5641:
1.40 daniel 5642: if (((CUR >= 'a') && (CUR <= 'z')) ||
5643: ((CUR >= 'A') && (CUR <= 'Z'))) {
5644: NEXT;
5645: while (IS_CHAR(CUR) &&
5646: (((CUR >= 'a') && (CUR <= 'z')) ||
5647: ((CUR >= 'A') && (CUR <= 'Z')) ||
5648: ((CUR >= '0') && (CUR <= '9')) ||
5649: (CUR == '-'))) NEXT;
5650: ret = xmlStrndup(q, CUR_PTR - q);
1.29 daniel 5651: } else {
1.55 daniel 5652: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5653: ctxt->sax->error(ctxt->userData, "Invalid XML encoding name\n");
1.59 daniel 5654: ctxt->wellFormed = 0;
1.123 daniel 5655: ctxt->errNo = XML_ERR_ENCODING_NAME;
1.29 daniel 5656: }
5657: return(ret);
5658: }
5659:
1.50 daniel 5660: /**
5661: * xmlParseEncodingDecl:
5662: * @ctxt: an XML parser context
5663: *
5664: * parse the XML encoding declaration
1.29 daniel 5665: *
5666: * [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'")
1.50 daniel 5667: *
5668: * TODO: this should setup the conversion filters.
5669: *
1.68 daniel 5670: * Returns the encoding value or NULL
1.29 daniel 5671: */
5672:
1.123 daniel 5673: xmlChar *
1.55 daniel 5674: xmlParseEncodingDecl(xmlParserCtxtPtr ctxt) {
1.123 daniel 5675: xmlChar *encoding = NULL;
5676: const xmlChar *q;
1.29 daniel 5677:
1.42 daniel 5678: SKIP_BLANKS;
1.40 daniel 5679: if ((CUR == 'e') && (NXT(1) == 'n') &&
5680: (NXT(2) == 'c') && (NXT(3) == 'o') &&
5681: (NXT(4) == 'd') && (NXT(5) == 'i') &&
5682: (NXT(6) == 'n') && (NXT(7) == 'g')) {
5683: SKIP(8);
1.42 daniel 5684: SKIP_BLANKS;
1.40 daniel 5685: if (CUR != '=') {
1.55 daniel 5686: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 5687: ctxt->sax->error(ctxt->userData,
5688: "xmlParseEncodingDecl : expected '='\n");
1.59 daniel 5689: ctxt->wellFormed = 0;
1.123 daniel 5690: ctxt->errNo = XML_ERR_EQUAL_REQUIRED;
1.31 daniel 5691: return(NULL);
5692: }
1.40 daniel 5693: NEXT;
1.42 daniel 5694: SKIP_BLANKS;
1.40 daniel 5695: if (CUR == '"') {
5696: NEXT;
5697: q = CUR_PTR;
1.29 daniel 5698: encoding = xmlParseEncName(ctxt);
1.55 daniel 5699: if (CUR != '"') {
5700: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 5701: ctxt->sax->error(ctxt->userData,
5702: "String not closed\n%.50s\n", q);
1.59 daniel 5703: ctxt->wellFormed = 0;
1.123 daniel 5704: ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
1.55 daniel 5705: } else
1.40 daniel 5706: NEXT;
5707: } else if (CUR == '\''){
5708: NEXT;
5709: q = CUR_PTR;
1.29 daniel 5710: encoding = xmlParseEncName(ctxt);
1.55 daniel 5711: if (CUR != '\'') {
5712: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 5713: ctxt->sax->error(ctxt->userData,
5714: "String not closed\n%.50s\n", q);
1.59 daniel 5715: ctxt->wellFormed = 0;
1.123 daniel 5716: ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
1.55 daniel 5717: } else
1.40 daniel 5718: NEXT;
5719: } else if (CUR == '"'){
1.55 daniel 5720: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5721: ctxt->sax->error(ctxt->userData,
1.59 daniel 5722: "xmlParseEncodingDecl : expected ' or \"\n");
5723: ctxt->wellFormed = 0;
1.123 daniel 5724: ctxt->errNo = XML_ERR_STRING_NOT_STARTED;
1.29 daniel 5725: }
5726: }
5727: return(encoding);
5728: }
5729:
1.50 daniel 5730: /**
5731: * xmlParseSDDecl:
5732: * @ctxt: an XML parser context
5733: *
5734: * parse the XML standalone declaration
1.29 daniel 5735: *
5736: * [32] SDDecl ::= S 'standalone' Eq
5737: * (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no')'"'))
1.99 daniel 5738: *
5739: * [ VC: Standalone Document Declaration ]
5740: * TODO The standalone document declaration must have the value "no"
5741: * if any external markup declarations contain declarations of:
5742: * - attributes with default values, if elements to which these
5743: * attributes apply appear in the document without specifications
5744: * of values for these attributes, or
5745: * - entities (other than amp, lt, gt, apos, quot), if references
5746: * to those entities appear in the document, or
5747: * - attributes with values subject to normalization, where the
5748: * attribute appears in the document with a value which will change
5749: * as a result of normalization, or
5750: * - element types with element content, if white space occurs directly
5751: * within any instance of those types.
1.68 daniel 5752: *
5753: * Returns 1 if standalone, 0 otherwise
1.29 daniel 5754: */
5755:
1.55 daniel 5756: int
5757: xmlParseSDDecl(xmlParserCtxtPtr ctxt) {
1.29 daniel 5758: int standalone = -1;
5759:
1.42 daniel 5760: SKIP_BLANKS;
1.40 daniel 5761: if ((CUR == 's') && (NXT(1) == 't') &&
5762: (NXT(2) == 'a') && (NXT(3) == 'n') &&
5763: (NXT(4) == 'd') && (NXT(5) == 'a') &&
5764: (NXT(6) == 'l') && (NXT(7) == 'o') &&
5765: (NXT(8) == 'n') && (NXT(9) == 'e')) {
5766: SKIP(10);
1.81 daniel 5767: SKIP_BLANKS;
1.40 daniel 5768: if (CUR != '=') {
1.55 daniel 5769: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5770: ctxt->sax->error(ctxt->userData,
1.59 daniel 5771: "XML standalone declaration : expected '='\n");
1.123 daniel 5772: ctxt->errNo = XML_ERR_EQUAL_REQUIRED;
1.59 daniel 5773: ctxt->wellFormed = 0;
1.32 daniel 5774: return(standalone);
5775: }
1.40 daniel 5776: NEXT;
1.42 daniel 5777: SKIP_BLANKS;
1.40 daniel 5778: if (CUR == '\''){
5779: NEXT;
5780: if ((CUR == 'n') && (NXT(1) == 'o')) {
1.29 daniel 5781: standalone = 0;
1.40 daniel 5782: SKIP(2);
5783: } else if ((CUR == 'y') && (NXT(1) == 'e') &&
5784: (NXT(2) == 's')) {
1.29 daniel 5785: standalone = 1;
1.40 daniel 5786: SKIP(3);
1.29 daniel 5787: } else {
1.55 daniel 5788: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 5789: ctxt->sax->error(ctxt->userData,
5790: "standalone accepts only 'yes' or 'no'\n");
1.123 daniel 5791: ctxt->errNo = XML_ERR_STANDALONE_VALUE;
1.59 daniel 5792: ctxt->wellFormed = 0;
1.29 daniel 5793: }
1.55 daniel 5794: if (CUR != '\'') {
5795: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5796: ctxt->sax->error(ctxt->userData, "String not closed\n");
1.123 daniel 5797: ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
1.59 daniel 5798: ctxt->wellFormed = 0;
1.55 daniel 5799: } else
1.40 daniel 5800: NEXT;
5801: } else if (CUR == '"'){
5802: NEXT;
5803: if ((CUR == 'n') && (NXT(1) == 'o')) {
1.29 daniel 5804: standalone = 0;
1.40 daniel 5805: SKIP(2);
5806: } else if ((CUR == 'y') && (NXT(1) == 'e') &&
5807: (NXT(2) == 's')) {
1.29 daniel 5808: standalone = 1;
1.40 daniel 5809: SKIP(3);
1.29 daniel 5810: } else {
1.55 daniel 5811: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5812: ctxt->sax->error(ctxt->userData,
1.59 daniel 5813: "standalone accepts only 'yes' or 'no'\n");
1.123 daniel 5814: ctxt->errNo = XML_ERR_STANDALONE_VALUE;
1.59 daniel 5815: ctxt->wellFormed = 0;
1.29 daniel 5816: }
1.55 daniel 5817: if (CUR != '"') {
5818: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5819: ctxt->sax->error(ctxt->userData, "String not closed\n");
1.59 daniel 5820: ctxt->wellFormed = 0;
1.123 daniel 5821: ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
1.55 daniel 5822: } else
1.40 daniel 5823: NEXT;
1.37 daniel 5824: } else {
1.55 daniel 5825: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 5826: ctxt->sax->error(ctxt->userData,
5827: "Standalone value not found\n");
1.59 daniel 5828: ctxt->wellFormed = 0;
1.123 daniel 5829: ctxt->errNo = XML_ERR_STRING_NOT_STARTED;
1.37 daniel 5830: }
1.29 daniel 5831: }
5832: return(standalone);
5833: }
5834:
1.50 daniel 5835: /**
5836: * xmlParseXMLDecl:
5837: * @ctxt: an XML parser context
5838: *
5839: * parse an XML declaration header
1.29 daniel 5840: *
5841: * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
1.1 veillard 5842: */
5843:
1.55 daniel 5844: void
5845: xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
1.123 daniel 5846: xmlChar *version;
1.1 veillard 5847:
5848: /*
1.19 daniel 5849: * We know that '<?xml' is here.
1.1 veillard 5850: */
1.40 daniel 5851: SKIP(5);
1.1 veillard 5852:
1.59 daniel 5853: if (!IS_BLANK(CUR)) {
5854: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5855: ctxt->sax->error(ctxt->userData, "Blank needed after '<?xml'\n");
1.123 daniel 5856: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 5857: ctxt->wellFormed = 0;
5858: }
1.42 daniel 5859: SKIP_BLANKS;
1.1 veillard 5860:
5861: /*
1.29 daniel 5862: * We should have the VersionInfo here.
1.1 veillard 5863: */
1.29 daniel 5864: version = xmlParseVersionInfo(ctxt);
5865: if (version == NULL)
1.45 daniel 5866: version = xmlCharStrdup(XML_DEFAULT_VERSION);
1.72 daniel 5867: ctxt->version = xmlStrdup(version);
1.119 daniel 5868: xmlFree(version);
1.29 daniel 5869:
5870: /*
5871: * We may have the encoding declaration
5872: */
1.59 daniel 5873: if (!IS_BLANK(CUR)) {
5874: if ((CUR == '?') && (NXT(1) == '>')) {
5875: SKIP(2);
5876: return;
5877: }
5878: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5879: ctxt->sax->error(ctxt->userData, "Blank needed here\n");
1.123 daniel 5880: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 5881: ctxt->wellFormed = 0;
5882: }
1.72 daniel 5883: ctxt->encoding = xmlParseEncodingDecl(ctxt);
1.1 veillard 5884:
5885: /*
1.29 daniel 5886: * We may have the standalone status.
1.1 veillard 5887: */
1.72 daniel 5888: if ((ctxt->encoding != NULL) && (!IS_BLANK(CUR))) {
1.59 daniel 5889: if ((CUR == '?') && (NXT(1) == '>')) {
5890: SKIP(2);
5891: return;
5892: }
5893: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5894: ctxt->sax->error(ctxt->userData, "Blank needed here\n");
1.59 daniel 5895: ctxt->wellFormed = 0;
1.123 daniel 5896: ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59 daniel 5897: }
5898: SKIP_BLANKS;
1.72 daniel 5899: ctxt->standalone = xmlParseSDDecl(ctxt);
1.1 veillard 5900:
1.42 daniel 5901: SKIP_BLANKS;
1.40 daniel 5902: if ((CUR == '?') && (NXT(1) == '>')) {
5903: SKIP(2);
5904: } else if (CUR == '>') {
1.31 daniel 5905: /* Deprecated old WD ... */
1.55 daniel 5906: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 5907: ctxt->sax->error(ctxt->userData,
5908: "XML declaration must end-up with '?>'\n");
1.59 daniel 5909: ctxt->wellFormed = 0;
1.123 daniel 5910: ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
1.40 daniel 5911: NEXT;
1.29 daniel 5912: } else {
1.55 daniel 5913: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122 daniel 5914: ctxt->sax->error(ctxt->userData,
5915: "parsing XML declaration: '?>' expected\n");
1.59 daniel 5916: ctxt->wellFormed = 0;
1.123 daniel 5917: ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
1.40 daniel 5918: MOVETO_ENDTAG(CUR_PTR);
5919: NEXT;
1.29 daniel 5920: }
1.1 veillard 5921: }
5922:
1.50 daniel 5923: /**
5924: * xmlParseMisc:
5925: * @ctxt: an XML parser context
5926: *
5927: * parse an XML Misc* optionnal field.
1.21 daniel 5928: *
1.22 daniel 5929: * [27] Misc ::= Comment | PI | S
1.1 veillard 5930: */
5931:
1.55 daniel 5932: void
5933: xmlParseMisc(xmlParserCtxtPtr ctxt) {
1.40 daniel 5934: while (((CUR == '<') && (NXT(1) == '?')) ||
5935: ((CUR == '<') && (NXT(1) == '!') &&
5936: (NXT(2) == '-') && (NXT(3) == '-')) ||
5937: IS_BLANK(CUR)) {
5938: if ((CUR == '<') && (NXT(1) == '?')) {
1.16 daniel 5939: xmlParsePI(ctxt);
1.40 daniel 5940: } else if (IS_BLANK(CUR)) {
5941: NEXT;
1.1 veillard 5942: } else
1.114 daniel 5943: xmlParseComment(ctxt);
1.1 veillard 5944: }
5945: }
5946:
1.50 daniel 5947: /**
5948: * xmlParseDocument :
5949: * @ctxt: an XML parser context
5950: *
5951: * parse an XML document (and build a tree if using the standard SAX
5952: * interface).
1.21 daniel 5953: *
1.22 daniel 5954: * [1] document ::= prolog element Misc*
1.29 daniel 5955: *
5956: * [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
1.50 daniel 5957: *
1.68 daniel 5958: * Returns 0, -1 in case of error. the parser context is augmented
1.50 daniel 5959: * as a result of the parsing.
1.1 veillard 5960: */
5961:
1.55 daniel 5962: int
5963: xmlParseDocument(xmlParserCtxtPtr ctxt) {
1.45 daniel 5964: xmlDefaultSAXHandlerInit();
5965:
1.91 daniel 5966: GROW;
5967:
1.14 veillard 5968: /*
1.44 daniel 5969: * SAX: beginning of the document processing.
5970: */
1.72 daniel 5971: if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
1.74 daniel 5972: ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
1.44 daniel 5973:
5974: /*
1.117 daniel 5975: * TODO We should check for encoding here and plug-in some
5976: * conversion code !!!!
1.14 veillard 5977: */
1.1 veillard 5978:
5979: /*
5980: * Wipe out everything which is before the first '<'
5981: */
1.59 daniel 5982: if (IS_BLANK(CUR)) {
5983: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5984: ctxt->sax->error(ctxt->userData,
1.59 daniel 5985: "Extra spaces at the beginning of the document are not allowed\n");
1.123 daniel 5986: ctxt->errNo = XML_ERR_DOCUMENT_START;
1.59 daniel 5987: ctxt->wellFormed = 0;
5988: SKIP_BLANKS;
5989: }
5990:
5991: if (CUR == 0) {
5992: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 5993: ctxt->sax->error(ctxt->userData, "Document is empty\n");
1.123 daniel 5994: ctxt->errNo = XML_ERR_DOCUMENT_EMPTY;
1.59 daniel 5995: ctxt->wellFormed = 0;
5996: }
1.1 veillard 5997:
5998: /*
5999: * Check for the XMLDecl in the Prolog.
6000: */
1.91 daniel 6001: GROW;
1.40 daniel 6002: if ((CUR == '<') && (NXT(1) == '?') &&
6003: (NXT(2) == 'x') && (NXT(3) == 'm') &&
6004: (NXT(4) == 'l')) {
1.19 daniel 6005: xmlParseXMLDecl(ctxt);
6006: /* SKIP_EOL(cur); */
1.42 daniel 6007: SKIP_BLANKS;
1.40 daniel 6008: } else if ((CUR == '<') && (NXT(1) == '?') &&
6009: (NXT(2) == 'X') && (NXT(3) == 'M') &&
6010: (NXT(4) == 'L')) {
1.19 daniel 6011: /*
6012: * The first drafts were using <?XML and the final W3C REC
6013: * now use <?xml ...
6014: */
1.16 daniel 6015: xmlParseXMLDecl(ctxt);
1.1 veillard 6016: /* SKIP_EOL(cur); */
1.42 daniel 6017: SKIP_BLANKS;
1.1 veillard 6018: } else {
1.72 daniel 6019: ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
1.1 veillard 6020: }
1.72 daniel 6021: if ((ctxt->sax) && (ctxt->sax->startDocument))
1.74 daniel 6022: ctxt->sax->startDocument(ctxt->userData);
1.1 veillard 6023:
6024: /*
6025: * The Misc part of the Prolog
6026: */
1.91 daniel 6027: GROW;
1.16 daniel 6028: xmlParseMisc(ctxt);
1.1 veillard 6029:
6030: /*
1.29 daniel 6031: * Then possibly doc type declaration(s) and more Misc
1.21 daniel 6032: * (doctypedecl Misc*)?
6033: */
1.91 daniel 6034: GROW;
1.40 daniel 6035: if ((CUR == '<') && (NXT(1) == '!') &&
6036: (NXT(2) == 'D') && (NXT(3) == 'O') &&
6037: (NXT(4) == 'C') && (NXT(5) == 'T') &&
6038: (NXT(6) == 'Y') && (NXT(7) == 'P') &&
6039: (NXT(8) == 'E')) {
1.22 daniel 6040: xmlParseDocTypeDecl(ctxt);
1.96 daniel 6041: ctxt->instate = XML_PARSER_PROLOG;
1.22 daniel 6042: xmlParseMisc(ctxt);
1.21 daniel 6043: }
6044:
6045: /*
6046: * Time to start parsing the tree itself
1.1 veillard 6047: */
1.91 daniel 6048: GROW;
1.96 daniel 6049: ctxt->instate = XML_PARSER_CONTENT;
1.72 daniel 6050: xmlParseElement(ctxt);
1.96 daniel 6051: ctxt->instate = XML_PARSER_EPILOG;
1.33 daniel 6052:
6053: /*
6054: * The Misc part at the end
6055: */
6056: xmlParseMisc(ctxt);
1.16 daniel 6057:
1.59 daniel 6058: if (CUR != 0) {
6059: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 6060: ctxt->sax->error(ctxt->userData,
1.59 daniel 6061: "Extra content at the end of the document\n");
6062: ctxt->wellFormed = 0;
1.123 daniel 6063: ctxt->errNo = XML_ERR_DOCUMENT_END;
1.59 daniel 6064: }
1.96 daniel 6065: ctxt->instate = XML_PARSER_EOF;
1.59 daniel 6066:
1.44 daniel 6067: /*
6068: * SAX: end of the document processing.
6069: */
1.72 daniel 6070: if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
1.74 daniel 6071: ctxt->sax->endDocument(ctxt->userData);
1.59 daniel 6072: if (! ctxt->wellFormed) return(-1);
1.16 daniel 6073: return(0);
6074: }
6075:
1.98 daniel 6076: /************************************************************************
6077: * *
1.128 daniel 6078: * Progressive parsing interfaces *
6079: * *
6080: ************************************************************************/
6081:
6082: /**
6083: * xmlParseLookupSequence:
6084: * @ctxt: an XML parser context
6085: * @first: the first char to lookup
6086: * @next: the next char to lookup
6087: *
6088: * Try to find if a sequence (first, next) or just (first) if next
6089: * is zero is available in the input stream.
6090: * Since XML-1.0 is an LALR(2) grammar a sequence of 2 char should be
6091: * enought. If this doesn't prove true this function call may change.
6092: *
6093: * Returns 1 if the full sequence is available, 0 otherwise.
6094: */
6095: int
6096: xmlParseLookupSequence(xmlParserCtxtPtr ctxt, xmlChar first, xmlChar next) {
6097: return(0);
6098: }
6099:
6100: /**
6101: * xmlParseTry:
6102: * @ctxt: an XML parser context
6103: *
6104: * Try to progress on parsing
6105: *
6106: * Returns zero if no parsing was possible
6107: */
6108: int
6109: xmlParseTry(xmlParserCtxtPtr ctxt) {
6110: int ret = 0;
6111:
6112: while (1) {
6113: switch (ctxt->instate) {
6114: case XML_PARSER_EOF:
6115: return(0);
6116: case XML_PARSER_PROLOG:
6117: case XML_PARSER_CONTENT:
6118: case XML_PARSER_ENTITY_DECL:
6119: case XML_PARSER_ENTITY_VALUE:
6120: case XML_PARSER_ATTRIBUTE_VALUE:
6121: case XML_PARSER_DTD:
6122: case XML_PARSER_EPILOG:
6123: case XML_PARSER_COMMENT:
6124: case XML_PARSER_CDATA_SECTION:
6125: }
6126: }
6127: return(ret);
6128: }
6129:
6130: /**
6131: * xmlParseChunk:
6132: * @ctxt: an XML parser context
6133: * @chunk: an char array
6134: * @size: the size in byte of the chunk
6135: * @terminate: last chunk indicator
6136: *
6137: * Parse a Chunk of memory
6138: *
6139: * Returns zero if no error, the xmlParserErrors otherwise.
6140: */
6141: xmlParserErrors
6142: xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
6143: int terminate) {
6144: if ((size > 0) && (chunk != NULL)) {
6145: xmlParserInputBufferPush(ctxt->input, size, chunk);
6146: }
6147: return((xmlParserErrors) ctxt->errNo);
6148: }
6149:
6150: /************************************************************************
6151: * *
1.98 daniel 6152: * I/O front end functions to the parser *
6153: * *
6154: ************************************************************************/
6155:
1.50 daniel 6156: /**
1.86 daniel 6157: * xmlCreateDocParserCtxt :
1.123 daniel 6158: * @cur: a pointer to an array of xmlChar
1.50 daniel 6159: *
1.69 daniel 6160: * Create a parser context for an XML in-memory document.
6161: *
6162: * Returns the new parser context or NULL
1.16 daniel 6163: */
1.69 daniel 6164: xmlParserCtxtPtr
1.123 daniel 6165: xmlCreateDocParserCtxt(xmlChar *cur) {
1.16 daniel 6166: xmlParserCtxtPtr ctxt;
1.40 daniel 6167: xmlParserInputPtr input;
1.75 daniel 6168: xmlCharEncoding enc;
1.16 daniel 6169:
1.97 daniel 6170: ctxt = xmlNewParserCtxt();
1.16 daniel 6171: if (ctxt == NULL) {
6172: return(NULL);
6173: }
1.96 daniel 6174: input = xmlNewInputStream(ctxt);
1.40 daniel 6175: if (input == NULL) {
1.97 daniel 6176: xmlFreeParserCtxt(ctxt);
1.40 daniel 6177: return(NULL);
6178: }
6179:
1.75 daniel 6180: /*
6181: * plug some encoding conversion routines here. !!!
6182: */
6183: enc = xmlDetectCharEncoding(cur);
6184: xmlSwitchEncoding(ctxt, enc);
6185:
1.40 daniel 6186: input->base = cur;
6187: input->cur = cur;
6188:
6189: inputPush(ctxt, input);
1.69 daniel 6190: return(ctxt);
6191: }
6192:
6193: /**
6194: * xmlSAXParseDoc :
6195: * @sax: the SAX handler block
1.123 daniel 6196: * @cur: a pointer to an array of xmlChar
1.69 daniel 6197: * @recovery: work in recovery mode, i.e. tries to read no Well Formed
6198: * documents
6199: *
6200: * parse an XML in-memory document and build a tree.
6201: * It use the given SAX function block to handle the parsing callback.
6202: * If sax is NULL, fallback to the default DOM tree building routines.
6203: *
6204: * Returns the resulting document tree
6205: */
6206:
6207: xmlDocPtr
1.123 daniel 6208: xmlSAXParseDoc(xmlSAXHandlerPtr sax, xmlChar *cur, int recovery) {
1.69 daniel 6209: xmlDocPtr ret;
6210: xmlParserCtxtPtr ctxt;
6211:
6212: if (cur == NULL) return(NULL);
1.16 daniel 6213:
6214:
1.69 daniel 6215: ctxt = xmlCreateDocParserCtxt(cur);
6216: if (ctxt == NULL) return(NULL);
1.74 daniel 6217: if (sax != NULL) {
6218: ctxt->sax = sax;
6219: ctxt->userData = NULL;
6220: }
1.69 daniel 6221:
1.16 daniel 6222: xmlParseDocument(ctxt);
1.72 daniel 6223: if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
1.59 daniel 6224: else {
6225: ret = NULL;
1.72 daniel 6226: xmlFreeDoc(ctxt->myDoc);
6227: ctxt->myDoc = NULL;
1.59 daniel 6228: }
1.86 daniel 6229: if (sax != NULL)
6230: ctxt->sax = NULL;
1.69 daniel 6231: xmlFreeParserCtxt(ctxt);
1.16 daniel 6232:
1.1 veillard 6233: return(ret);
6234: }
6235:
1.50 daniel 6236: /**
1.55 daniel 6237: * xmlParseDoc :
1.123 daniel 6238: * @cur: a pointer to an array of xmlChar
1.55 daniel 6239: *
6240: * parse an XML in-memory document and build a tree.
6241: *
1.68 daniel 6242: * Returns the resulting document tree
1.55 daniel 6243: */
6244:
1.69 daniel 6245: xmlDocPtr
1.123 daniel 6246: xmlParseDoc(xmlChar *cur) {
1.59 daniel 6247: return(xmlSAXParseDoc(NULL, cur, 0));
1.76 daniel 6248: }
6249:
6250: /**
6251: * xmlSAXParseDTD :
6252: * @sax: the SAX handler block
6253: * @ExternalID: a NAME* containing the External ID of the DTD
6254: * @SystemID: a NAME* containing the URL to the DTD
6255: *
6256: * Load and parse an external subset.
6257: *
6258: * Returns the resulting xmlDtdPtr or NULL in case of error.
6259: */
6260:
6261: xmlDtdPtr
1.123 daniel 6262: xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID,
6263: const xmlChar *SystemID) {
1.76 daniel 6264: xmlDtdPtr ret = NULL;
6265: xmlParserCtxtPtr ctxt;
1.83 daniel 6266: xmlParserInputPtr input = NULL;
1.76 daniel 6267: xmlCharEncoding enc;
6268:
6269: if ((ExternalID == NULL) && (SystemID == NULL)) return(NULL);
6270:
1.97 daniel 6271: ctxt = xmlNewParserCtxt();
1.76 daniel 6272: if (ctxt == NULL) {
6273: return(NULL);
6274: }
6275:
6276: /*
6277: * Set-up the SAX context
6278: */
6279: if (ctxt == NULL) return(NULL);
6280: if (sax != NULL) {
1.93 veillard 6281: if (ctxt->sax != NULL)
1.119 daniel 6282: xmlFree(ctxt->sax);
1.76 daniel 6283: ctxt->sax = sax;
6284: ctxt->userData = NULL;
6285: }
6286:
6287: /*
6288: * Ask the Entity resolver to load the damn thing
6289: */
6290:
6291: if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
6292: input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID, SystemID);
6293: if (input == NULL) {
1.86 daniel 6294: if (sax != NULL) ctxt->sax = NULL;
1.76 daniel 6295: xmlFreeParserCtxt(ctxt);
6296: return(NULL);
6297: }
6298:
6299: /*
6300: * plug some encoding conversion routines here. !!!
6301: */
6302: xmlPushInput(ctxt, input);
6303: enc = xmlDetectCharEncoding(ctxt->input->cur);
6304: xmlSwitchEncoding(ctxt, enc);
6305:
1.95 veillard 6306: if (input->filename == NULL)
1.116 daniel 6307: input->filename = (char *) xmlStrdup(SystemID); /* !!!!!!! */
1.76 daniel 6308: input->line = 1;
6309: input->col = 1;
6310: input->base = ctxt->input->cur;
6311: input->cur = ctxt->input->cur;
6312: input->free = NULL;
6313:
6314: /*
6315: * let's parse that entity knowing it's an external subset.
6316: */
1.79 daniel 6317: xmlParseExternalSubset(ctxt, ExternalID, SystemID);
1.76 daniel 6318:
6319: if (ctxt->myDoc != NULL) {
6320: if (ctxt->wellFormed) {
6321: ret = ctxt->myDoc->intSubset;
6322: ctxt->myDoc->intSubset = NULL;
6323: } else {
6324: ret = NULL;
6325: }
6326: xmlFreeDoc(ctxt->myDoc);
6327: ctxt->myDoc = NULL;
6328: }
1.86 daniel 6329: if (sax != NULL) ctxt->sax = NULL;
1.76 daniel 6330: xmlFreeParserCtxt(ctxt);
6331:
6332: return(ret);
6333: }
6334:
6335: /**
6336: * xmlParseDTD :
6337: * @ExternalID: a NAME* containing the External ID of the DTD
6338: * @SystemID: a NAME* containing the URL to the DTD
6339: *
6340: * Load and parse an external subset.
6341: *
6342: * Returns the resulting xmlDtdPtr or NULL in case of error.
6343: */
6344:
6345: xmlDtdPtr
1.123 daniel 6346: xmlParseDTD(const xmlChar *ExternalID, const xmlChar *SystemID) {
1.76 daniel 6347: return(xmlSAXParseDTD(NULL, ExternalID, SystemID));
1.59 daniel 6348: }
6349:
6350: /**
6351: * xmlRecoverDoc :
1.123 daniel 6352: * @cur: a pointer to an array of xmlChar
1.59 daniel 6353: *
6354: * parse an XML in-memory document and build a tree.
6355: * In the case the document is not Well Formed, a tree is built anyway
6356: *
1.68 daniel 6357: * Returns the resulting document tree
1.59 daniel 6358: */
6359:
1.69 daniel 6360: xmlDocPtr
1.123 daniel 6361: xmlRecoverDoc(xmlChar *cur) {
1.59 daniel 6362: return(xmlSAXParseDoc(NULL, cur, 1));
1.55 daniel 6363: }
6364:
6365: /**
1.69 daniel 6366: * xmlCreateFileParserCtxt :
1.50 daniel 6367: * @filename: the filename
6368: *
1.69 daniel 6369: * Create a parser context for a file content.
6370: * Automatic support for ZLIB/Compress compressed document is provided
6371: * by default if found at compile-time.
1.50 daniel 6372: *
1.69 daniel 6373: * Returns the new parser context or NULL
1.9 httpng 6374: */
1.69 daniel 6375: xmlParserCtxtPtr
6376: xmlCreateFileParserCtxt(const char *filename)
6377: {
6378: xmlParserCtxtPtr ctxt;
1.40 daniel 6379: xmlParserInputPtr inputStream;
1.91 daniel 6380: xmlParserInputBufferPtr buf;
1.111 daniel 6381: char *directory = NULL;
1.9 httpng 6382:
1.91 daniel 6383: buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
6384: if (buf == NULL) return(NULL);
1.9 httpng 6385:
1.97 daniel 6386: ctxt = xmlNewParserCtxt();
1.16 daniel 6387: if (ctxt == NULL) {
6388: return(NULL);
6389: }
1.97 daniel 6390:
1.96 daniel 6391: inputStream = xmlNewInputStream(ctxt);
1.40 daniel 6392: if (inputStream == NULL) {
1.97 daniel 6393: xmlFreeParserCtxt(ctxt);
1.40 daniel 6394: return(NULL);
6395: }
6396:
1.119 daniel 6397: inputStream->filename = xmlMemStrdup(filename);
1.91 daniel 6398: inputStream->buf = buf;
6399: inputStream->base = inputStream->buf->buffer->content;
6400: inputStream->cur = inputStream->buf->buffer->content;
1.16 daniel 6401:
1.40 daniel 6402: inputPush(ctxt, inputStream);
1.110 daniel 6403: if ((ctxt->directory == NULL) && (directory == NULL))
1.106 daniel 6404: directory = xmlParserGetDirectory(filename);
6405: if ((ctxt->directory == NULL) && (directory != NULL))
1.110 daniel 6406: ctxt->directory = directory;
1.106 daniel 6407:
1.69 daniel 6408: return(ctxt);
6409: }
6410:
6411: /**
6412: * xmlSAXParseFile :
6413: * @sax: the SAX handler block
6414: * @filename: the filename
6415: * @recovery: work in recovery mode, i.e. tries to read no Well Formed
6416: * documents
6417: *
6418: * parse an XML file and build a tree. Automatic support for ZLIB/Compress
6419: * compressed document is provided by default if found at compile-time.
6420: * It use the given SAX function block to handle the parsing callback.
6421: * If sax is NULL, fallback to the default DOM tree building routines.
6422: *
6423: * Returns the resulting document tree
6424: */
6425:
1.79 daniel 6426: xmlDocPtr
6427: xmlSAXParseFile(xmlSAXHandlerPtr sax, const char *filename,
1.69 daniel 6428: int recovery) {
6429: xmlDocPtr ret;
6430: xmlParserCtxtPtr ctxt;
1.111 daniel 6431: char *directory = NULL;
1.69 daniel 6432:
6433: ctxt = xmlCreateFileParserCtxt(filename);
6434: if (ctxt == NULL) return(NULL);
1.74 daniel 6435: if (sax != NULL) {
1.93 veillard 6436: if (ctxt->sax != NULL)
1.119 daniel 6437: xmlFree(ctxt->sax);
1.74 daniel 6438: ctxt->sax = sax;
6439: ctxt->userData = NULL;
6440: }
1.106 daniel 6441:
1.110 daniel 6442: if ((ctxt->directory == NULL) && (directory == NULL))
1.106 daniel 6443: directory = xmlParserGetDirectory(filename);
6444: if ((ctxt->directory == NULL) && (directory != NULL))
1.123 daniel 6445: ctxt->directory = (char *) xmlStrdup((xmlChar *) directory); /* !!!!!!! */
1.16 daniel 6446:
6447: xmlParseDocument(ctxt);
1.40 daniel 6448:
1.72 daniel 6449: if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
1.59 daniel 6450: else {
6451: ret = NULL;
1.72 daniel 6452: xmlFreeDoc(ctxt->myDoc);
6453: ctxt->myDoc = NULL;
1.59 daniel 6454: }
1.86 daniel 6455: if (sax != NULL)
6456: ctxt->sax = NULL;
1.69 daniel 6457: xmlFreeParserCtxt(ctxt);
1.20 daniel 6458:
6459: return(ret);
6460: }
6461:
1.55 daniel 6462: /**
6463: * xmlParseFile :
6464: * @filename: the filename
6465: *
6466: * parse an XML file and build a tree. Automatic support for ZLIB/Compress
6467: * compressed document is provided by default if found at compile-time.
6468: *
1.68 daniel 6469: * Returns the resulting document tree
1.55 daniel 6470: */
6471:
1.79 daniel 6472: xmlDocPtr
6473: xmlParseFile(const char *filename) {
1.59 daniel 6474: return(xmlSAXParseFile(NULL, filename, 0));
6475: }
6476:
6477: /**
6478: * xmlRecoverFile :
6479: * @filename: the filename
6480: *
6481: * parse an XML file and build a tree. Automatic support for ZLIB/Compress
6482: * compressed document is provided by default if found at compile-time.
6483: * In the case the document is not Well Formed, a tree is built anyway
6484: *
1.68 daniel 6485: * Returns the resulting document tree
1.59 daniel 6486: */
6487:
1.79 daniel 6488: xmlDocPtr
6489: xmlRecoverFile(const char *filename) {
1.59 daniel 6490: return(xmlSAXParseFile(NULL, filename, 1));
1.55 daniel 6491: }
1.32 daniel 6492:
1.50 daniel 6493: /**
1.69 daniel 6494: * xmlCreateMemoryParserCtxt :
1.68 daniel 6495: * @buffer: an pointer to a char array
1.127 daniel 6496: * @size: the size of the array
1.50 daniel 6497: *
1.69 daniel 6498: * Create a parser context for an XML in-memory document.
1.50 daniel 6499: *
1.69 daniel 6500: * Returns the new parser context or NULL
1.20 daniel 6501: */
1.69 daniel 6502: xmlParserCtxtPtr
6503: xmlCreateMemoryParserCtxt(char *buffer, int size) {
1.20 daniel 6504: xmlParserCtxtPtr ctxt;
1.40 daniel 6505: xmlParserInputPtr input;
1.75 daniel 6506: xmlCharEncoding enc;
1.40 daniel 6507:
6508: buffer[size - 1] = '\0';
6509:
1.97 daniel 6510: ctxt = xmlNewParserCtxt();
1.20 daniel 6511: if (ctxt == NULL) {
6512: return(NULL);
6513: }
1.97 daniel 6514:
1.96 daniel 6515: input = xmlNewInputStream(ctxt);
1.40 daniel 6516: if (input == NULL) {
1.97 daniel 6517: xmlFreeParserCtxt(ctxt);
1.40 daniel 6518: return(NULL);
6519: }
1.20 daniel 6520:
1.40 daniel 6521: input->filename = NULL;
6522: input->line = 1;
6523: input->col = 1;
1.96 daniel 6524: input->buf = NULL;
1.91 daniel 6525: input->consumed = 0;
1.45 daniel 6526:
6527: /*
1.75 daniel 6528: * plug some encoding conversion routines here. !!!
1.45 daniel 6529: */
1.116 daniel 6530: enc = xmlDetectCharEncoding(BAD_CAST buffer);
1.75 daniel 6531: xmlSwitchEncoding(ctxt, enc);
6532:
1.116 daniel 6533: input->base = BAD_CAST buffer;
6534: input->cur = BAD_CAST buffer;
1.69 daniel 6535: input->free = NULL;
1.20 daniel 6536:
1.40 daniel 6537: inputPush(ctxt, input);
1.69 daniel 6538: return(ctxt);
6539: }
6540:
6541: /**
6542: * xmlSAXParseMemory :
6543: * @sax: the SAX handler block
6544: * @buffer: an pointer to a char array
1.127 daniel 6545: * @size: the size of the array
6546: * @recovery: work in recovery mode, i.e. tries to read not Well Formed
1.69 daniel 6547: * documents
6548: *
6549: * parse an XML in-memory block and use the given SAX function block
6550: * to handle the parsing callback. If sax is NULL, fallback to the default
6551: * DOM tree building routines.
6552: *
6553: * Returns the resulting document tree
6554: */
6555: xmlDocPtr
6556: xmlSAXParseMemory(xmlSAXHandlerPtr sax, char *buffer, int size, int recovery) {
6557: xmlDocPtr ret;
6558: xmlParserCtxtPtr ctxt;
6559:
6560: ctxt = xmlCreateMemoryParserCtxt(buffer, size);
6561: if (ctxt == NULL) return(NULL);
1.74 daniel 6562: if (sax != NULL) {
6563: ctxt->sax = sax;
6564: ctxt->userData = NULL;
6565: }
1.20 daniel 6566:
6567: xmlParseDocument(ctxt);
1.40 daniel 6568:
1.72 daniel 6569: if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
1.59 daniel 6570: else {
6571: ret = NULL;
1.72 daniel 6572: xmlFreeDoc(ctxt->myDoc);
6573: ctxt->myDoc = NULL;
1.59 daniel 6574: }
1.86 daniel 6575: if (sax != NULL)
6576: ctxt->sax = NULL;
1.69 daniel 6577: xmlFreeParserCtxt(ctxt);
1.16 daniel 6578:
1.9 httpng 6579: return(ret);
1.17 daniel 6580: }
6581:
1.55 daniel 6582: /**
6583: * xmlParseMemory :
1.68 daniel 6584: * @buffer: an pointer to a char array
1.55 daniel 6585: * @size: the size of the array
6586: *
6587: * parse an XML in-memory block and build a tree.
6588: *
1.68 daniel 6589: * Returns the resulting document tree
1.55 daniel 6590: */
6591:
6592: xmlDocPtr xmlParseMemory(char *buffer, int size) {
1.59 daniel 6593: return(xmlSAXParseMemory(NULL, buffer, size, 0));
6594: }
6595:
6596: /**
6597: * xmlRecoverMemory :
1.68 daniel 6598: * @buffer: an pointer to a char array
1.59 daniel 6599: * @size: the size of the array
6600: *
6601: * parse an XML in-memory block and build a tree.
6602: * In the case the document is not Well Formed, a tree is built anyway
6603: *
1.68 daniel 6604: * Returns the resulting document tree
1.59 daniel 6605: */
6606:
6607: xmlDocPtr xmlRecoverMemory(char *buffer, int size) {
6608: return(xmlSAXParseMemory(NULL, buffer, size, 1));
1.17 daniel 6609: }
6610:
6611:
1.50 daniel 6612: /**
6613: * xmlSetupParserForBuffer:
6614: * @ctxt: an XML parser context
1.123 daniel 6615: * @buffer: a xmlChar * buffer
1.50 daniel 6616: * @filename: a file name
6617: *
1.19 daniel 6618: * Setup the parser context to parse a new buffer; Clears any prior
6619: * contents from the parser context. The buffer parameter must not be
6620: * NULL, but the filename parameter can be
6621: */
1.55 daniel 6622: void
1.123 daniel 6623: xmlSetupParserForBuffer(xmlParserCtxtPtr ctxt, const xmlChar* buffer,
1.17 daniel 6624: const char* filename)
6625: {
1.96 daniel 6626: xmlParserInputPtr input;
1.40 daniel 6627:
1.96 daniel 6628: input = xmlNewInputStream(ctxt);
6629: if (input == NULL) {
6630: perror("malloc");
1.119 daniel 6631: xmlFree(ctxt);
1.96 daniel 6632: exit(1);
6633: }
6634:
6635: xmlClearParserCtxt(ctxt);
6636: if (filename != NULL)
1.119 daniel 6637: input->filename = xmlMemStrdup(filename);
1.96 daniel 6638: input->base = buffer;
6639: input->cur = buffer;
6640: inputPush(ctxt, input);
1.17 daniel 6641: }
6642:
1.123 daniel 6643: /**
6644: * xmlSAXUserParseFile:
6645: * @sax: a SAX handler
6646: * @user_data: The user data returned on SAX callbacks
6647: * @filename: a file name
6648: *
6649: * parse an XML file and call the given SAX handler routines.
6650: * Automatic support for ZLIB/Compress compressed document is provided
6651: *
6652: * Returns 0 in case of success or a error number otherwise
6653: */
1.131 ! daniel 6654: int
! 6655: xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data,
! 6656: const char *filename) {
1.123 daniel 6657: int ret = 0;
6658: xmlParserCtxtPtr ctxt;
6659:
6660: ctxt = xmlCreateFileParserCtxt(filename);
6661: if (ctxt == NULL) return -1;
6662: ctxt->sax = sax;
6663: ctxt->userData = user_data;
6664:
6665: xmlParseDocument(ctxt);
6666:
6667: if (ctxt->wellFormed)
6668: ret = 0;
6669: else {
6670: if (ctxt->errNo != 0)
6671: ret = ctxt->errNo;
6672: else
6673: ret = -1;
6674: }
6675: if (sax != NULL)
6676: ctxt->sax = NULL;
6677: xmlFreeParserCtxt(ctxt);
6678:
6679: return ret;
6680: }
6681:
6682: /**
6683: * xmlSAXUserParseMemory:
6684: * @sax: a SAX handler
6685: * @user_data: The user data returned on SAX callbacks
6686: * @buffer: an in-memory XML document input
1.127 daniel 6687: * @size: the length of the XML document in bytes
1.123 daniel 6688: *
6689: * A better SAX parsing routine.
6690: * parse an XML in-memory buffer and call the given SAX handler routines.
6691: *
6692: * Returns 0 in case of success or a error number otherwise
6693: */
6694: int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data,
6695: char *buffer, int size) {
6696: int ret = 0;
6697: xmlParserCtxtPtr ctxt;
6698:
6699: ctxt = xmlCreateMemoryParserCtxt(buffer, size);
6700: if (ctxt == NULL) return -1;
6701: ctxt->sax = sax;
6702: ctxt->userData = user_data;
6703:
6704: xmlParseDocument(ctxt);
6705:
6706: if (ctxt->wellFormed)
6707: ret = 0;
6708: else {
6709: if (ctxt->errNo != 0)
6710: ret = ctxt->errNo;
6711: else
6712: ret = -1;
6713: }
6714: if (sax != NULL)
6715: ctxt->sax = NULL;
6716: xmlFreeParserCtxt(ctxt);
6717:
6718: return ret;
6719: }
6720:
1.32 daniel 6721:
1.98 daniel 6722: /************************************************************************
6723: * *
1.127 daniel 6724: * Miscellaneous *
1.98 daniel 6725: * *
6726: ************************************************************************/
6727:
6728:
1.50 daniel 6729: /**
6730: * xmlParserFindNodeInfo:
6731: * @ctxt: an XML parser context
6732: * @node: an XML node within the tree
6733: *
6734: * Find the parser node info struct for a given node
6735: *
1.68 daniel 6736: * Returns an xmlParserNodeInfo block pointer or NULL
1.32 daniel 6737: */
6738: const xmlParserNodeInfo* xmlParserFindNodeInfo(const xmlParserCtxt* ctx,
6739: const xmlNode* node)
6740: {
6741: unsigned long pos;
6742:
6743: /* Find position where node should be at */
6744: pos = xmlParserFindNodeInfoIndex(&ctx->node_seq, node);
6745: if ( ctx->node_seq.buffer[pos].node == node )
6746: return &ctx->node_seq.buffer[pos];
6747: else
6748: return NULL;
6749: }
6750:
6751:
1.50 daniel 6752: /**
6753: * xmlInitNodeInfoSeq :
6754: * @seq: a node info sequence pointer
6755: *
6756: * -- Initialize (set to initial state) node info sequence
1.32 daniel 6757: */
1.55 daniel 6758: void
6759: xmlInitNodeInfoSeq(xmlParserNodeInfoSeqPtr seq)
1.32 daniel 6760: {
6761: seq->length = 0;
6762: seq->maximum = 0;
6763: seq->buffer = NULL;
6764: }
6765:
1.50 daniel 6766: /**
6767: * xmlClearNodeInfoSeq :
6768: * @seq: a node info sequence pointer
6769: *
6770: * -- Clear (release memory and reinitialize) node
1.32 daniel 6771: * info sequence
6772: */
1.55 daniel 6773: void
6774: xmlClearNodeInfoSeq(xmlParserNodeInfoSeqPtr seq)
1.32 daniel 6775: {
6776: if ( seq->buffer != NULL )
1.119 daniel 6777: xmlFree(seq->buffer);
1.32 daniel 6778: xmlInitNodeInfoSeq(seq);
6779: }
6780:
6781:
1.50 daniel 6782: /**
6783: * xmlParserFindNodeInfoIndex:
6784: * @seq: a node info sequence pointer
6785: * @node: an XML node pointer
6786: *
6787: *
1.32 daniel 6788: * xmlParserFindNodeInfoIndex : Find the index that the info record for
6789: * the given node is or should be at in a sorted sequence
1.68 daniel 6790: *
6791: * Returns a long indicating the position of the record
1.32 daniel 6792: */
6793: unsigned long xmlParserFindNodeInfoIndex(const xmlParserNodeInfoSeq* seq,
6794: const xmlNode* node)
6795: {
6796: unsigned long upper, lower, middle;
6797: int found = 0;
6798:
6799: /* Do a binary search for the key */
6800: lower = 1;
6801: upper = seq->length;
6802: middle = 0;
6803: while ( lower <= upper && !found) {
6804: middle = lower + (upper - lower) / 2;
6805: if ( node == seq->buffer[middle - 1].node )
6806: found = 1;
6807: else if ( node < seq->buffer[middle - 1].node )
6808: upper = middle - 1;
6809: else
6810: lower = middle + 1;
6811: }
6812:
6813: /* Return position */
6814: if ( middle == 0 || seq->buffer[middle - 1].node < node )
6815: return middle;
6816: else
6817: return middle - 1;
6818: }
6819:
6820:
1.50 daniel 6821: /**
6822: * xmlParserAddNodeInfo:
6823: * @ctxt: an XML parser context
1.68 daniel 6824: * @info: a node info sequence pointer
1.50 daniel 6825: *
6826: * Insert node info record into the sorted sequence
1.32 daniel 6827: */
1.55 daniel 6828: void
6829: xmlParserAddNodeInfo(xmlParserCtxtPtr ctxt,
1.68 daniel 6830: const xmlParserNodeInfo* info)
1.32 daniel 6831: {
6832: unsigned long pos;
6833: static unsigned int block_size = 5;
6834:
6835: /* Find pos and check to see if node is already in the sequence */
1.55 daniel 6836: pos = xmlParserFindNodeInfoIndex(&ctxt->node_seq, info->node);
6837: if ( pos < ctxt->node_seq.length
6838: && ctxt->node_seq.buffer[pos].node == info->node ) {
6839: ctxt->node_seq.buffer[pos] = *info;
1.32 daniel 6840: }
6841:
6842: /* Otherwise, we need to add new node to buffer */
6843: else {
6844: /* Expand buffer by 5 if needed */
1.55 daniel 6845: if ( ctxt->node_seq.length + 1 > ctxt->node_seq.maximum ) {
1.32 daniel 6846: xmlParserNodeInfo* tmp_buffer;
1.55 daniel 6847: unsigned int byte_size = (sizeof(*ctxt->node_seq.buffer)
6848: *(ctxt->node_seq.maximum + block_size));
1.32 daniel 6849:
1.55 daniel 6850: if ( ctxt->node_seq.buffer == NULL )
1.119 daniel 6851: tmp_buffer = (xmlParserNodeInfo*) xmlMalloc(byte_size);
1.32 daniel 6852: else
1.119 daniel 6853: tmp_buffer = (xmlParserNodeInfo*) xmlRealloc(ctxt->node_seq.buffer, byte_size);
1.32 daniel 6854:
6855: if ( tmp_buffer == NULL ) {
1.55 daniel 6856: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74 daniel 6857: ctxt->sax->error(ctxt->userData, "Out of memory\n");
1.123 daniel 6858: ctxt->errNo = XML_ERR_NO_MEMORY;
1.32 daniel 6859: return;
6860: }
1.55 daniel 6861: ctxt->node_seq.buffer = tmp_buffer;
6862: ctxt->node_seq.maximum += block_size;
1.32 daniel 6863: }
6864:
6865: /* If position is not at end, move elements out of the way */
1.55 daniel 6866: if ( pos != ctxt->node_seq.length ) {
1.32 daniel 6867: unsigned long i;
6868:
1.55 daniel 6869: for ( i = ctxt->node_seq.length; i > pos; i-- )
6870: ctxt->node_seq.buffer[i] = ctxt->node_seq.buffer[i - 1];
1.32 daniel 6871: }
6872:
6873: /* Copy element and increase length */
1.55 daniel 6874: ctxt->node_seq.buffer[pos] = *info;
6875: ctxt->node_seq.length++;
1.32 daniel 6876: }
6877: }
1.77 daniel 6878:
1.98 daniel 6879:
6880: /**
6881: * xmlSubstituteEntitiesDefault :
6882: * @val: int 0 or 1
6883: *
6884: * Set and return the previous value for default entity support.
6885: * Initially the parser always keep entity references instead of substituting
6886: * entity values in the output. This function has to be used to change the
6887: * default parser behaviour
6888: * SAX::subtituteEntities() has to be used for changing that on a file by
6889: * file basis.
6890: *
6891: * Returns the last value for 0 for no substitution, 1 for substitution.
6892: */
6893:
6894: int
6895: xmlSubstituteEntitiesDefault(int val) {
6896: int old = xmlSubstituteEntitiesDefaultValue;
6897:
6898: xmlSubstituteEntitiesDefaultValue = val;
6899: return(old);
6900: }
1.77 daniel 6901:
Webmaster