Annotation of embedaddon/libxml2/SAX2.c, revision 1.1.1.2
1.1 misho 1: /*
2: * SAX2.c : Default SAX2 handler to build a tree.
3: *
4: * See Copyright for the status of this software.
5: *
6: * Daniel Veillard <daniel@veillard.com>
7: */
8:
9:
10: #define IN_LIBXML
11: #include "libxml.h"
12: #include <stdlib.h>
13: #include <string.h>
14: #include <limits.h>
15: #include <libxml/xmlmemory.h>
16: #include <libxml/tree.h>
17: #include <libxml/parser.h>
18: #include <libxml/parserInternals.h>
19: #include <libxml/valid.h>
20: #include <libxml/entities.h>
21: #include <libxml/xmlerror.h>
22: #include <libxml/debugXML.h>
23: #include <libxml/xmlIO.h>
24: #include <libxml/SAX.h>
25: #include <libxml/uri.h>
26: #include <libxml/valid.h>
27: #include <libxml/HTMLtree.h>
28: #include <libxml/globals.h>
29:
30: /* Define SIZE_T_MAX unless defined through <limits.h>. */
31: #ifndef SIZE_T_MAX
32: # define SIZE_T_MAX ((size_t)-1)
33: #endif /* !SIZE_T_MAX */
34:
35: /* #define DEBUG_SAX2 */
36: /* #define DEBUG_SAX2_TREE */
37:
38: /**
39: * TODO:
40: *
41: * macro to flag unimplemented blocks
42: * XML_CATALOG_PREFER user env to select between system/public prefered
43: * option. C.f. Richard Tobin <richard@cogsci.ed.ac.uk>
44: *> Just FYI, I am using an environment variable XML_CATALOG_PREFER with
45: *> values "system" and "public". I have made the default be "system" to
46: *> match yours.
47: */
48: #define TODO \
49: xmlGenericError(xmlGenericErrorContext, \
50: "Unimplemented block at %s:%d\n", \
51: __FILE__, __LINE__);
52:
53: /*
54: * xmlSAX2ErrMemory:
55: * @ctxt: an XML validation parser context
56: * @msg: a string to accompany the error message
57: */
58: static void
59: xmlSAX2ErrMemory(xmlParserCtxtPtr ctxt, const char *msg) {
60: if (ctxt != NULL) {
61: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
62: ctxt->sax->error(ctxt->userData, "%s: out of memory\n", msg);
63: ctxt->errNo = XML_ERR_NO_MEMORY;
64: ctxt->instate = XML_PARSER_EOF;
65: ctxt->disableSAX = 1;
66: }
67: }
68:
69: /**
70: * xmlValidError:
71: * @ctxt: an XML validation parser context
72: * @error: the error number
73: * @msg: the error message
74: * @str1: extra data
75: * @str2: extra data
76: *
77: * Handle a validation error
78: */
79: static void
80: xmlErrValid(xmlParserCtxtPtr ctxt, xmlParserErrors error,
81: const char *msg, const char *str1, const char *str2)
82: {
83: xmlStructuredErrorFunc schannel = NULL;
84:
85: if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
86: (ctxt->instate == XML_PARSER_EOF))
87: return;
88: if (ctxt != NULL) {
89: ctxt->errNo = error;
90: if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
91: schannel = ctxt->sax->serror;
92: __xmlRaiseError(schannel,
93: ctxt->vctxt.error, ctxt->vctxt.userData,
94: ctxt, NULL, XML_FROM_DTD, error,
95: XML_ERR_ERROR, NULL, 0, (const char *) str1,
96: (const char *) str2, NULL, 0, 0,
97: msg, (const char *) str1, (const char *) str2);
98: ctxt->valid = 0;
99: } else {
100: __xmlRaiseError(schannel,
101: NULL, NULL,
102: ctxt, NULL, XML_FROM_DTD, error,
103: XML_ERR_ERROR, NULL, 0, (const char *) str1,
104: (const char *) str2, NULL, 0, 0,
105: msg, (const char *) str1, (const char *) str2);
106: }
107: }
108:
109: /**
110: * xmlFatalErrMsg:
111: * @ctxt: an XML parser context
112: * @error: the error number
113: * @msg: the error message
114: * @str1: an error string
115: * @str2: an error string
116: *
117: * Handle a fatal parser error, i.e. violating Well-Formedness constraints
118: */
119: static void
120: xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
121: const char *msg, const xmlChar *str1, const xmlChar *str2)
122: {
123: if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
124: (ctxt->instate == XML_PARSER_EOF))
125: return;
126: if (ctxt != NULL)
127: ctxt->errNo = error;
128: __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
129: XML_ERR_FATAL, NULL, 0,
130: (const char *) str1, (const char *) str2,
131: NULL, 0, 0, msg, str1, str2);
132: if (ctxt != NULL) {
133: ctxt->wellFormed = 0;
134: ctxt->valid = 0;
135: if (ctxt->recovery == 0)
136: ctxt->disableSAX = 1;
137: }
138: }
139:
140: /**
141: * xmlWarnMsg:
142: * @ctxt: an XML parser context
143: * @error: the error number
144: * @msg: the error message
145: * @str1: an error string
146: * @str2: an error string
147: *
148: * Handle a parser warning
149: */
150: static void
151: xmlWarnMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
152: const char *msg, const xmlChar *str1)
153: {
154: if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
155: (ctxt->instate == XML_PARSER_EOF))
156: return;
157: if (ctxt != NULL)
158: ctxt->errNo = error;
159: __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
160: XML_ERR_WARNING, NULL, 0,
161: (const char *) str1, NULL,
162: NULL, 0, 0, msg, str1);
163: }
164:
165: /**
166: * xmlNsErrMsg:
167: * @ctxt: an XML parser context
168: * @error: the error number
169: * @msg: the error message
170: * @str1: an error string
171: * @str2: an error string
172: *
173: * Handle a namespace error
174: */
175: static void
176: xmlNsErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
177: const char *msg, const xmlChar *str1, const xmlChar *str2)
178: {
179: if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
180: (ctxt->instate == XML_PARSER_EOF))
181: return;
182: if (ctxt != NULL)
183: ctxt->errNo = error;
184: __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
185: XML_ERR_ERROR, NULL, 0,
186: (const char *) str1, (const char *) str2,
187: NULL, 0, 0, msg, str1, str2);
188: }
189:
190: /**
191: * xmlNsWarnMsg:
192: * @ctxt: an XML parser context
193: * @error: the error number
194: * @msg: the error message
195: * @str1: an error string
196: *
197: * Handle a namespace warning
198: */
199: static void
200: xmlNsWarnMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
201: const char *msg, const xmlChar *str1, const xmlChar *str2)
202: {
203: if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
204: (ctxt->instate == XML_PARSER_EOF))
205: return;
206: if (ctxt != NULL)
207: ctxt->errNo = error;
208: __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
209: XML_ERR_WARNING, NULL, 0,
210: (const char *) str1, (const char *) str2,
211: NULL, 0, 0, msg, str1, str2);
212: }
213:
214: /**
215: * xmlSAX2GetPublicId:
216: * @ctx: the user data (XML parser context)
217: *
218: * Provides the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
219: *
220: * Returns a xmlChar *
221: */
222: const xmlChar *
223: xmlSAX2GetPublicId(void *ctx ATTRIBUTE_UNUSED)
224: {
225: /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
226: return(NULL);
227: }
228:
229: /**
230: * xmlSAX2GetSystemId:
231: * @ctx: the user data (XML parser context)
232: *
233: * Provides the system ID, basically URL or filename e.g.
234: * http://www.sgmlsource.com/dtds/memo.dtd
235: *
236: * Returns a xmlChar *
237: */
238: const xmlChar *
239: xmlSAX2GetSystemId(void *ctx)
240: {
241: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
242: if ((ctx == NULL) || (ctxt->input == NULL)) return(NULL);
243: return((const xmlChar *) ctxt->input->filename);
244: }
245:
246: /**
247: * xmlSAX2GetLineNumber:
248: * @ctx: the user data (XML parser context)
249: *
250: * Provide the line number of the current parsing point.
251: *
252: * Returns an int
253: */
254: int
255: xmlSAX2GetLineNumber(void *ctx)
256: {
257: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
258: if ((ctx == NULL) || (ctxt->input == NULL)) return(0);
259: return(ctxt->input->line);
260: }
261:
262: /**
263: * xmlSAX2GetColumnNumber:
264: * @ctx: the user data (XML parser context)
265: *
266: * Provide the column number of the current parsing point.
267: *
268: * Returns an int
269: */
270: int
271: xmlSAX2GetColumnNumber(void *ctx)
272: {
273: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
274: if ((ctx == NULL) || (ctxt->input == NULL)) return(0);
275: return(ctxt->input->col);
276: }
277:
278: /**
279: * xmlSAX2IsStandalone:
280: * @ctx: the user data (XML parser context)
281: *
282: * Is this document tagged standalone ?
283: *
284: * Returns 1 if true
285: */
286: int
287: xmlSAX2IsStandalone(void *ctx)
288: {
289: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
290: if ((ctx == NULL) || (ctxt->myDoc == NULL)) return(0);
291: return(ctxt->myDoc->standalone == 1);
292: }
293:
294: /**
295: * xmlSAX2HasInternalSubset:
296: * @ctx: the user data (XML parser context)
297: *
298: * Does this document has an internal subset
299: *
300: * Returns 1 if true
301: */
302: int
303: xmlSAX2HasInternalSubset(void *ctx)
304: {
305: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
306: if ((ctxt == NULL) || (ctxt->myDoc == NULL)) return(0);
307: return(ctxt->myDoc->intSubset != NULL);
308: }
309:
310: /**
311: * xmlSAX2HasExternalSubset:
312: * @ctx: the user data (XML parser context)
313: *
314: * Does this document has an external subset
315: *
316: * Returns 1 if true
317: */
318: int
319: xmlSAX2HasExternalSubset(void *ctx)
320: {
321: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
322: if ((ctxt == NULL) || (ctxt->myDoc == NULL)) return(0);
323: return(ctxt->myDoc->extSubset != NULL);
324: }
325:
326: /**
327: * xmlSAX2InternalSubset:
328: * @ctx: the user data (XML parser context)
329: * @name: the root element name
330: * @ExternalID: the external ID
331: * @SystemID: the SYSTEM ID (e.g. filename or URL)
332: *
333: * Callback on internal subset declaration.
334: */
335: void
336: xmlSAX2InternalSubset(void *ctx, const xmlChar *name,
337: const xmlChar *ExternalID, const xmlChar *SystemID)
338: {
339: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
340: xmlDtdPtr dtd;
341: if (ctx == NULL) return;
342: #ifdef DEBUG_SAX
343: xmlGenericError(xmlGenericErrorContext,
344: "SAX.xmlSAX2InternalSubset(%s, %s, %s)\n",
345: name, ExternalID, SystemID);
346: #endif
347:
348: if (ctxt->myDoc == NULL)
349: return;
350: dtd = xmlGetIntSubset(ctxt->myDoc);
351: if (dtd != NULL) {
352: if (ctxt->html)
353: return;
354: xmlUnlinkNode((xmlNodePtr) dtd);
355: xmlFreeDtd(dtd);
356: ctxt->myDoc->intSubset = NULL;
357: }
358: ctxt->myDoc->intSubset =
359: xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
360: if (ctxt->myDoc->intSubset == NULL)
361: xmlSAX2ErrMemory(ctxt, "xmlSAX2InternalSubset");
362: }
363:
364: /**
365: * xmlSAX2ExternalSubset:
366: * @ctx: the user data (XML parser context)
367: * @name: the root element name
368: * @ExternalID: the external ID
369: * @SystemID: the SYSTEM ID (e.g. filename or URL)
370: *
371: * Callback on external subset declaration.
372: */
373: void
374: xmlSAX2ExternalSubset(void *ctx, const xmlChar *name,
375: const xmlChar *ExternalID, const xmlChar *SystemID)
376: {
377: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
378: if (ctx == NULL) return;
379: #ifdef DEBUG_SAX
380: xmlGenericError(xmlGenericErrorContext,
381: "SAX.xmlSAX2ExternalSubset(%s, %s, %s)\n",
382: name, ExternalID, SystemID);
383: #endif
384: if (((ExternalID != NULL) || (SystemID != NULL)) &&
385: (((ctxt->validate) || (ctxt->loadsubset != 0)) &&
386: (ctxt->wellFormed && ctxt->myDoc))) {
387: /*
388: * Try to fetch and parse the external subset.
389: */
390: xmlParserInputPtr oldinput;
391: int oldinputNr;
392: int oldinputMax;
393: xmlParserInputPtr *oldinputTab;
394: xmlParserInputPtr input = NULL;
395: xmlCharEncoding enc;
396: int oldcharset;
397:
398: /*
399: * Ask the Entity resolver to load the damn thing
400: */
401: if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
402: input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
403: SystemID);
404: if (input == NULL) {
405: return;
406: }
407:
408: xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
409:
410: /*
411: * make sure we won't destroy the main document context
412: */
413: oldinput = ctxt->input;
414: oldinputNr = ctxt->inputNr;
415: oldinputMax = ctxt->inputMax;
416: oldinputTab = ctxt->inputTab;
417: oldcharset = ctxt->charset;
418:
419: ctxt->inputTab = (xmlParserInputPtr *)
420: xmlMalloc(5 * sizeof(xmlParserInputPtr));
421: if (ctxt->inputTab == NULL) {
422: xmlSAX2ErrMemory(ctxt, "xmlSAX2ExternalSubset");
423: ctxt->input = oldinput;
424: ctxt->inputNr = oldinputNr;
425: ctxt->inputMax = oldinputMax;
426: ctxt->inputTab = oldinputTab;
427: ctxt->charset = oldcharset;
428: return;
429: }
430: ctxt->inputNr = 0;
431: ctxt->inputMax = 5;
432: ctxt->input = NULL;
433: xmlPushInput(ctxt, input);
434:
435: /*
436: * On the fly encoding conversion if needed
437: */
438: if (ctxt->input->length >= 4) {
439: enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
440: xmlSwitchEncoding(ctxt, enc);
441: }
442:
443: if (input->filename == NULL)
444: input->filename = (char *) xmlCanonicPath(SystemID);
445: input->line = 1;
446: input->col = 1;
447: input->base = ctxt->input->cur;
448: input->cur = ctxt->input->cur;
449: input->free = NULL;
450:
451: /*
452: * let's parse that entity knowing it's an external subset.
453: */
454: xmlParseExternalSubset(ctxt, ExternalID, SystemID);
455:
456: /*
457: * Free up the external entities
458: */
459:
460: while (ctxt->inputNr > 1)
461: xmlPopInput(ctxt);
462: xmlFreeInputStream(ctxt->input);
463: xmlFree(ctxt->inputTab);
464:
465: /*
466: * Restore the parsing context of the main entity
467: */
468: ctxt->input = oldinput;
469: ctxt->inputNr = oldinputNr;
470: ctxt->inputMax = oldinputMax;
471: ctxt->inputTab = oldinputTab;
472: ctxt->charset = oldcharset;
473: /* ctxt->wellFormed = oldwellFormed; */
474: }
475: }
476:
477: /**
478: * xmlSAX2ResolveEntity:
479: * @ctx: the user data (XML parser context)
480: * @publicId: The public ID of the entity
481: * @systemId: The system ID of the entity
482: *
483: * The entity loader, to control the loading of external entities,
484: * the application can either:
485: * - override this xmlSAX2ResolveEntity() callback in the SAX block
486: * - or better use the xmlSetExternalEntityLoader() function to
487: * set up it's own entity resolution routine
488: *
489: * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
490: */
491: xmlParserInputPtr
492: xmlSAX2ResolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
493: {
494: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
495: xmlParserInputPtr ret;
496: xmlChar *URI;
497: const char *base = NULL;
498:
499: if (ctx == NULL) return(NULL);
500: if (ctxt->input != NULL)
501: base = ctxt->input->filename;
502: if (base == NULL)
503: base = ctxt->directory;
504:
505: URI = xmlBuildURI(systemId, (const xmlChar *) base);
506:
507: #ifdef DEBUG_SAX
508: xmlGenericError(xmlGenericErrorContext,
509: "SAX.xmlSAX2ResolveEntity(%s, %s)\n", publicId, systemId);
510: #endif
511:
512: ret = xmlLoadExternalEntity((const char *) URI,
513: (const char *) publicId, ctxt);
514: if (URI != NULL)
515: xmlFree(URI);
516: return(ret);
517: }
518:
519: /**
520: * xmlSAX2GetEntity:
521: * @ctx: the user data (XML parser context)
522: * @name: The entity name
523: *
524: * Get an entity by name
525: *
526: * Returns the xmlEntityPtr if found.
527: */
528: xmlEntityPtr
529: xmlSAX2GetEntity(void *ctx, const xmlChar *name)
530: {
531: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
532: xmlEntityPtr ret = NULL;
533:
534: if (ctx == NULL) return(NULL);
535: #ifdef DEBUG_SAX
536: xmlGenericError(xmlGenericErrorContext,
537: "SAX.xmlSAX2GetEntity(%s)\n", name);
538: #endif
539:
540: if (ctxt->inSubset == 0) {
541: ret = xmlGetPredefinedEntity(name);
542: if (ret != NULL)
543: return(ret);
544: }
545: if ((ctxt->myDoc != NULL) && (ctxt->myDoc->standalone == 1)) {
546: if (ctxt->inSubset == 2) {
547: ctxt->myDoc->standalone = 0;
548: ret = xmlGetDocEntity(ctxt->myDoc, name);
549: ctxt->myDoc->standalone = 1;
550: } else {
551: ret = xmlGetDocEntity(ctxt->myDoc, name);
552: if (ret == NULL) {
553: ctxt->myDoc->standalone = 0;
554: ret = xmlGetDocEntity(ctxt->myDoc, name);
555: if (ret != NULL) {
556: xmlFatalErrMsg(ctxt, XML_ERR_NOT_STANDALONE,
557: "Entity(%s) document marked standalone but requires external subset\n",
558: name, NULL);
559: }
560: ctxt->myDoc->standalone = 1;
561: }
562: }
563: } else {
564: ret = xmlGetDocEntity(ctxt->myDoc, name);
565: }
566: if ((ret != NULL) &&
567: ((ctxt->validate) || (ctxt->replaceEntities)) &&
568: (ret->children == NULL) &&
569: (ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
570: int val;
571:
572: /*
573: * for validation purposes we really need to fetch and
574: * parse the external entity
575: */
576: xmlNodePtr children;
577:
578: val = xmlParseCtxtExternalEntity(ctxt, ret->URI,
579: ret->ExternalID, &children);
580: if (val == 0) {
581: xmlAddChildList((xmlNodePtr) ret, children);
582: } else {
583: xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_PROCESSING,
584: "Failure to process entity %s\n", name, NULL);
585: ctxt->validate = 0;
586: return(NULL);
587: }
588: ret->owner = 1;
589: if (ret->checked == 0)
590: ret->checked = 1;
591: }
592: return(ret);
593: }
594:
595: /**
596: * xmlSAX2GetParameterEntity:
597: * @ctx: the user data (XML parser context)
598: * @name: The entity name
599: *
600: * Get a parameter entity by name
601: *
602: * Returns the xmlEntityPtr if found.
603: */
604: xmlEntityPtr
605: xmlSAX2GetParameterEntity(void *ctx, const xmlChar *name)
606: {
607: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
608: xmlEntityPtr ret;
609:
610: if (ctx == NULL) return(NULL);
611: #ifdef DEBUG_SAX
612: xmlGenericError(xmlGenericErrorContext,
613: "SAX.xmlSAX2GetParameterEntity(%s)\n", name);
614: #endif
615:
616: ret = xmlGetParameterEntity(ctxt->myDoc, name);
617: return(ret);
618: }
619:
620:
621: /**
622: * xmlSAX2EntityDecl:
623: * @ctx: the user data (XML parser context)
624: * @name: the entity name
625: * @type: the entity type
626: * @publicId: The public ID of the entity
627: * @systemId: The system ID of the entity
628: * @content: the entity value (without processing).
629: *
630: * An entity definition has been parsed
631: */
632: void
633: xmlSAX2EntityDecl(void *ctx, const xmlChar *name, int type,
634: const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
635: {
636: xmlEntityPtr ent;
637: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
638:
639: if (ctx == NULL) return;
640: #ifdef DEBUG_SAX
641: xmlGenericError(xmlGenericErrorContext,
642: "SAX.xmlSAX2EntityDecl(%s, %d, %s, %s, %s)\n",
643: name, type, publicId, systemId, content);
644: #endif
645: if (ctxt->inSubset == 1) {
646: ent = xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
647: systemId, content);
648: if ((ent == NULL) && (ctxt->pedantic))
649: xmlWarnMsg(ctxt, XML_WAR_ENTITY_REDEFINED,
650: "Entity(%s) already defined in the internal subset\n",
651: name);
652: if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
653: xmlChar *URI;
654: const char *base = NULL;
655:
656: if (ctxt->input != NULL)
657: base = ctxt->input->filename;
658: if (base == NULL)
659: base = ctxt->directory;
660:
661: URI = xmlBuildURI(systemId, (const xmlChar *) base);
662: ent->URI = URI;
663: }
664: } else if (ctxt->inSubset == 2) {
665: ent = xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
666: systemId, content);
667: if ((ent == NULL) && (ctxt->pedantic) &&
668: (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
669: ctxt->sax->warning(ctxt->userData,
670: "Entity(%s) already defined in the external subset\n", name);
671: if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
672: xmlChar *URI;
673: const char *base = NULL;
674:
675: if (ctxt->input != NULL)
676: base = ctxt->input->filename;
677: if (base == NULL)
678: base = ctxt->directory;
679:
680: URI = xmlBuildURI(systemId, (const xmlChar *) base);
681: ent->URI = URI;
682: }
683: } else {
684: xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_PROCESSING,
685: "SAX.xmlSAX2EntityDecl(%s) called while not in subset\n",
686: name, NULL);
687: }
688: }
689:
690: /**
691: * xmlSAX2AttributeDecl:
692: * @ctx: the user data (XML parser context)
693: * @elem: the name of the element
694: * @fullname: the attribute name
695: * @type: the attribute type
696: * @def: the type of default value
697: * @defaultValue: the attribute default value
698: * @tree: the tree of enumerated value set
699: *
700: * An attribute definition has been parsed
701: */
702: void
703: xmlSAX2AttributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
704: int type, int def, const xmlChar *defaultValue,
705: xmlEnumerationPtr tree)
706: {
707: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
708: xmlAttributePtr attr;
709: xmlChar *name = NULL, *prefix = NULL;
710:
711: if ((ctxt == NULL) || (ctxt->myDoc == NULL))
712: return;
713:
714: #ifdef DEBUG_SAX
715: xmlGenericError(xmlGenericErrorContext,
716: "SAX.xmlSAX2AttributeDecl(%s, %s, %d, %d, %s, ...)\n",
717: elem, fullname, type, def, defaultValue);
718: #endif
719: if ((xmlStrEqual(fullname, BAD_CAST "xml:id")) &&
720: (type != XML_ATTRIBUTE_ID)) {
721: /*
722: * Raise the error but keep the validity flag
723: */
724: int tmp = ctxt->valid;
725: xmlErrValid(ctxt, XML_DTD_XMLID_TYPE,
726: "xml:id : attribute type should be ID\n", NULL, NULL);
727: ctxt->valid = tmp;
728: }
729: /* TODO: optimize name/prefix allocation */
730: name = xmlSplitQName(ctxt, fullname, &prefix);
731: ctxt->vctxt.valid = 1;
732: if (ctxt->inSubset == 1)
733: attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
734: name, prefix, (xmlAttributeType) type,
735: (xmlAttributeDefault) def, defaultValue, tree);
736: else if (ctxt->inSubset == 2)
737: attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
738: name, prefix, (xmlAttributeType) type,
739: (xmlAttributeDefault) def, defaultValue, tree);
740: else {
741: xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
742: "SAX.xmlSAX2AttributeDecl(%s) called while not in subset\n",
743: name, NULL);
744: xmlFreeEnumeration(tree);
745: return;
746: }
747: #ifdef LIBXML_VALID_ENABLED
748: if (ctxt->vctxt.valid == 0)
749: ctxt->valid = 0;
750: if ((attr != NULL) && (ctxt->validate) && (ctxt->wellFormed) &&
751: (ctxt->myDoc->intSubset != NULL))
752: ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
753: attr);
754: #endif /* LIBXML_VALID_ENABLED */
755: if (prefix != NULL)
756: xmlFree(prefix);
757: if (name != NULL)
758: xmlFree(name);
759: }
760:
761: /**
762: * xmlSAX2ElementDecl:
763: * @ctx: the user data (XML parser context)
764: * @name: the element name
765: * @type: the element type
766: * @content: the element value tree
767: *
768: * An element definition has been parsed
769: */
770: void
771: xmlSAX2ElementDecl(void *ctx, const xmlChar * name, int type,
772: xmlElementContentPtr content)
773: {
774: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
775: xmlElementPtr elem = NULL;
776:
777: if ((ctxt == NULL) || (ctxt->myDoc == NULL))
778: return;
779:
780: #ifdef DEBUG_SAX
781: xmlGenericError(xmlGenericErrorContext,
782: "SAX.xmlSAX2ElementDecl(%s, %d, ...)\n", name, type);
783: #endif
784:
785: if (ctxt->inSubset == 1)
786: elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
787: name, (xmlElementTypeVal) type, content);
788: else if (ctxt->inSubset == 2)
789: elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
790: name, (xmlElementTypeVal) type, content);
791: else {
792: xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
793: "SAX.xmlSAX2ElementDecl(%s) called while not in subset\n",
794: name, NULL);
795: return;
796: }
797: #ifdef LIBXML_VALID_ENABLED
798: if (elem == NULL)
799: ctxt->valid = 0;
800: if (ctxt->validate && ctxt->wellFormed &&
801: ctxt->myDoc && ctxt->myDoc->intSubset)
802: ctxt->valid &=
803: xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
804: #endif /* LIBXML_VALID_ENABLED */
805: }
806:
807: /**
808: * xmlSAX2NotationDecl:
809: * @ctx: the user data (XML parser context)
810: * @name: The name of the notation
811: * @publicId: The public ID of the entity
812: * @systemId: The system ID of the entity
813: *
814: * What to do when a notation declaration has been parsed.
815: */
816: void
817: xmlSAX2NotationDecl(void *ctx, const xmlChar *name,
818: const xmlChar *publicId, const xmlChar *systemId)
819: {
820: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
821: xmlNotationPtr nota = NULL;
822:
823: if ((ctxt == NULL) || (ctxt->myDoc == NULL))
824: return;
825:
826: #ifdef DEBUG_SAX
827: xmlGenericError(xmlGenericErrorContext,
828: "SAX.xmlSAX2NotationDecl(%s, %s, %s)\n", name, publicId, systemId);
829: #endif
830:
831: if ((publicId == NULL) && (systemId == NULL)) {
832: xmlFatalErrMsg(ctxt, XML_ERR_NOTATION_PROCESSING,
833: "SAX.xmlSAX2NotationDecl(%s) externalID or PublicID missing\n",
834: name, NULL);
835: return;
836: } else if (ctxt->inSubset == 1)
837: nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
838: publicId, systemId);
839: else if (ctxt->inSubset == 2)
840: nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, name,
841: publicId, systemId);
842: else {
843: xmlFatalErrMsg(ctxt, XML_ERR_NOTATION_PROCESSING,
844: "SAX.xmlSAX2NotationDecl(%s) called while not in subset\n",
845: name, NULL);
846: return;
847: }
848: #ifdef LIBXML_VALID_ENABLED
849: if (nota == NULL) ctxt->valid = 0;
850: if ((ctxt->validate) && (ctxt->wellFormed) &&
851: (ctxt->myDoc->intSubset != NULL))
852: ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
853: nota);
854: #endif /* LIBXML_VALID_ENABLED */
855: }
856:
857: /**
858: * xmlSAX2UnparsedEntityDecl:
859: * @ctx: the user data (XML parser context)
860: * @name: The name of the entity
861: * @publicId: The public ID of the entity
862: * @systemId: The system ID of the entity
863: * @notationName: the name of the notation
864: *
865: * What to do when an unparsed entity declaration is parsed
866: */
867: void
868: xmlSAX2UnparsedEntityDecl(void *ctx, const xmlChar *name,
869: const xmlChar *publicId, const xmlChar *systemId,
870: const xmlChar *notationName)
871: {
872: xmlEntityPtr ent;
873: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
874: if (ctx == NULL) return;
875: #ifdef DEBUG_SAX
876: xmlGenericError(xmlGenericErrorContext,
877: "SAX.xmlSAX2UnparsedEntityDecl(%s, %s, %s, %s)\n",
878: name, publicId, systemId, notationName);
879: #endif
880: if (ctxt->inSubset == 1) {
881: ent = xmlAddDocEntity(ctxt->myDoc, name,
882: XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
883: publicId, systemId, notationName);
884: if ((ent == NULL) && (ctxt->pedantic) &&
885: (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
886: ctxt->sax->warning(ctxt->userData,
887: "Entity(%s) already defined in the internal subset\n", name);
888: if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
889: xmlChar *URI;
890: const char *base = NULL;
891:
892: if (ctxt->input != NULL)
893: base = ctxt->input->filename;
894: if (base == NULL)
895: base = ctxt->directory;
896:
897: URI = xmlBuildURI(systemId, (const xmlChar *) base);
898: ent->URI = URI;
899: }
900: } else if (ctxt->inSubset == 2) {
901: ent = xmlAddDtdEntity(ctxt->myDoc, name,
902: XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
903: publicId, systemId, notationName);
904: if ((ent == NULL) && (ctxt->pedantic) &&
905: (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
906: ctxt->sax->warning(ctxt->userData,
907: "Entity(%s) already defined in the external subset\n", name);
908: if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
909: xmlChar *URI;
910: const char *base = NULL;
911:
912: if (ctxt->input != NULL)
913: base = ctxt->input->filename;
914: if (base == NULL)
915: base = ctxt->directory;
916:
917: URI = xmlBuildURI(systemId, (const xmlChar *) base);
918: ent->URI = URI;
919: }
920: } else {
921: xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
922: "SAX.xmlSAX2UnparsedEntityDecl(%s) called while not in subset\n",
923: name, NULL);
924: }
925: }
926:
927: /**
928: * xmlSAX2SetDocumentLocator:
929: * @ctx: the user data (XML parser context)
930: * @loc: A SAX Locator
931: *
932: * Receive the document locator at startup, actually xmlDefaultSAXLocator
933: * Everything is available on the context, so this is useless in our case.
934: */
935: void
936: xmlSAX2SetDocumentLocator(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
937: {
938: /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
939: #ifdef DEBUG_SAX
940: xmlGenericError(xmlGenericErrorContext,
941: "SAX.xmlSAX2SetDocumentLocator()\n");
942: #endif
943: }
944:
945: /**
946: * xmlSAX2StartDocument:
947: * @ctx: the user data (XML parser context)
948: *
949: * called when the document start being processed.
950: */
951: void
952: xmlSAX2StartDocument(void *ctx)
953: {
954: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
955: xmlDocPtr doc;
956:
957: if (ctx == NULL) return;
958:
959: #ifdef DEBUG_SAX
960: xmlGenericError(xmlGenericErrorContext,
961: "SAX.xmlSAX2StartDocument()\n");
962: #endif
963: if (ctxt->html) {
964: #ifdef LIBXML_HTML_ENABLED
965: if (ctxt->myDoc == NULL)
966: ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
967: ctxt->myDoc->properties = XML_DOC_HTML;
968: ctxt->myDoc->parseFlags = ctxt->options;
969: if (ctxt->myDoc == NULL) {
970: xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
971: return;
972: }
973: #else
974: xmlGenericError(xmlGenericErrorContext,
975: "libxml2 built without HTML support\n");
976: ctxt->errNo = XML_ERR_INTERNAL_ERROR;
977: ctxt->instate = XML_PARSER_EOF;
978: ctxt->disableSAX = 1;
979: return;
980: #endif
981: } else {
982: doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
983: if (doc != NULL) {
984: doc->properties = 0;
985: if (ctxt->options & XML_PARSE_OLD10)
986: doc->properties |= XML_DOC_OLD10;
987: doc->parseFlags = ctxt->options;
988: if (ctxt->encoding != NULL)
989: doc->encoding = xmlStrdup(ctxt->encoding);
990: else
991: doc->encoding = NULL;
992: doc->standalone = ctxt->standalone;
993: } else {
994: xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
995: return;
996: }
997: if ((ctxt->dictNames) && (doc != NULL)) {
998: doc->dict = ctxt->dict;
999: xmlDictReference(doc->dict);
1000: }
1001: }
1002: if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
1003: (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
1004: ctxt->myDoc->URL = xmlPathToURI((const xmlChar *)ctxt->input->filename);
1005: if (ctxt->myDoc->URL == NULL)
1006: xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
1007: }
1008: }
1009:
1010: /**
1011: * xmlSAX2EndDocument:
1012: * @ctx: the user data (XML parser context)
1013: *
1014: * called when the document end has been detected.
1015: */
1016: void
1017: xmlSAX2EndDocument(void *ctx)
1018: {
1019: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1020: #ifdef DEBUG_SAX
1021: xmlGenericError(xmlGenericErrorContext,
1022: "SAX.xmlSAX2EndDocument()\n");
1023: #endif
1024: if (ctx == NULL) return;
1025: #ifdef LIBXML_VALID_ENABLED
1026: if (ctxt->validate && ctxt->wellFormed &&
1027: ctxt->myDoc && ctxt->myDoc->intSubset)
1028: ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
1029: #endif /* LIBXML_VALID_ENABLED */
1030:
1031: /*
1032: * Grab the encoding if it was added on-the-fly
1033: */
1034: if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
1035: (ctxt->myDoc->encoding == NULL)) {
1036: ctxt->myDoc->encoding = ctxt->encoding;
1037: ctxt->encoding = NULL;
1038: }
1039: if ((ctxt->inputTab != NULL) &&
1040: (ctxt->inputNr > 0) && (ctxt->inputTab[0] != NULL) &&
1041: (ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
1042: (ctxt->myDoc->encoding == NULL)) {
1043: ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
1044: }
1045: if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
1046: (ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
1047: ctxt->myDoc->charset = ctxt->charset;
1048: }
1049: }
1050:
1051: #if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_DOCB_ENABLED)
1052: /**
1053: * xmlSAX2AttributeInternal:
1054: * @ctx: the user data (XML parser context)
1055: * @fullname: The attribute name, including namespace prefix
1056: * @value: The attribute value
1057: * @prefix: the prefix on the element node
1058: *
1059: * Handle an attribute that has been read by the parser.
1060: * The default handling is to convert the attribute into an
1061: * DOM subtree and past it in a new xmlAttr element added to
1062: * the element.
1063: */
1064: static void
1065: xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
1066: const xmlChar *value, const xmlChar *prefix ATTRIBUTE_UNUSED)
1067: {
1068: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1069: xmlAttrPtr ret;
1070: xmlChar *name;
1071: xmlChar *ns;
1072: xmlChar *nval;
1073: xmlNsPtr namespace;
1074:
1075: if (ctxt->html) {
1076: name = xmlStrdup(fullname);
1077: ns = NULL;
1078: namespace = NULL;
1079: } else {
1080: /*
1081: * Split the full name into a namespace prefix and the tag name
1082: */
1083: name = xmlSplitQName(ctxt, fullname, &ns);
1084: if ((name != NULL) && (name[0] == 0)) {
1085: if (xmlStrEqual(ns, BAD_CAST "xmlns")) {
1086: xmlNsErrMsg(ctxt, XML_ERR_NS_DECL_ERROR,
1087: "invalid namespace declaration '%s'\n",
1088: fullname, NULL);
1089: } else {
1090: xmlNsWarnMsg(ctxt, XML_WAR_NS_COLUMN,
1091: "Avoid attribute ending with ':' like '%s'\n",
1092: fullname, NULL);
1093: }
1094: if (ns != NULL)
1095: xmlFree(ns);
1096: ns = NULL;
1097: xmlFree(name);
1098: name = xmlStrdup(fullname);
1099: }
1100: }
1101: if (name == NULL) {
1102: xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
1103: if (ns != NULL)
1104: xmlFree(ns);
1105: return;
1106: }
1107:
1108: #ifdef LIBXML_HTML_ENABLED
1109: if ((ctxt->html) &&
1110: (value == NULL) && (htmlIsBooleanAttr(fullname))) {
1111: nval = xmlStrdup(fullname);
1112: value = (const xmlChar *) nval;
1113: } else
1114: #endif
1115: {
1116: #ifdef LIBXML_VALID_ENABLED
1117: /*
1118: * Do the last stage of the attribute normalization
1119: * Needed for HTML too:
1120: * http://www.w3.org/TR/html4/types.html#h-6.2
1121: */
1122: ctxt->vctxt.valid = 1;
1123: nval = xmlValidCtxtNormalizeAttributeValue(&ctxt->vctxt,
1124: ctxt->myDoc, ctxt->node,
1125: fullname, value);
1126: if (ctxt->vctxt.valid != 1) {
1127: ctxt->valid = 0;
1128: }
1129: if (nval != NULL)
1130: value = nval;
1131: #else
1132: nval = NULL;
1133: #endif /* LIBXML_VALID_ENABLED */
1134: }
1135:
1136: /*
1137: * Check whether it's a namespace definition
1138: */
1139: if ((!ctxt->html) && (ns == NULL) &&
1140: (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
1141: (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
1142: xmlNsPtr nsret;
1143: xmlChar *val;
1144:
1145: if (!ctxt->replaceEntities) {
1146: ctxt->depth++;
1147: val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1148: 0,0,0);
1149: ctxt->depth--;
1150: } else {
1151: val = (xmlChar *) value;
1152: }
1153:
1154: if (val[0] != 0) {
1155: xmlURIPtr uri;
1156:
1157: uri = xmlParseURI((const char *)val);
1158: if (uri == NULL) {
1159: if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1160: ctxt->sax->warning(ctxt->userData,
1161: "xmlns: %s not a valid URI\n", val);
1162: } else {
1163: if (uri->scheme == NULL) {
1164: if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1165: ctxt->sax->warning(ctxt->userData,
1166: "xmlns: URI %s is not absolute\n", val);
1167: }
1168: xmlFreeURI(uri);
1169: }
1170: }
1171:
1172: /* a default namespace definition */
1173: nsret = xmlNewNs(ctxt->node, val, NULL);
1174:
1175: #ifdef LIBXML_VALID_ENABLED
1176: /*
1177: * Validate also for namespace decls, they are attributes from
1178: * an XML-1.0 perspective
1179: */
1180: if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
1181: ctxt->myDoc && ctxt->myDoc->intSubset)
1182: ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
1183: ctxt->node, prefix, nsret, val);
1184: #endif /* LIBXML_VALID_ENABLED */
1185: if (name != NULL)
1186: xmlFree(name);
1187: if (nval != NULL)
1188: xmlFree(nval);
1189: if (val != value)
1190: xmlFree(val);
1191: return;
1192: }
1193: if ((!ctxt->html) &&
1194: (ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
1195: (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
1196: xmlNsPtr nsret;
1197: xmlChar *val;
1198:
1199: if (!ctxt->replaceEntities) {
1200: ctxt->depth++;
1201: val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1202: 0,0,0);
1203: ctxt->depth--;
1204: if (val == NULL) {
1205: xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
1206: xmlFree(ns);
1207: if (name != NULL)
1208: xmlFree(name);
1209: return;
1210: }
1211: } else {
1212: val = (xmlChar *) value;
1213: }
1214:
1215: if (val[0] == 0) {
1216: xmlNsErrMsg(ctxt, XML_NS_ERR_EMPTY,
1217: "Empty namespace name for prefix %s\n", name, NULL);
1218: }
1219: if ((ctxt->pedantic != 0) && (val[0] != 0)) {
1220: xmlURIPtr uri;
1221:
1222: uri = xmlParseURI((const char *)val);
1223: if (uri == NULL) {
1224: xmlNsWarnMsg(ctxt, XML_WAR_NS_URI,
1225: "xmlns:%s: %s not a valid URI\n", name, value);
1226: } else {
1227: if (uri->scheme == NULL) {
1228: xmlNsWarnMsg(ctxt, XML_WAR_NS_URI_RELATIVE,
1229: "xmlns:%s: URI %s is not absolute\n", name, value);
1230: }
1231: xmlFreeURI(uri);
1232: }
1233: }
1234:
1235: /* a standard namespace definition */
1236: nsret = xmlNewNs(ctxt->node, val, name);
1237: xmlFree(ns);
1238: #ifdef LIBXML_VALID_ENABLED
1239: /*
1240: * Validate also for namespace decls, they are attributes from
1241: * an XML-1.0 perspective
1242: */
1243: if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
1244: ctxt->myDoc && ctxt->myDoc->intSubset)
1245: ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
1246: ctxt->node, prefix, nsret, value);
1247: #endif /* LIBXML_VALID_ENABLED */
1248: if (name != NULL)
1249: xmlFree(name);
1250: if (nval != NULL)
1251: xmlFree(nval);
1252: if (val != value)
1253: xmlFree(val);
1254: return;
1255: }
1256:
1257: if (ns != NULL) {
1258: namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
1259:
1260: if (namespace == NULL) {
1261: xmlNsErrMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
1262: "Namespace prefix %s of attribute %s is not defined\n",
1263: ns, name);
1264: } else {
1265: xmlAttrPtr prop;
1266:
1267: prop = ctxt->node->properties;
1268: while (prop != NULL) {
1269: if (prop->ns != NULL) {
1270: if ((xmlStrEqual(name, prop->name)) &&
1271: ((namespace == prop->ns) ||
1272: (xmlStrEqual(namespace->href, prop->ns->href)))) {
1273: xmlNsErrMsg(ctxt, XML_ERR_ATTRIBUTE_REDEFINED,
1274: "Attribute %s in %s redefined\n",
1275: name, namespace->href);
1276: ctxt->wellFormed = 0;
1277: if (ctxt->recovery == 0) ctxt->disableSAX = 1;
1278: goto error;
1279: }
1280: }
1281: prop = prop->next;
1282: }
1283: }
1284: } else {
1285: namespace = NULL;
1286: }
1287:
1288: /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
1289: ret = xmlNewNsPropEatName(ctxt->node, namespace, name, NULL);
1290:
1291: if (ret != NULL) {
1292: if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
1293: xmlNodePtr tmp;
1294:
1295: ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
1296: tmp = ret->children;
1297: while (tmp != NULL) {
1298: tmp->parent = (xmlNodePtr) ret;
1299: if (tmp->next == NULL)
1300: ret->last = tmp;
1301: tmp = tmp->next;
1302: }
1303: } else if (value != NULL) {
1304: ret->children = xmlNewDocText(ctxt->myDoc, value);
1305: ret->last = ret->children;
1306: if (ret->children != NULL)
1307: ret->children->parent = (xmlNodePtr) ret;
1308: }
1309: }
1310:
1311: #ifdef LIBXML_VALID_ENABLED
1312: if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
1313: ctxt->myDoc && ctxt->myDoc->intSubset) {
1314:
1315: /*
1316: * If we don't substitute entities, the validation should be
1317: * done on a value with replaced entities anyway.
1318: */
1319: if (!ctxt->replaceEntities) {
1320: xmlChar *val;
1321:
1322: ctxt->depth++;
1323: val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1324: 0,0,0);
1325: ctxt->depth--;
1326:
1327: if (val == NULL)
1328: ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1329: ctxt->myDoc, ctxt->node, ret, value);
1330: else {
1331: xmlChar *nvalnorm;
1332:
1333: /*
1334: * Do the last stage of the attribute normalization
1335: * It need to be done twice ... it's an extra burden related
1336: * to the ability to keep xmlSAX2References in attributes
1337: */
1338: nvalnorm = xmlValidNormalizeAttributeValue(ctxt->myDoc,
1339: ctxt->node, fullname, val);
1340: if (nvalnorm != NULL) {
1341: xmlFree(val);
1342: val = nvalnorm;
1343: }
1344:
1345: ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1346: ctxt->myDoc, ctxt->node, ret, val);
1347: xmlFree(val);
1348: }
1349: } else {
1350: ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
1351: ctxt->node, ret, value);
1352: }
1353: } else
1354: #endif /* LIBXML_VALID_ENABLED */
1355: if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
1356: (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
1357: ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
1358: /*
1359: * when validating, the ID registration is done at the attribute
1360: * validation level. Otherwise we have to do specific handling here.
1361: */
1362: if (xmlStrEqual(fullname, BAD_CAST "xml:id")) {
1363: /*
1364: * Add the xml:id value
1365: *
1366: * Open issue: normalization of the value.
1367: */
1368: if (xmlValidateNCName(value, 1) != 0) {
1369: xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
1370: "xml:id : attribute value %s is not an NCName\n",
1371: (const char *) value, NULL);
1372: }
1373: xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
1374: } else if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
1375: xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
1376: else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
1377: xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
1378: }
1379:
1380: error:
1381: if (nval != NULL)
1382: xmlFree(nval);
1383: if (ns != NULL)
1384: xmlFree(ns);
1385: }
1386:
1387: /*
1388: * xmlCheckDefaultedAttributes:
1389: *
1390: * Check defaulted attributes from the DTD
1391: */
1392: static void
1393: xmlCheckDefaultedAttributes(xmlParserCtxtPtr ctxt, const xmlChar *name,
1394: const xmlChar *prefix, const xmlChar **atts) {
1395: xmlElementPtr elemDecl;
1396: const xmlChar *att;
1397: int internal = 1;
1398: int i;
1399:
1400: elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset, name, prefix);
1401: if (elemDecl == NULL) {
1402: elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset, name, prefix);
1403: internal = 0;
1404: }
1405:
1406: process_external_subset:
1407:
1408: if (elemDecl != NULL) {
1409: xmlAttributePtr attr = elemDecl->attributes;
1410: /*
1411: * Check against defaulted attributes from the external subset
1412: * if the document is stamped as standalone
1413: */
1414: if ((ctxt->myDoc->standalone == 1) &&
1415: (ctxt->myDoc->extSubset != NULL) &&
1416: (ctxt->validate)) {
1417: while (attr != NULL) {
1418: if ((attr->defaultValue != NULL) &&
1419: (xmlGetDtdQAttrDesc(ctxt->myDoc->extSubset,
1420: attr->elem, attr->name,
1421: attr->prefix) == attr) &&
1422: (xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1423: attr->elem, attr->name,
1424: attr->prefix) == NULL)) {
1425: xmlChar *fulln;
1426:
1427: if (attr->prefix != NULL) {
1428: fulln = xmlStrdup(attr->prefix);
1429: fulln = xmlStrcat(fulln, BAD_CAST ":");
1430: fulln = xmlStrcat(fulln, attr->name);
1431: } else {
1432: fulln = xmlStrdup(attr->name);
1433: }
1434: if (fulln == NULL) {
1435: xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
1436: break;
1437: }
1438:
1439: /*
1440: * Check that the attribute is not declared in the
1441: * serialization
1442: */
1443: att = NULL;
1444: if (atts != NULL) {
1445: i = 0;
1446: att = atts[i];
1447: while (att != NULL) {
1448: if (xmlStrEqual(att, fulln))
1449: break;
1450: i += 2;
1451: att = atts[i];
1452: }
1453: }
1454: if (att == NULL) {
1455: xmlErrValid(ctxt, XML_DTD_STANDALONE_DEFAULTED,
1456: "standalone: attribute %s on %s defaulted from external subset\n",
1457: (const char *)fulln,
1458: (const char *)attr->elem);
1459: }
1460: xmlFree(fulln);
1461: }
1462: attr = attr->nexth;
1463: }
1464: }
1465:
1466: /*
1467: * Actually insert defaulted values when needed
1468: */
1469: attr = elemDecl->attributes;
1470: while (attr != NULL) {
1471: /*
1472: * Make sure that attributes redefinition occuring in the
1473: * internal subset are not overriden by definitions in the
1474: * external subset.
1475: */
1476: if (attr->defaultValue != NULL) {
1477: /*
1478: * the element should be instantiated in the tree if:
1479: * - this is a namespace prefix
1480: * - the user required for completion in the tree
1481: * like XSLT
1482: * - there isn't already an attribute definition
1483: * in the internal subset overriding it.
1484: */
1485: if (((attr->prefix != NULL) &&
1486: (xmlStrEqual(attr->prefix, BAD_CAST "xmlns"))) ||
1487: ((attr->prefix == NULL) &&
1488: (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) ||
1489: (ctxt->loadsubset & XML_COMPLETE_ATTRS)) {
1490: xmlAttributePtr tst;
1491:
1492: tst = xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1493: attr->elem, attr->name,
1494: attr->prefix);
1495: if ((tst == attr) || (tst == NULL)) {
1496: xmlChar fn[50];
1497: xmlChar *fulln;
1498:
1499: fulln = xmlBuildQName(attr->name, attr->prefix, fn, 50);
1500: if (fulln == NULL) {
1501: xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
1502: return;
1503: }
1504:
1505: /*
1506: * Check that the attribute is not declared in the
1507: * serialization
1508: */
1509: att = NULL;
1510: if (atts != NULL) {
1511: i = 0;
1512: att = atts[i];
1513: while (att != NULL) {
1514: if (xmlStrEqual(att, fulln))
1515: break;
1516: i += 2;
1517: att = atts[i];
1518: }
1519: }
1520: if (att == NULL) {
1521: xmlSAX2AttributeInternal(ctxt, fulln,
1522: attr->defaultValue, prefix);
1523: }
1524: if ((fulln != fn) && (fulln != attr->name))
1525: xmlFree(fulln);
1526: }
1527: }
1528: }
1529: attr = attr->nexth;
1530: }
1531: if (internal == 1) {
1532: elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset,
1533: name, prefix);
1534: internal = 0;
1535: goto process_external_subset;
1536: }
1537: }
1538: }
1539:
1540: /**
1541: * xmlSAX2StartElement:
1542: * @ctx: the user data (XML parser context)
1543: * @fullname: The element name, including namespace prefix
1544: * @atts: An array of name/value attributes pairs, NULL terminated
1545: *
1546: * called when an opening tag has been processed.
1547: */
1548: void
1549: xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
1550: {
1551: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1552: xmlNodePtr ret;
1553: xmlNodePtr parent;
1554: xmlNsPtr ns;
1555: xmlChar *name;
1556: xmlChar *prefix;
1557: const xmlChar *att;
1558: const xmlChar *value;
1559: int i;
1560:
1561: if ((ctx == NULL) || (fullname == NULL) || (ctxt->myDoc == NULL)) return;
1562: parent = ctxt->node;
1563: #ifdef DEBUG_SAX
1564: xmlGenericError(xmlGenericErrorContext,
1565: "SAX.xmlSAX2StartElement(%s)\n", fullname);
1566: #endif
1567:
1568: /*
1569: * First check on validity:
1570: */
1571: if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
1572: ((ctxt->myDoc->intSubset == NULL) ||
1573: ((ctxt->myDoc->intSubset->notations == NULL) &&
1574: (ctxt->myDoc->intSubset->elements == NULL) &&
1575: (ctxt->myDoc->intSubset->attributes == NULL) &&
1576: (ctxt->myDoc->intSubset->entities == NULL)))) {
1577: xmlErrValid(ctxt, XML_ERR_NO_DTD,
1578: "Validation failed: no DTD found !", NULL, NULL);
1579: ctxt->validate = 0;
1580: }
1581:
1582:
1583: /*
1584: * Split the full name into a namespace prefix and the tag name
1585: */
1586: name = xmlSplitQName(ctxt, fullname, &prefix);
1587:
1588:
1589: /*
1590: * Note : the namespace resolution is deferred until the end of the
1591: * attributes parsing, since local namespace can be defined as
1592: * an attribute at this level.
1593: */
1594: ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL);
1595: if (ret == NULL) {
1596: if (prefix != NULL)
1597: xmlFree(prefix);
1598: xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
1599: return;
1600: }
1601: if (ctxt->myDoc->children == NULL) {
1602: #ifdef DEBUG_SAX_TREE
1603: xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
1604: #endif
1605: xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1606: } else if (parent == NULL) {
1607: parent = ctxt->myDoc->children;
1608: }
1609: ctxt->nodemem = -1;
1610: if (ctxt->linenumbers) {
1611: if (ctxt->input != NULL) {
1612: if (ctxt->input->line < 65535)
1613: ret->line = (short) ctxt->input->line;
1614: else
1615: ret->line = 65535;
1616: }
1617: }
1618:
1619: /*
1620: * We are parsing a new node.
1621: */
1622: #ifdef DEBUG_SAX_TREE
1623: xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);
1624: #endif
1625: nodePush(ctxt, ret);
1626:
1627: /*
1628: * Link the child element
1629: */
1630: if (parent != NULL) {
1631: if (parent->type == XML_ELEMENT_NODE) {
1632: #ifdef DEBUG_SAX_TREE
1633: xmlGenericError(xmlGenericErrorContext,
1634: "adding child %s to %s\n", name, parent->name);
1635: #endif
1636: xmlAddChild(parent, ret);
1637: } else {
1638: #ifdef DEBUG_SAX_TREE
1639: xmlGenericError(xmlGenericErrorContext,
1640: "adding sibling %s to ", name);
1641: xmlDebugDumpOneNode(stderr, parent, 0);
1642: #endif
1643: xmlAddSibling(parent, ret);
1644: }
1645: }
1646:
1647: /*
1648: * Insert all the defaulted attributes from the DTD especially namespaces
1649: */
1650: if ((!ctxt->html) &&
1651: ((ctxt->myDoc->intSubset != NULL) ||
1652: (ctxt->myDoc->extSubset != NULL))) {
1653: xmlCheckDefaultedAttributes(ctxt, name, prefix, atts);
1654: }
1655:
1656: /*
1657: * process all the attributes whose name start with "xmlns"
1658: */
1659: if (atts != NULL) {
1660: i = 0;
1661: att = atts[i++];
1662: value = atts[i++];
1663: if (!ctxt->html) {
1664: while ((att != NULL) && (value != NULL)) {
1665: if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l') &&
1666: (att[3] == 'n') && (att[4] == 's'))
1667: xmlSAX2AttributeInternal(ctxt, att, value, prefix);
1668:
1669: att = atts[i++];
1670: value = atts[i++];
1671: }
1672: }
1673: }
1674:
1675: /*
1676: * Search the namespace, note that since the attributes have been
1677: * processed, the local namespaces are available.
1678: */
1679: ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
1680: if ((ns == NULL) && (parent != NULL))
1681: ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
1682: if ((prefix != NULL) && (ns == NULL)) {
1683: ns = xmlNewNs(ret, NULL, prefix);
1684: xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
1685: "Namespace prefix %s is not defined\n",
1686: prefix, NULL);
1687: }
1688:
1689: /*
1690: * set the namespace node, making sure that if the default namspace
1691: * is unbound on a parent we simply kee it NULL
1692: */
1693: if ((ns != NULL) && (ns->href != NULL) &&
1694: ((ns->href[0] != 0) || (ns->prefix != NULL)))
1695: xmlSetNs(ret, ns);
1696:
1697: /*
1698: * process all the other attributes
1699: */
1700: if (atts != NULL) {
1701: i = 0;
1702: att = atts[i++];
1703: value = atts[i++];
1704: if (ctxt->html) {
1705: while (att != NULL) {
1706: xmlSAX2AttributeInternal(ctxt, att, value, NULL);
1707: att = atts[i++];
1708: value = atts[i++];
1709: }
1710: } else {
1711: while ((att != NULL) && (value != NULL)) {
1712: if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l') ||
1713: (att[3] != 'n') || (att[4] != 's'))
1714: xmlSAX2AttributeInternal(ctxt, att, value, NULL);
1715:
1716: /*
1717: * Next ones
1718: */
1719: att = atts[i++];
1720: value = atts[i++];
1721: }
1722: }
1723: }
1724:
1725: #ifdef LIBXML_VALID_ENABLED
1726: /*
1727: * If it's the Document root, finish the DTD validation and
1728: * check the document root element for validity
1729: */
1730: if ((ctxt->validate) && (ctxt->vctxt.finishDtd == XML_CTXT_FINISH_DTD_0)) {
1731: int chk;
1732:
1733: chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
1734: if (chk <= 0)
1735: ctxt->valid = 0;
1736: if (chk < 0)
1737: ctxt->wellFormed = 0;
1738: ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
1739: ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_1;
1740: }
1741: #endif /* LIBXML_VALID_ENABLED */
1742:
1743: if (prefix != NULL)
1744: xmlFree(prefix);
1745:
1746: }
1747:
1748: /**
1749: * xmlSAX2EndElement:
1750: * @ctx: the user data (XML parser context)
1751: * @name: The element name
1752: *
1753: * called when the end of an element has been detected.
1754: */
1755: void
1756: xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
1757: {
1758: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1759: xmlNodePtr cur;
1760:
1761: if (ctx == NULL) return;
1762: cur = ctxt->node;
1763: #ifdef DEBUG_SAX
1764: if (name == NULL)
1765: xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(NULL)\n");
1766: else
1767: xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(%s)\n", name);
1768: #endif
1769:
1770: /* Capture end position and add node */
1771: if (cur != NULL && ctxt->record_info) {
1.1.1.2 ! misho 1772: ctxt->nodeInfo->end_pos = ctxt->input->cur - ctxt->input->base;
! 1773: ctxt->nodeInfo->end_line = ctxt->input->line;
! 1774: ctxt->nodeInfo->node = cur;
! 1775: xmlParserAddNodeInfo(ctxt, ctxt->nodeInfo);
1.1 misho 1776: }
1777: ctxt->nodemem = -1;
1778:
1779: #ifdef LIBXML_VALID_ENABLED
1780: if (ctxt->validate && ctxt->wellFormed &&
1781: ctxt->myDoc && ctxt->myDoc->intSubset)
1782: ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
1783: cur);
1784: #endif /* LIBXML_VALID_ENABLED */
1785:
1786:
1787: /*
1788: * end of parsing of this node.
1789: */
1790: #ifdef DEBUG_SAX_TREE
1791: xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);
1792: #endif
1793: nodePop(ctxt);
1794: }
1795: #endif /* LIBXML_SAX1_ENABLED || LIBXML_HTML_ENABLE */
1796:
1797: /*
1798: * xmlSAX2TextNode:
1799: * @ctxt: the parser context
1800: * @str: the input string
1801: * @len: the string length
1802: *
1803: * Remove the entities from an attribute value
1804: *
1805: * Returns the newly allocated string or NULL if not needed or error
1806: */
1807: static xmlNodePtr
1808: xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
1809: xmlNodePtr ret;
1810: const xmlChar *intern = NULL;
1811:
1812: /*
1813: * Allocate
1814: */
1815: if (ctxt->freeElems != NULL) {
1816: ret = ctxt->freeElems;
1817: ctxt->freeElems = ret->next;
1818: ctxt->freeElemsNr--;
1819: } else {
1820: ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1821: }
1822: if (ret == NULL) {
1823: xmlErrMemory(ctxt, "xmlSAX2Characters");
1824: return(NULL);
1825: }
1826: memset(ret, 0, sizeof(xmlNode));
1827: /*
1828: * intern the formatting blanks found between tags, or the
1829: * very short strings
1830: */
1831: if (ctxt->dictNames) {
1832: xmlChar cur = str[len];
1833:
1834: if ((len < (int) (2 * sizeof(void *))) &&
1835: (ctxt->options & XML_PARSE_COMPACT)) {
1836: /* store the string in the node overrithing properties and nsDef */
1837: xmlChar *tmp = (xmlChar *) &(ret->properties);
1838: memcpy(tmp, str, len);
1839: tmp[len] = 0;
1840: intern = tmp;
1841: } else if ((len <= 3) && ((cur == '"') || (cur == '\'') ||
1842: ((cur == '<') && (str[len + 1] != '!')))) {
1843: intern = xmlDictLookup(ctxt->dict, str, len);
1844: } else if (IS_BLANK_CH(*str) && (len < 60) && (cur == '<') &&
1845: (str[len + 1] != '!')) {
1846: int i;
1847:
1848: for (i = 1;i < len;i++) {
1849: if (!IS_BLANK_CH(str[i])) goto skip;
1850: }
1851: intern = xmlDictLookup(ctxt->dict, str, len);
1852: }
1853: }
1854: skip:
1855: ret->type = XML_TEXT_NODE;
1856:
1857: ret->name = xmlStringText;
1858: if (intern == NULL) {
1859: ret->content = xmlStrndup(str, len);
1860: if (ret->content == NULL) {
1861: xmlSAX2ErrMemory(ctxt, "xmlSAX2TextNode");
1862: xmlFree(ret);
1863: return(NULL);
1864: }
1865: } else
1866: ret->content = (xmlChar *) intern;
1867:
1868: if (ctxt->input != NULL)
1869: ret->line = ctxt->input->line;
1870:
1871: if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1872: xmlRegisterNodeDefaultValue(ret);
1873: return(ret);
1874: }
1875:
1876: #ifdef LIBXML_VALID_ENABLED
1877: /*
1878: * xmlSAX2DecodeAttrEntities:
1879: * @ctxt: the parser context
1880: * @str: the input string
1881: * @len: the string length
1882: *
1883: * Remove the entities from an attribute value
1884: *
1885: * Returns the newly allocated string or NULL if not needed or error
1886: */
1887: static xmlChar *
1888: xmlSAX2DecodeAttrEntities(xmlParserCtxtPtr ctxt, const xmlChar *str,
1889: const xmlChar *end) {
1890: const xmlChar *in;
1891: xmlChar *ret;
1892:
1893: in = str;
1894: while (in < end)
1895: if (*in++ == '&')
1896: goto decode;
1897: return(NULL);
1898: decode:
1899: ctxt->depth++;
1900: ret = xmlStringLenDecodeEntities(ctxt, str, end - str,
1901: XML_SUBSTITUTE_REF, 0,0,0);
1902: ctxt->depth--;
1903: return(ret);
1904: }
1905: #endif /* LIBXML_VALID_ENABLED */
1906:
1907: /**
1908: * xmlSAX2AttributeNs:
1909: * @ctx: the user data (XML parser context)
1910: * @localname: the local name of the attribute
1911: * @prefix: the attribute namespace prefix if available
1912: * @URI: the attribute namespace name if available
1913: * @value: Start of the attribute value
1914: * @valueend: end of the attribute value
1915: *
1916: * Handle an attribute that has been read by the parser.
1917: * The default handling is to convert the attribute into an
1918: * DOM subtree and past it in a new xmlAttr element added to
1919: * the element.
1920: */
1921: static void
1922: xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
1923: const xmlChar * localname,
1924: const xmlChar * prefix,
1925: const xmlChar * value,
1926: const xmlChar * valueend)
1927: {
1928: xmlAttrPtr ret;
1929: xmlNsPtr namespace = NULL;
1930: xmlChar *dup = NULL;
1931:
1932: /*
1933: * Note: if prefix == NULL, the attribute is not in the default namespace
1934: */
1935: if (prefix != NULL)
1936: namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, prefix);
1937:
1938: /*
1939: * allocate the node
1940: */
1941: if (ctxt->freeAttrs != NULL) {
1942: ret = ctxt->freeAttrs;
1943: ctxt->freeAttrs = ret->next;
1944: ctxt->freeAttrsNr--;
1945: memset(ret, 0, sizeof(xmlAttr));
1946: ret->type = XML_ATTRIBUTE_NODE;
1947:
1948: ret->parent = ctxt->node;
1949: ret->doc = ctxt->myDoc;
1950: ret->ns = namespace;
1951:
1952: if (ctxt->dictNames)
1953: ret->name = localname;
1954: else
1955: ret->name = xmlStrdup(localname);
1956:
1957: /* link at the end to preserv order, TODO speed up with a last */
1958: if (ctxt->node->properties == NULL) {
1959: ctxt->node->properties = ret;
1960: } else {
1961: xmlAttrPtr prev = ctxt->node->properties;
1962:
1963: while (prev->next != NULL) prev = prev->next;
1964: prev->next = ret;
1965: ret->prev = prev;
1966: }
1967:
1968: if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1969: xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
1970: } else {
1971: if (ctxt->dictNames)
1972: ret = xmlNewNsPropEatName(ctxt->node, namespace,
1973: (xmlChar *) localname, NULL);
1974: else
1975: ret = xmlNewNsProp(ctxt->node, namespace, localname, NULL);
1976: if (ret == NULL) {
1977: xmlErrMemory(ctxt, "xmlSAX2AttributeNs");
1978: return;
1979: }
1980: }
1981:
1982: if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
1983: xmlNodePtr tmp;
1984:
1985: /*
1986: * We know that if there is an entity reference, then
1987: * the string has been dup'ed and terminates with 0
1988: * otherwise with ' or "
1989: */
1990: if (*valueend != 0) {
1991: tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
1992: ret->children = tmp;
1993: ret->last = tmp;
1994: if (tmp != NULL) {
1995: tmp->doc = ret->doc;
1996: tmp->parent = (xmlNodePtr) ret;
1997: }
1998: } else {
1999: ret->children = xmlStringLenGetNodeList(ctxt->myDoc, value,
2000: valueend - value);
2001: tmp = ret->children;
2002: while (tmp != NULL) {
2003: tmp->doc = ret->doc;
2004: tmp->parent = (xmlNodePtr) ret;
2005: if (tmp->next == NULL)
2006: ret->last = tmp;
2007: tmp = tmp->next;
2008: }
2009: }
2010: } else if (value != NULL) {
2011: xmlNodePtr tmp;
2012:
2013: tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
2014: ret->children = tmp;
2015: ret->last = tmp;
2016: if (tmp != NULL) {
2017: tmp->doc = ret->doc;
2018: tmp->parent = (xmlNodePtr) ret;
2019: }
2020: }
2021:
2022: #ifdef LIBXML_VALID_ENABLED
2023: if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
2024: ctxt->myDoc && ctxt->myDoc->intSubset) {
2025: /*
2026: * If we don't substitute entities, the validation should be
2027: * done on a value with replaced entities anyway.
2028: */
2029: if (!ctxt->replaceEntities) {
2030: dup = xmlSAX2DecodeAttrEntities(ctxt, value, valueend);
2031: if (dup == NULL) {
2032: if (*valueend == 0) {
2033: ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2034: ctxt->myDoc, ctxt->node, ret, value);
2035: } else {
2036: /*
2037: * That should already be normalized.
2038: * cheaper to finally allocate here than duplicate
2039: * entry points in the full validation code
2040: */
2041: dup = xmlStrndup(value, valueend - value);
2042:
2043: ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2044: ctxt->myDoc, ctxt->node, ret, dup);
2045: }
2046: } else {
2047: /*
2048: * dup now contains a string of the flattened attribute
2049: * content with entities substitued. Check if we need to
2050: * apply an extra layer of normalization.
2051: * It need to be done twice ... it's an extra burden related
2052: * to the ability to keep references in attributes
2053: */
2054: if (ctxt->attsSpecial != NULL) {
2055: xmlChar *nvalnorm;
2056: xmlChar fn[50];
2057: xmlChar *fullname;
2058:
2059: fullname = xmlBuildQName(localname, prefix, fn, 50);
2060: if (fullname != NULL) {
2061: ctxt->vctxt.valid = 1;
2062: nvalnorm = xmlValidCtxtNormalizeAttributeValue(
2063: &ctxt->vctxt, ctxt->myDoc,
2064: ctxt->node, fullname, dup);
2065: if (ctxt->vctxt.valid != 1)
2066: ctxt->valid = 0;
2067:
2068: if ((fullname != fn) && (fullname != localname))
2069: xmlFree(fullname);
2070: if (nvalnorm != NULL) {
2071: xmlFree(dup);
2072: dup = nvalnorm;
2073: }
2074: }
2075: }
2076:
2077: ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2078: ctxt->myDoc, ctxt->node, ret, dup);
2079: }
2080: } else {
2081: /*
2082: * if entities already have been substitued, then
2083: * the attribute as passed is already normalized
2084: */
2085: dup = xmlStrndup(value, valueend - value);
2086:
2087: ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2088: ctxt->myDoc, ctxt->node, ret, dup);
2089: }
2090: } else
2091: #endif /* LIBXML_VALID_ENABLED */
2092: if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
2093: (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
2094: ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
2095: /*
2096: * when validating, the ID registration is done at the attribute
2097: * validation level. Otherwise we have to do specific handling here.
2098: */
2099: if ((prefix == ctxt->str_xml) &&
2100: (localname[0] == 'i') && (localname[1] == 'd') &&
2101: (localname[2] == 0)) {
2102: /*
2103: * Add the xml:id value
2104: *
2105: * Open issue: normalization of the value.
2106: */
2107: if (dup == NULL)
2108: dup = xmlStrndup(value, valueend - value);
2109: #ifdef LIBXML_VALID_ENABLED
2110: if (xmlValidateNCName(dup, 1) != 0) {
2111: xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
2112: "xml:id : attribute value %s is not an NCName\n",
2113: (const char *) dup, NULL);
2114: }
2115: #endif
2116: xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
2117: } else if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) {
2118: /* might be worth duplicate entry points and not copy */
2119: if (dup == NULL)
2120: dup = xmlStrndup(value, valueend - value);
2121: xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
2122: } else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) {
2123: if (dup == NULL)
2124: dup = xmlStrndup(value, valueend - value);
2125: xmlAddRef(&ctxt->vctxt, ctxt->myDoc, dup, ret);
2126: }
2127: }
2128: if (dup != NULL)
2129: xmlFree(dup);
2130: }
2131:
2132: /**
2133: * xmlSAX2StartElementNs:
2134: * @ctx: the user data (XML parser context)
2135: * @localname: the local name of the element
2136: * @prefix: the element namespace prefix if available
2137: * @URI: the element namespace name if available
2138: * @nb_namespaces: number of namespace definitions on that node
2139: * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
2140: * @nb_attributes: the number of attributes on that node
2141: * @nb_defaulted: the number of defaulted attributes.
2142: * @attributes: pointer to the array of (localname/prefix/URI/value/end)
2143: * attribute values.
2144: *
2145: * SAX2 callback when an element start has been detected by the parser.
2146: * It provides the namespace informations for the element, as well as
2147: * the new namespace declarations on the element.
2148: */
2149: void
2150: xmlSAX2StartElementNs(void *ctx,
2151: const xmlChar *localname,
2152: const xmlChar *prefix,
2153: const xmlChar *URI,
2154: int nb_namespaces,
2155: const xmlChar **namespaces,
2156: int nb_attributes,
2157: int nb_defaulted,
2158: const xmlChar **attributes)
2159: {
2160: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2161: xmlNodePtr ret;
2162: xmlNodePtr parent;
2163: xmlNsPtr last = NULL, ns;
2164: const xmlChar *uri, *pref;
1.1.1.2 ! misho 2165: xmlChar *lname = NULL;
1.1 misho 2166: int i, j;
2167:
2168: if (ctx == NULL) return;
2169: parent = ctxt->node;
2170: /*
2171: * First check on validity:
2172: */
2173: if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
2174: ((ctxt->myDoc->intSubset == NULL) ||
2175: ((ctxt->myDoc->intSubset->notations == NULL) &&
2176: (ctxt->myDoc->intSubset->elements == NULL) &&
2177: (ctxt->myDoc->intSubset->attributes == NULL) &&
2178: (ctxt->myDoc->intSubset->entities == NULL)))) {
2179: xmlErrValid(ctxt, XML_ERR_NO_DTD,
2180: "Validation failed: no DTD found !", NULL, NULL);
2181: ctxt->validate = 0;
2182: }
2183:
2184: /*
1.1.1.2 ! misho 2185: * Take care of the rare case of an undefined namespace prefix
! 2186: */
! 2187: if ((prefix != NULL) && (URI == NULL)) {
! 2188: if (ctxt->dictNames) {
! 2189: const xmlChar *fullname;
! 2190:
! 2191: fullname = xmlDictQLookup(ctxt->dict, prefix, localname);
! 2192: if (fullname != NULL)
! 2193: localname = fullname;
! 2194: } else {
! 2195: lname = xmlBuildQName(localname, prefix, NULL, 0);
! 2196: }
! 2197: }
! 2198: /*
1.1 misho 2199: * allocate the node
2200: */
2201: if (ctxt->freeElems != NULL) {
2202: ret = ctxt->freeElems;
2203: ctxt->freeElems = ret->next;
2204: ctxt->freeElemsNr--;
2205: memset(ret, 0, sizeof(xmlNode));
2206: ret->type = XML_ELEMENT_NODE;
2207:
2208: if (ctxt->dictNames)
2209: ret->name = localname;
2210: else {
1.1.1.2 ! misho 2211: if (lname == NULL)
! 2212: ret->name = xmlStrdup(localname);
! 2213: else
! 2214: ret->name = lname;
1.1 misho 2215: if (ret->name == NULL) {
2216: xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
2217: return;
2218: }
2219: }
2220: if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2221: xmlRegisterNodeDefaultValue(ret);
2222: } else {
2223: if (ctxt->dictNames)
2224: ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
2225: (xmlChar *) localname, NULL);
1.1.1.2 ! misho 2226: else if (lname == NULL)
1.1 misho 2227: ret = xmlNewDocNode(ctxt->myDoc, NULL, localname, NULL);
1.1.1.2 ! misho 2228: else
! 2229: ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
! 2230: (xmlChar *) lname, NULL);
1.1 misho 2231: if (ret == NULL) {
2232: xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
2233: return;
2234: }
2235: }
2236: if (ctxt->linenumbers) {
2237: if (ctxt->input != NULL) {
2238: if (ctxt->input->line < 65535)
2239: ret->line = (short) ctxt->input->line;
2240: else
2241: ret->line = 65535;
2242: }
2243: }
2244:
1.1.1.2 ! misho 2245: if (parent == NULL) {
1.1 misho 2246: xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2247: }
2248: /*
2249: * Build the namespace list
2250: */
2251: for (i = 0,j = 0;j < nb_namespaces;j++) {
2252: pref = namespaces[i++];
2253: uri = namespaces[i++];
2254: ns = xmlNewNs(NULL, uri, pref);
2255: if (ns != NULL) {
2256: if (last == NULL) {
2257: ret->nsDef = last = ns;
2258: } else {
2259: last->next = ns;
2260: last = ns;
2261: }
2262: if ((URI != NULL) && (prefix == pref))
2263: ret->ns = ns;
2264: } else {
2265: /*
2266: * any out of memory error would already have been raised
2267: * but we can't be garanteed it's the actual error due to the
2268: * API, best is to skip in this case
2269: */
2270: continue;
2271: }
2272: #ifdef LIBXML_VALID_ENABLED
2273: if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
2274: ctxt->myDoc && ctxt->myDoc->intSubset) {
2275: ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
2276: ret, prefix, ns, uri);
2277: }
2278: #endif /* LIBXML_VALID_ENABLED */
2279: }
2280: ctxt->nodemem = -1;
2281:
2282: /*
2283: * We are parsing a new node.
2284: */
2285: nodePush(ctxt, ret);
2286:
2287: /*
2288: * Link the child element
2289: */
2290: if (parent != NULL) {
2291: if (parent->type == XML_ELEMENT_NODE) {
2292: xmlAddChild(parent, ret);
2293: } else {
2294: xmlAddSibling(parent, ret);
2295: }
2296: }
2297:
2298: /*
2299: * Insert the defaulted attributes from the DTD only if requested:
2300: */
2301: if ((nb_defaulted != 0) &&
2302: ((ctxt->loadsubset & XML_COMPLETE_ATTRS) == 0))
2303: nb_attributes -= nb_defaulted;
2304:
2305: /*
2306: * Search the namespace if it wasn't already found
2307: * Note that, if prefix is NULL, this searches for the default Ns
2308: */
2309: if ((URI != NULL) && (ret->ns == NULL)) {
2310: ret->ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
2311: if ((ret->ns == NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) {
2312: ret->ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
2313: }
2314: if (ret->ns == NULL) {
2315: ns = xmlNewNs(ret, NULL, prefix);
2316: if (ns == NULL) {
2317:
2318: xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
2319: return;
2320: }
2321: if (prefix != NULL)
2322: xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
2323: "Namespace prefix %s was not found\n",
2324: prefix, NULL);
2325: else
2326: xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
2327: "Namespace default prefix was not found\n",
2328: NULL, NULL);
2329: }
2330: }
2331:
2332: /*
2333: * process all the other attributes
2334: */
2335: if (nb_attributes > 0) {
2336: for (j = 0,i = 0;i < nb_attributes;i++,j+=5) {
1.1.1.2 ! misho 2337: /*
! 2338: * Handle the rare case of an undefined atribute prefix
! 2339: */
! 2340: if ((attributes[j+1] != NULL) && (attributes[j+2] == NULL)) {
! 2341: if (ctxt->dictNames) {
! 2342: const xmlChar *fullname;
! 2343:
! 2344: fullname = xmlDictQLookup(ctxt->dict, attributes[j+1],
! 2345: attributes[j]);
! 2346: if (fullname != NULL) {
! 2347: xmlSAX2AttributeNs(ctxt, fullname, NULL,
! 2348: attributes[j+3], attributes[j+4]);
! 2349: continue;
! 2350: }
! 2351: } else {
! 2352: lname = xmlBuildQName(attributes[j], attributes[j+1],
! 2353: NULL, 0);
! 2354: if (lname != NULL) {
! 2355: xmlSAX2AttributeNs(ctxt, lname, NULL,
! 2356: attributes[j+3], attributes[j+4]);
! 2357: xmlFree(lname);
! 2358: continue;
! 2359: }
! 2360: }
! 2361: }
1.1 misho 2362: xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1],
1.1.1.2 ! misho 2363: attributes[j+3], attributes[j+4]);
1.1 misho 2364: }
2365: }
2366:
2367: #ifdef LIBXML_VALID_ENABLED
2368: /*
2369: * If it's the Document root, finish the DTD validation and
2370: * check the document root element for validity
2371: */
2372: if ((ctxt->validate) && (ctxt->vctxt.finishDtd == XML_CTXT_FINISH_DTD_0)) {
2373: int chk;
2374:
2375: chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
2376: if (chk <= 0)
2377: ctxt->valid = 0;
2378: if (chk < 0)
2379: ctxt->wellFormed = 0;
2380: ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
2381: ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_1;
2382: }
2383: #endif /* LIBXML_VALID_ENABLED */
2384: }
2385:
2386: /**
2387: * xmlSAX2EndElementNs:
2388: * @ctx: the user data (XML parser context)
2389: * @localname: the local name of the element
2390: * @prefix: the element namespace prefix if available
2391: * @URI: the element namespace name if available
2392: *
2393: * SAX2 callback when an element end has been detected by the parser.
2394: * It provides the namespace informations for the element.
2395: */
2396: void
2397: xmlSAX2EndElementNs(void *ctx,
2398: const xmlChar * localname ATTRIBUTE_UNUSED,
2399: const xmlChar * prefix ATTRIBUTE_UNUSED,
2400: const xmlChar * URI ATTRIBUTE_UNUSED)
2401: {
2402: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2403: xmlParserNodeInfo node_info;
2404: xmlNodePtr cur;
2405:
2406: if (ctx == NULL) return;
2407: cur = ctxt->node;
2408: /* Capture end position and add node */
2409: if ((ctxt->record_info) && (cur != NULL)) {
2410: node_info.end_pos = ctxt->input->cur - ctxt->input->base;
2411: node_info.end_line = ctxt->input->line;
2412: node_info.node = cur;
2413: xmlParserAddNodeInfo(ctxt, &node_info);
2414: }
2415: ctxt->nodemem = -1;
2416:
2417: #ifdef LIBXML_VALID_ENABLED
2418: if (ctxt->validate && ctxt->wellFormed &&
2419: ctxt->myDoc && ctxt->myDoc->intSubset)
2420: ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, cur);
2421: #endif /* LIBXML_VALID_ENABLED */
2422:
2423: /*
2424: * end of parsing of this node.
2425: */
2426: nodePop(ctxt);
2427: }
2428:
2429: /**
2430: * xmlSAX2Reference:
2431: * @ctx: the user data (XML parser context)
2432: * @name: The entity name
2433: *
2434: * called when an entity xmlSAX2Reference is detected.
2435: */
2436: void
2437: xmlSAX2Reference(void *ctx, const xmlChar *name)
2438: {
2439: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2440: xmlNodePtr ret;
2441:
2442: if (ctx == NULL) return;
2443: #ifdef DEBUG_SAX
2444: xmlGenericError(xmlGenericErrorContext,
2445: "SAX.xmlSAX2Reference(%s)\n", name);
2446: #endif
2447: if (name[0] == '#')
2448: ret = xmlNewCharRef(ctxt->myDoc, name);
2449: else
2450: ret = xmlNewReference(ctxt->myDoc, name);
2451: #ifdef DEBUG_SAX_TREE
2452: xmlGenericError(xmlGenericErrorContext,
2453: "add xmlSAX2Reference %s to %s \n", name, ctxt->node->name);
2454: #endif
2455: if (xmlAddChild(ctxt->node, ret) == NULL) {
2456: xmlFreeNode(ret);
2457: }
2458: }
2459:
2460: /**
2461: * xmlSAX2Characters:
2462: * @ctx: the user data (XML parser context)
2463: * @ch: a xmlChar string
2464: * @len: the number of xmlChar
2465: *
2466: * receiving some chars from the parser.
2467: */
2468: void
2469: xmlSAX2Characters(void *ctx, const xmlChar *ch, int len)
2470: {
2471: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2472: xmlNodePtr lastChild;
2473:
2474: if (ctx == NULL) return;
2475: #ifdef DEBUG_SAX
2476: xmlGenericError(xmlGenericErrorContext,
2477: "SAX.xmlSAX2Characters(%.30s, %d)\n", ch, len);
2478: #endif
2479: /*
2480: * Handle the data if any. If there is no child
2481: * add it as content, otherwise if the last child is text,
2482: * concatenate it, else create a new node of type text.
2483: */
2484:
2485: if (ctxt->node == NULL) {
2486: #ifdef DEBUG_SAX_TREE
2487: xmlGenericError(xmlGenericErrorContext,
2488: "add chars: ctxt->node == NULL !\n");
2489: #endif
2490: return;
2491: }
2492: lastChild = ctxt->node->last;
2493: #ifdef DEBUG_SAX_TREE
2494: xmlGenericError(xmlGenericErrorContext,
2495: "add chars to %s \n", ctxt->node->name);
2496: #endif
2497:
2498: /*
2499: * Here we needed an accelerator mechanism in case of very large
2500: * elements. Use an attribute in the structure !!!
2501: */
2502: if (lastChild == NULL) {
2503: lastChild = xmlSAX2TextNode(ctxt, ch, len);
2504: if (lastChild != NULL) {
2505: ctxt->node->children = lastChild;
2506: ctxt->node->last = lastChild;
2507: lastChild->parent = ctxt->node;
2508: lastChild->doc = ctxt->node->doc;
2509: ctxt->nodelen = len;
2510: ctxt->nodemem = len + 1;
2511: } else {
2512: xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
2513: return;
2514: }
2515: } else {
2516: int coalesceText = (lastChild != NULL) &&
2517: (lastChild->type == XML_TEXT_NODE) &&
2518: (lastChild->name == xmlStringText);
2519: if ((coalesceText) && (ctxt->nodemem != 0)) {
2520: /*
2521: * The whole point of maintaining nodelen and nodemem,
2522: * xmlTextConcat is too costly, i.e. compute length,
2523: * reallocate a new buffer, move data, append ch. Here
2524: * We try to minimaze realloc() uses and avoid copying
2525: * and recomputing length over and over.
2526: */
2527: if (lastChild->content == (xmlChar *)&(lastChild->properties)) {
2528: lastChild->content = xmlStrdup(lastChild->content);
2529: lastChild->properties = NULL;
2530: } else if ((ctxt->nodemem == ctxt->nodelen + 1) &&
2531: (xmlDictOwns(ctxt->dict, lastChild->content))) {
2532: lastChild->content = xmlStrdup(lastChild->content);
2533: }
2534: if (((size_t)ctxt->nodelen + (size_t)len > XML_MAX_TEXT_LENGTH) &&
2535: ((ctxt->options & XML_PARSE_HUGE) == 0)) {
2536: xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters: huge text node");
2537: return;
2538: }
2539: if ((size_t)ctxt->nodelen > SIZE_T_MAX - (size_t)len ||
2540: (size_t)ctxt->nodemem + (size_t)len > SIZE_T_MAX / 2) {
2541: xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters overflow prevented");
2542: return;
2543: }
2544: if (ctxt->nodelen + len >= ctxt->nodemem) {
2545: xmlChar *newbuf;
2546: size_t size;
2547:
2548: size = ctxt->nodemem + len;
2549: size *= 2;
2550: newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
2551: if (newbuf == NULL) {
2552: xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
2553: return;
2554: }
2555: ctxt->nodemem = size;
2556: lastChild->content = newbuf;
2557: }
2558: memcpy(&lastChild->content[ctxt->nodelen], ch, len);
2559: ctxt->nodelen += len;
2560: lastChild->content[ctxt->nodelen] = 0;
2561: } else if (coalesceText) {
2562: if (xmlTextConcat(lastChild, ch, len)) {
2563: xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
2564: }
2565: if (ctxt->node->children != NULL) {
2566: ctxt->nodelen = xmlStrlen(lastChild->content);
2567: ctxt->nodemem = ctxt->nodelen + 1;
2568: }
2569: } else {
2570: /* Mixed content, first time */
2571: lastChild = xmlSAX2TextNode(ctxt, ch, len);
2572: if (lastChild != NULL) {
2573: xmlAddChild(ctxt->node, lastChild);
2574: if (ctxt->node->children != NULL) {
2575: ctxt->nodelen = len;
2576: ctxt->nodemem = len + 1;
2577: }
2578: }
2579: }
2580: }
2581: }
2582:
2583: /**
2584: * xmlSAX2IgnorableWhitespace:
2585: * @ctx: the user data (XML parser context)
2586: * @ch: a xmlChar string
2587: * @len: the number of xmlChar
2588: *
2589: * receiving some ignorable whitespaces from the parser.
2590: * UNUSED: by default the DOM building will use xmlSAX2Characters
2591: */
2592: void
2593: xmlSAX2IgnorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
2594: {
2595: /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
2596: #ifdef DEBUG_SAX
2597: xmlGenericError(xmlGenericErrorContext,
2598: "SAX.xmlSAX2IgnorableWhitespace(%.30s, %d)\n", ch, len);
2599: #endif
2600: }
2601:
2602: /**
2603: * xmlSAX2ProcessingInstruction:
2604: * @ctx: the user data (XML parser context)
2605: * @target: the target name
2606: * @data: the PI data's
2607: *
2608: * A processing instruction has been parsed.
2609: */
2610: void
2611: xmlSAX2ProcessingInstruction(void *ctx, const xmlChar *target,
2612: const xmlChar *data)
2613: {
2614: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2615: xmlNodePtr ret;
2616: xmlNodePtr parent;
2617:
2618: if (ctx == NULL) return;
2619: parent = ctxt->node;
2620: #ifdef DEBUG_SAX
2621: xmlGenericError(xmlGenericErrorContext,
2622: "SAX.xmlSAX2ProcessingInstruction(%s, %s)\n", target, data);
2623: #endif
2624:
2625: ret = xmlNewDocPI(ctxt->myDoc, target, data);
2626: if (ret == NULL) return;
2627:
2628: if (ctxt->linenumbers) {
2629: if (ctxt->input != NULL) {
2630: if (ctxt->input->line < 65535)
2631: ret->line = (short) ctxt->input->line;
2632: else
2633: ret->line = 65535;
2634: }
2635: }
2636: if (ctxt->inSubset == 1) {
2637: xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2638: return;
2639: } else if (ctxt->inSubset == 2) {
2640: xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2641: return;
2642: }
1.1.1.2 ! misho 2643: if (parent == NULL) {
1.1 misho 2644: #ifdef DEBUG_SAX_TREE
2645: xmlGenericError(xmlGenericErrorContext,
2646: "Setting PI %s as root\n", target);
2647: #endif
2648: xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2649: return;
2650: }
2651: if (parent->type == XML_ELEMENT_NODE) {
2652: #ifdef DEBUG_SAX_TREE
2653: xmlGenericError(xmlGenericErrorContext,
2654: "adding PI %s child to %s\n", target, parent->name);
2655: #endif
2656: xmlAddChild(parent, ret);
2657: } else {
2658: #ifdef DEBUG_SAX_TREE
2659: xmlGenericError(xmlGenericErrorContext,
2660: "adding PI %s sibling to ", target);
2661: xmlDebugDumpOneNode(stderr, parent, 0);
2662: #endif
2663: xmlAddSibling(parent, ret);
2664: }
2665: }
2666:
2667: /**
2668: * xmlSAX2Comment:
2669: * @ctx: the user data (XML parser context)
2670: * @value: the xmlSAX2Comment content
2671: *
2672: * A xmlSAX2Comment has been parsed.
2673: */
2674: void
2675: xmlSAX2Comment(void *ctx, const xmlChar *value)
2676: {
2677: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2678: xmlNodePtr ret;
2679: xmlNodePtr parent;
2680:
2681: if (ctx == NULL) return;
2682: parent = ctxt->node;
2683: #ifdef DEBUG_SAX
2684: xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2Comment(%s)\n", value);
2685: #endif
2686: ret = xmlNewDocComment(ctxt->myDoc, value);
2687: if (ret == NULL) return;
2688: if (ctxt->linenumbers) {
2689: if (ctxt->input != NULL) {
2690: if (ctxt->input->line < 65535)
2691: ret->line = (short) ctxt->input->line;
2692: else
2693: ret->line = 65535;
2694: }
2695: }
2696:
2697: if (ctxt->inSubset == 1) {
2698: xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2699: return;
2700: } else if (ctxt->inSubset == 2) {
2701: xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2702: return;
2703: }
1.1.1.2 ! misho 2704: if (parent == NULL) {
1.1 misho 2705: #ifdef DEBUG_SAX_TREE
2706: xmlGenericError(xmlGenericErrorContext,
2707: "Setting xmlSAX2Comment as root\n");
2708: #endif
2709: xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2710: return;
2711: }
2712: if (parent->type == XML_ELEMENT_NODE) {
2713: #ifdef DEBUG_SAX_TREE
2714: xmlGenericError(xmlGenericErrorContext,
2715: "adding xmlSAX2Comment child to %s\n", parent->name);
2716: #endif
2717: xmlAddChild(parent, ret);
2718: } else {
2719: #ifdef DEBUG_SAX_TREE
2720: xmlGenericError(xmlGenericErrorContext,
2721: "adding xmlSAX2Comment sibling to ");
2722: xmlDebugDumpOneNode(stderr, parent, 0);
2723: #endif
2724: xmlAddSibling(parent, ret);
2725: }
2726: }
2727:
2728: /**
2729: * xmlSAX2CDataBlock:
2730: * @ctx: the user data (XML parser context)
2731: * @value: The pcdata content
2732: * @len: the block length
2733: *
2734: * called when a pcdata block has been parsed
2735: */
2736: void
2737: xmlSAX2CDataBlock(void *ctx, const xmlChar *value, int len)
2738: {
2739: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2740: xmlNodePtr ret, lastChild;
2741:
2742: if (ctx == NULL) return;
2743: #ifdef DEBUG_SAX
2744: xmlGenericError(xmlGenericErrorContext,
2745: "SAX.pcdata(%.10s, %d)\n", value, len);
2746: #endif
2747: lastChild = xmlGetLastChild(ctxt->node);
2748: #ifdef DEBUG_SAX_TREE
2749: xmlGenericError(xmlGenericErrorContext,
2750: "add chars to %s \n", ctxt->node->name);
2751: #endif
2752: if ((lastChild != NULL) &&
2753: (lastChild->type == XML_CDATA_SECTION_NODE)) {
2754: xmlTextConcat(lastChild, value, len);
2755: } else {
2756: ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
2757: xmlAddChild(ctxt->node, ret);
2758: }
2759: }
2760:
2761: static int xmlSAX2DefaultVersionValue = 2;
2762:
2763: #ifdef LIBXML_SAX1_ENABLED
2764: /**
2765: * xmlSAXDefaultVersion:
2766: * @version: the version, 1 or 2
2767: *
2768: * Set the default version of SAX used globally by the library.
2769: * By default, during initialization the default is set to 2.
2770: * Note that it is generally a better coding style to use
2771: * xmlSAXVersion() to set up the version explicitly for a given
2772: * parsing context.
2773: *
2774: * Returns the previous value in case of success and -1 in case of error.
2775: */
2776: int
2777: xmlSAXDefaultVersion(int version)
2778: {
2779: int ret = xmlSAX2DefaultVersionValue;
2780:
2781: if ((version != 1) && (version != 2))
2782: return(-1);
2783: xmlSAX2DefaultVersionValue = version;
2784: return(ret);
2785: }
2786: #endif /* LIBXML_SAX1_ENABLED */
2787:
2788: /**
2789: * xmlSAXVersion:
2790: * @hdlr: the SAX handler
2791: * @version: the version, 1 or 2
2792: *
2793: * Initialize the default XML SAX handler according to the version
2794: *
2795: * Returns 0 in case of success and -1 in case of error.
2796: */
2797: int
2798: xmlSAXVersion(xmlSAXHandler *hdlr, int version)
2799: {
2800: if (hdlr == NULL) return(-1);
2801: if (version == 2) {
2802: hdlr->startElement = NULL;
2803: hdlr->endElement = NULL;
2804: hdlr->startElementNs = xmlSAX2StartElementNs;
2805: hdlr->endElementNs = xmlSAX2EndElementNs;
2806: hdlr->serror = NULL;
2807: hdlr->initialized = XML_SAX2_MAGIC;
2808: #ifdef LIBXML_SAX1_ENABLED
2809: } else if (version == 1) {
2810: hdlr->startElement = xmlSAX2StartElement;
2811: hdlr->endElement = xmlSAX2EndElement;
2812: hdlr->initialized = 1;
2813: #endif /* LIBXML_SAX1_ENABLED */
2814: } else
2815: return(-1);
2816: hdlr->internalSubset = xmlSAX2InternalSubset;
2817: hdlr->externalSubset = xmlSAX2ExternalSubset;
2818: hdlr->isStandalone = xmlSAX2IsStandalone;
2819: hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
2820: hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
2821: hdlr->resolveEntity = xmlSAX2ResolveEntity;
2822: hdlr->getEntity = xmlSAX2GetEntity;
2823: hdlr->getParameterEntity = xmlSAX2GetParameterEntity;
2824: hdlr->entityDecl = xmlSAX2EntityDecl;
2825: hdlr->attributeDecl = xmlSAX2AttributeDecl;
2826: hdlr->elementDecl = xmlSAX2ElementDecl;
2827: hdlr->notationDecl = xmlSAX2NotationDecl;
2828: hdlr->unparsedEntityDecl = xmlSAX2UnparsedEntityDecl;
2829: hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2830: hdlr->startDocument = xmlSAX2StartDocument;
2831: hdlr->endDocument = xmlSAX2EndDocument;
2832: hdlr->reference = xmlSAX2Reference;
2833: hdlr->characters = xmlSAX2Characters;
2834: hdlr->cdataBlock = xmlSAX2CDataBlock;
2835: hdlr->ignorableWhitespace = xmlSAX2Characters;
2836: hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
2837: hdlr->comment = xmlSAX2Comment;
2838: hdlr->warning = xmlParserWarning;
2839: hdlr->error = xmlParserError;
2840: hdlr->fatalError = xmlParserError;
2841:
2842: return(0);
2843: }
2844:
2845: /**
2846: * xmlSAX2InitDefaultSAXHandler:
2847: * @hdlr: the SAX handler
2848: * @warning: flag if non-zero sets the handler warning procedure
2849: *
2850: * Initialize the default XML SAX2 handler
2851: */
2852: void
2853: xmlSAX2InitDefaultSAXHandler(xmlSAXHandler *hdlr, int warning)
2854: {
2855: if ((hdlr == NULL) || (hdlr->initialized != 0))
2856: return;
2857:
2858: xmlSAXVersion(hdlr, xmlSAX2DefaultVersionValue);
2859: if (warning == 0)
2860: hdlr->warning = NULL;
2861: else
2862: hdlr->warning = xmlParserWarning;
2863: }
2864:
2865: /**
2866: * xmlDefaultSAXHandlerInit:
2867: *
2868: * Initialize the default SAX2 handler
2869: */
2870: void
2871: xmlDefaultSAXHandlerInit(void)
2872: {
2873: #ifdef LIBXML_SAX1_ENABLED
2874: xmlSAXVersion((xmlSAXHandlerPtr) &xmlDefaultSAXHandler, 1);
2875: #endif /* LIBXML_SAX1_ENABLED */
2876: }
2877:
2878: #ifdef LIBXML_HTML_ENABLED
2879:
2880: /**
2881: * xmlSAX2InitHtmlDefaultSAXHandler:
2882: * @hdlr: the SAX handler
2883: *
2884: * Initialize the default HTML SAX2 handler
2885: */
2886: void
2887: xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr)
2888: {
2889: if ((hdlr == NULL) || (hdlr->initialized != 0))
2890: return;
2891:
2892: hdlr->internalSubset = xmlSAX2InternalSubset;
2893: hdlr->externalSubset = NULL;
2894: hdlr->isStandalone = NULL;
2895: hdlr->hasInternalSubset = NULL;
2896: hdlr->hasExternalSubset = NULL;
2897: hdlr->resolveEntity = NULL;
2898: hdlr->getEntity = xmlSAX2GetEntity;
2899: hdlr->getParameterEntity = NULL;
2900: hdlr->entityDecl = NULL;
2901: hdlr->attributeDecl = NULL;
2902: hdlr->elementDecl = NULL;
2903: hdlr->notationDecl = NULL;
2904: hdlr->unparsedEntityDecl = NULL;
2905: hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2906: hdlr->startDocument = xmlSAX2StartDocument;
2907: hdlr->endDocument = xmlSAX2EndDocument;
2908: hdlr->startElement = xmlSAX2StartElement;
2909: hdlr->endElement = xmlSAX2EndElement;
2910: hdlr->reference = NULL;
2911: hdlr->characters = xmlSAX2Characters;
2912: hdlr->cdataBlock = xmlSAX2CDataBlock;
2913: hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
2914: hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
2915: hdlr->comment = xmlSAX2Comment;
2916: hdlr->warning = xmlParserWarning;
2917: hdlr->error = xmlParserError;
2918: hdlr->fatalError = xmlParserError;
2919:
2920: hdlr->initialized = 1;
2921: }
2922:
2923: /**
2924: * htmlDefaultSAXHandlerInit:
2925: *
2926: * Initialize the default SAX handler
2927: */
2928: void
2929: htmlDefaultSAXHandlerInit(void)
2930: {
2931: xmlSAX2InitHtmlDefaultSAXHandler((xmlSAXHandlerPtr) &htmlDefaultSAXHandler);
2932: }
2933:
2934: #endif /* LIBXML_HTML_ENABLED */
2935:
2936: #ifdef LIBXML_DOCB_ENABLED
2937:
2938: /**
2939: * xmlSAX2InitDocbDefaultSAXHandler:
2940: * @hdlr: the SAX handler
2941: *
2942: * Initialize the default DocBook SAX2 handler
2943: */
2944: void
2945: xmlSAX2InitDocbDefaultSAXHandler(xmlSAXHandler *hdlr)
2946: {
2947: if ((hdlr == NULL) || (hdlr->initialized != 0))
2948: return;
2949:
2950: hdlr->internalSubset = xmlSAX2InternalSubset;
2951: hdlr->externalSubset = NULL;
2952: hdlr->isStandalone = xmlSAX2IsStandalone;
2953: hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
2954: hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
2955: hdlr->resolveEntity = xmlSAX2ResolveEntity;
2956: hdlr->getEntity = xmlSAX2GetEntity;
2957: hdlr->getParameterEntity = NULL;
2958: hdlr->entityDecl = xmlSAX2EntityDecl;
2959: hdlr->attributeDecl = NULL;
2960: hdlr->elementDecl = NULL;
2961: hdlr->notationDecl = NULL;
2962: hdlr->unparsedEntityDecl = NULL;
2963: hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2964: hdlr->startDocument = xmlSAX2StartDocument;
2965: hdlr->endDocument = xmlSAX2EndDocument;
2966: hdlr->startElement = xmlSAX2StartElement;
2967: hdlr->endElement = xmlSAX2EndElement;
2968: hdlr->reference = xmlSAX2Reference;
2969: hdlr->characters = xmlSAX2Characters;
2970: hdlr->cdataBlock = NULL;
2971: hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
2972: hdlr->processingInstruction = NULL;
2973: hdlr->comment = xmlSAX2Comment;
2974: hdlr->warning = xmlParserWarning;
2975: hdlr->error = xmlParserError;
2976: hdlr->fatalError = xmlParserError;
2977:
2978: hdlr->initialized = 1;
2979: }
2980:
2981: /**
2982: * docbDefaultSAXHandlerInit:
2983: *
2984: * Initialize the default SAX handler
2985: */
2986: void
2987: docbDefaultSAXHandlerInit(void)
2988: {
2989: xmlSAX2InitDocbDefaultSAXHandler((xmlSAXHandlerPtr) &docbDefaultSAXHandler);
2990: }
2991:
2992: #endif /* LIBXML_DOCB_ENABLED */
2993: #define bottom_SAX2
2994: #include "elfgcchack.h"
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>