Annotation of embedaddon/libxml2/SAX2.c, revision 1.1.1.1
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: xmlParserNodeInfo node_info;
1760: xmlNodePtr cur;
1761:
1762: if (ctx == NULL) return;
1763: cur = ctxt->node;
1764: #ifdef DEBUG_SAX
1765: if (name == NULL)
1766: xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(NULL)\n");
1767: else
1768: xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(%s)\n", name);
1769: #endif
1770:
1771: /* Capture end position and add node */
1772: if (cur != NULL && ctxt->record_info) {
1773: node_info.end_pos = ctxt->input->cur - ctxt->input->base;
1774: node_info.end_line = ctxt->input->line;
1775: node_info.node = cur;
1776: xmlParserAddNodeInfo(ctxt, &node_info);
1777: }
1778: ctxt->nodemem = -1;
1779:
1780: #ifdef LIBXML_VALID_ENABLED
1781: if (ctxt->validate && ctxt->wellFormed &&
1782: ctxt->myDoc && ctxt->myDoc->intSubset)
1783: ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
1784: cur);
1785: #endif /* LIBXML_VALID_ENABLED */
1786:
1787:
1788: /*
1789: * end of parsing of this node.
1790: */
1791: #ifdef DEBUG_SAX_TREE
1792: xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);
1793: #endif
1794: nodePop(ctxt);
1795: }
1796: #endif /* LIBXML_SAX1_ENABLED || LIBXML_HTML_ENABLE */
1797:
1798: /*
1799: * xmlSAX2TextNode:
1800: * @ctxt: the parser context
1801: * @str: the input string
1802: * @len: the string length
1803: *
1804: * Remove the entities from an attribute value
1805: *
1806: * Returns the newly allocated string or NULL if not needed or error
1807: */
1808: static xmlNodePtr
1809: xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
1810: xmlNodePtr ret;
1811: const xmlChar *intern = NULL;
1812:
1813: /*
1814: * Allocate
1815: */
1816: if (ctxt->freeElems != NULL) {
1817: ret = ctxt->freeElems;
1818: ctxt->freeElems = ret->next;
1819: ctxt->freeElemsNr--;
1820: } else {
1821: ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1822: }
1823: if (ret == NULL) {
1824: xmlErrMemory(ctxt, "xmlSAX2Characters");
1825: return(NULL);
1826: }
1827: memset(ret, 0, sizeof(xmlNode));
1828: /*
1829: * intern the formatting blanks found between tags, or the
1830: * very short strings
1831: */
1832: if (ctxt->dictNames) {
1833: xmlChar cur = str[len];
1834:
1835: if ((len < (int) (2 * sizeof(void *))) &&
1836: (ctxt->options & XML_PARSE_COMPACT)) {
1837: /* store the string in the node overrithing properties and nsDef */
1838: xmlChar *tmp = (xmlChar *) &(ret->properties);
1839: memcpy(tmp, str, len);
1840: tmp[len] = 0;
1841: intern = tmp;
1842: } else if ((len <= 3) && ((cur == '"') || (cur == '\'') ||
1843: ((cur == '<') && (str[len + 1] != '!')))) {
1844: intern = xmlDictLookup(ctxt->dict, str, len);
1845: } else if (IS_BLANK_CH(*str) && (len < 60) && (cur == '<') &&
1846: (str[len + 1] != '!')) {
1847: int i;
1848:
1849: for (i = 1;i < len;i++) {
1850: if (!IS_BLANK_CH(str[i])) goto skip;
1851: }
1852: intern = xmlDictLookup(ctxt->dict, str, len);
1853: }
1854: }
1855: skip:
1856: ret->type = XML_TEXT_NODE;
1857:
1858: ret->name = xmlStringText;
1859: if (intern == NULL) {
1860: ret->content = xmlStrndup(str, len);
1861: if (ret->content == NULL) {
1862: xmlSAX2ErrMemory(ctxt, "xmlSAX2TextNode");
1863: xmlFree(ret);
1864: return(NULL);
1865: }
1866: } else
1867: ret->content = (xmlChar *) intern;
1868:
1869: if (ctxt->input != NULL)
1870: ret->line = ctxt->input->line;
1871:
1872: if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1873: xmlRegisterNodeDefaultValue(ret);
1874: return(ret);
1875: }
1876:
1877: #ifdef LIBXML_VALID_ENABLED
1878: /*
1879: * xmlSAX2DecodeAttrEntities:
1880: * @ctxt: the parser context
1881: * @str: the input string
1882: * @len: the string length
1883: *
1884: * Remove the entities from an attribute value
1885: *
1886: * Returns the newly allocated string or NULL if not needed or error
1887: */
1888: static xmlChar *
1889: xmlSAX2DecodeAttrEntities(xmlParserCtxtPtr ctxt, const xmlChar *str,
1890: const xmlChar *end) {
1891: const xmlChar *in;
1892: xmlChar *ret;
1893:
1894: in = str;
1895: while (in < end)
1896: if (*in++ == '&')
1897: goto decode;
1898: return(NULL);
1899: decode:
1900: ctxt->depth++;
1901: ret = xmlStringLenDecodeEntities(ctxt, str, end - str,
1902: XML_SUBSTITUTE_REF, 0,0,0);
1903: ctxt->depth--;
1904: return(ret);
1905: }
1906: #endif /* LIBXML_VALID_ENABLED */
1907:
1908: /**
1909: * xmlSAX2AttributeNs:
1910: * @ctx: the user data (XML parser context)
1911: * @localname: the local name of the attribute
1912: * @prefix: the attribute namespace prefix if available
1913: * @URI: the attribute namespace name if available
1914: * @value: Start of the attribute value
1915: * @valueend: end of the attribute value
1916: *
1917: * Handle an attribute that has been read by the parser.
1918: * The default handling is to convert the attribute into an
1919: * DOM subtree and past it in a new xmlAttr element added to
1920: * the element.
1921: */
1922: static void
1923: xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
1924: const xmlChar * localname,
1925: const xmlChar * prefix,
1926: const xmlChar * value,
1927: const xmlChar * valueend)
1928: {
1929: xmlAttrPtr ret;
1930: xmlNsPtr namespace = NULL;
1931: xmlChar *dup = NULL;
1932:
1933: /*
1934: * Note: if prefix == NULL, the attribute is not in the default namespace
1935: */
1936: if (prefix != NULL)
1937: namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, prefix);
1938:
1939: /*
1940: * allocate the node
1941: */
1942: if (ctxt->freeAttrs != NULL) {
1943: ret = ctxt->freeAttrs;
1944: ctxt->freeAttrs = ret->next;
1945: ctxt->freeAttrsNr--;
1946: memset(ret, 0, sizeof(xmlAttr));
1947: ret->type = XML_ATTRIBUTE_NODE;
1948:
1949: ret->parent = ctxt->node;
1950: ret->doc = ctxt->myDoc;
1951: ret->ns = namespace;
1952:
1953: if (ctxt->dictNames)
1954: ret->name = localname;
1955: else
1956: ret->name = xmlStrdup(localname);
1957:
1958: /* link at the end to preserv order, TODO speed up with a last */
1959: if (ctxt->node->properties == NULL) {
1960: ctxt->node->properties = ret;
1961: } else {
1962: xmlAttrPtr prev = ctxt->node->properties;
1963:
1964: while (prev->next != NULL) prev = prev->next;
1965: prev->next = ret;
1966: ret->prev = prev;
1967: }
1968:
1969: if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1970: xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
1971: } else {
1972: if (ctxt->dictNames)
1973: ret = xmlNewNsPropEatName(ctxt->node, namespace,
1974: (xmlChar *) localname, NULL);
1975: else
1976: ret = xmlNewNsProp(ctxt->node, namespace, localname, NULL);
1977: if (ret == NULL) {
1978: xmlErrMemory(ctxt, "xmlSAX2AttributeNs");
1979: return;
1980: }
1981: }
1982:
1983: if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
1984: xmlNodePtr tmp;
1985:
1986: /*
1987: * We know that if there is an entity reference, then
1988: * the string has been dup'ed and terminates with 0
1989: * otherwise with ' or "
1990: */
1991: if (*valueend != 0) {
1992: tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
1993: ret->children = tmp;
1994: ret->last = tmp;
1995: if (tmp != NULL) {
1996: tmp->doc = ret->doc;
1997: tmp->parent = (xmlNodePtr) ret;
1998: }
1999: } else {
2000: ret->children = xmlStringLenGetNodeList(ctxt->myDoc, value,
2001: valueend - value);
2002: tmp = ret->children;
2003: while (tmp != NULL) {
2004: tmp->doc = ret->doc;
2005: tmp->parent = (xmlNodePtr) ret;
2006: if (tmp->next == NULL)
2007: ret->last = tmp;
2008: tmp = tmp->next;
2009: }
2010: }
2011: } else if (value != NULL) {
2012: xmlNodePtr tmp;
2013:
2014: tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
2015: ret->children = tmp;
2016: ret->last = tmp;
2017: if (tmp != NULL) {
2018: tmp->doc = ret->doc;
2019: tmp->parent = (xmlNodePtr) ret;
2020: }
2021: }
2022:
2023: #ifdef LIBXML_VALID_ENABLED
2024: if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
2025: ctxt->myDoc && ctxt->myDoc->intSubset) {
2026: /*
2027: * If we don't substitute entities, the validation should be
2028: * done on a value with replaced entities anyway.
2029: */
2030: if (!ctxt->replaceEntities) {
2031: dup = xmlSAX2DecodeAttrEntities(ctxt, value, valueend);
2032: if (dup == NULL) {
2033: if (*valueend == 0) {
2034: ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2035: ctxt->myDoc, ctxt->node, ret, value);
2036: } else {
2037: /*
2038: * That should already be normalized.
2039: * cheaper to finally allocate here than duplicate
2040: * entry points in the full validation code
2041: */
2042: dup = xmlStrndup(value, valueend - value);
2043:
2044: ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2045: ctxt->myDoc, ctxt->node, ret, dup);
2046: }
2047: } else {
2048: /*
2049: * dup now contains a string of the flattened attribute
2050: * content with entities substitued. Check if we need to
2051: * apply an extra layer of normalization.
2052: * It need to be done twice ... it's an extra burden related
2053: * to the ability to keep references in attributes
2054: */
2055: if (ctxt->attsSpecial != NULL) {
2056: xmlChar *nvalnorm;
2057: xmlChar fn[50];
2058: xmlChar *fullname;
2059:
2060: fullname = xmlBuildQName(localname, prefix, fn, 50);
2061: if (fullname != NULL) {
2062: ctxt->vctxt.valid = 1;
2063: nvalnorm = xmlValidCtxtNormalizeAttributeValue(
2064: &ctxt->vctxt, ctxt->myDoc,
2065: ctxt->node, fullname, dup);
2066: if (ctxt->vctxt.valid != 1)
2067: ctxt->valid = 0;
2068:
2069: if ((fullname != fn) && (fullname != localname))
2070: xmlFree(fullname);
2071: if (nvalnorm != NULL) {
2072: xmlFree(dup);
2073: dup = nvalnorm;
2074: }
2075: }
2076: }
2077:
2078: ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2079: ctxt->myDoc, ctxt->node, ret, dup);
2080: }
2081: } else {
2082: /*
2083: * if entities already have been substitued, then
2084: * the attribute as passed is already normalized
2085: */
2086: dup = xmlStrndup(value, valueend - value);
2087:
2088: ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2089: ctxt->myDoc, ctxt->node, ret, dup);
2090: }
2091: } else
2092: #endif /* LIBXML_VALID_ENABLED */
2093: if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
2094: (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
2095: ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
2096: /*
2097: * when validating, the ID registration is done at the attribute
2098: * validation level. Otherwise we have to do specific handling here.
2099: */
2100: if ((prefix == ctxt->str_xml) &&
2101: (localname[0] == 'i') && (localname[1] == 'd') &&
2102: (localname[2] == 0)) {
2103: /*
2104: * Add the xml:id value
2105: *
2106: * Open issue: normalization of the value.
2107: */
2108: if (dup == NULL)
2109: dup = xmlStrndup(value, valueend - value);
2110: #ifdef LIBXML_VALID_ENABLED
2111: if (xmlValidateNCName(dup, 1) != 0) {
2112: xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
2113: "xml:id : attribute value %s is not an NCName\n",
2114: (const char *) dup, NULL);
2115: }
2116: #endif
2117: xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
2118: } else if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) {
2119: /* might be worth duplicate entry points and not copy */
2120: if (dup == NULL)
2121: dup = xmlStrndup(value, valueend - value);
2122: xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
2123: } else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) {
2124: if (dup == NULL)
2125: dup = xmlStrndup(value, valueend - value);
2126: xmlAddRef(&ctxt->vctxt, ctxt->myDoc, dup, ret);
2127: }
2128: }
2129: if (dup != NULL)
2130: xmlFree(dup);
2131: }
2132:
2133: /**
2134: * xmlSAX2StartElementNs:
2135: * @ctx: the user data (XML parser context)
2136: * @localname: the local name of the element
2137: * @prefix: the element namespace prefix if available
2138: * @URI: the element namespace name if available
2139: * @nb_namespaces: number of namespace definitions on that node
2140: * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
2141: * @nb_attributes: the number of attributes on that node
2142: * @nb_defaulted: the number of defaulted attributes.
2143: * @attributes: pointer to the array of (localname/prefix/URI/value/end)
2144: * attribute values.
2145: *
2146: * SAX2 callback when an element start has been detected by the parser.
2147: * It provides the namespace informations for the element, as well as
2148: * the new namespace declarations on the element.
2149: */
2150: void
2151: xmlSAX2StartElementNs(void *ctx,
2152: const xmlChar *localname,
2153: const xmlChar *prefix,
2154: const xmlChar *URI,
2155: int nb_namespaces,
2156: const xmlChar **namespaces,
2157: int nb_attributes,
2158: int nb_defaulted,
2159: const xmlChar **attributes)
2160: {
2161: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2162: xmlNodePtr ret;
2163: xmlNodePtr parent;
2164: xmlNsPtr last = NULL, ns;
2165: const xmlChar *uri, *pref;
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: /*
2185: * allocate the node
2186: */
2187: if (ctxt->freeElems != NULL) {
2188: ret = ctxt->freeElems;
2189: ctxt->freeElems = ret->next;
2190: ctxt->freeElemsNr--;
2191: memset(ret, 0, sizeof(xmlNode));
2192: ret->type = XML_ELEMENT_NODE;
2193:
2194: if (ctxt->dictNames)
2195: ret->name = localname;
2196: else {
2197: ret->name = xmlStrdup(localname);
2198: if (ret->name == NULL) {
2199: xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
2200: return;
2201: }
2202: }
2203: if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2204: xmlRegisterNodeDefaultValue(ret);
2205: } else {
2206: if (ctxt->dictNames)
2207: ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
2208: (xmlChar *) localname, NULL);
2209: else
2210: ret = xmlNewDocNode(ctxt->myDoc, NULL, localname, NULL);
2211: if (ret == NULL) {
2212: xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
2213: return;
2214: }
2215: }
2216: if (ctxt->linenumbers) {
2217: if (ctxt->input != NULL) {
2218: if (ctxt->input->line < 65535)
2219: ret->line = (short) ctxt->input->line;
2220: else
2221: ret->line = 65535;
2222: }
2223: }
2224:
2225: if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
2226: xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2227: }
2228: /*
2229: * Build the namespace list
2230: */
2231: for (i = 0,j = 0;j < nb_namespaces;j++) {
2232: pref = namespaces[i++];
2233: uri = namespaces[i++];
2234: ns = xmlNewNs(NULL, uri, pref);
2235: if (ns != NULL) {
2236: if (last == NULL) {
2237: ret->nsDef = last = ns;
2238: } else {
2239: last->next = ns;
2240: last = ns;
2241: }
2242: if ((URI != NULL) && (prefix == pref))
2243: ret->ns = ns;
2244: } else {
2245: /*
2246: * any out of memory error would already have been raised
2247: * but we can't be garanteed it's the actual error due to the
2248: * API, best is to skip in this case
2249: */
2250: continue;
2251: }
2252: #ifdef LIBXML_VALID_ENABLED
2253: if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
2254: ctxt->myDoc && ctxt->myDoc->intSubset) {
2255: ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
2256: ret, prefix, ns, uri);
2257: }
2258: #endif /* LIBXML_VALID_ENABLED */
2259: }
2260: ctxt->nodemem = -1;
2261:
2262: /*
2263: * We are parsing a new node.
2264: */
2265: nodePush(ctxt, ret);
2266:
2267: /*
2268: * Link the child element
2269: */
2270: if (parent != NULL) {
2271: if (parent->type == XML_ELEMENT_NODE) {
2272: xmlAddChild(parent, ret);
2273: } else {
2274: xmlAddSibling(parent, ret);
2275: }
2276: }
2277:
2278: /*
2279: * Insert the defaulted attributes from the DTD only if requested:
2280: */
2281: if ((nb_defaulted != 0) &&
2282: ((ctxt->loadsubset & XML_COMPLETE_ATTRS) == 0))
2283: nb_attributes -= nb_defaulted;
2284:
2285: /*
2286: * Search the namespace if it wasn't already found
2287: * Note that, if prefix is NULL, this searches for the default Ns
2288: */
2289: if ((URI != NULL) && (ret->ns == NULL)) {
2290: ret->ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
2291: if ((ret->ns == NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) {
2292: ret->ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
2293: }
2294: if (ret->ns == NULL) {
2295: ns = xmlNewNs(ret, NULL, prefix);
2296: if (ns == NULL) {
2297:
2298: xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
2299: return;
2300: }
2301: if (prefix != NULL)
2302: xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
2303: "Namespace prefix %s was not found\n",
2304: prefix, NULL);
2305: else
2306: xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
2307: "Namespace default prefix was not found\n",
2308: NULL, NULL);
2309: }
2310: }
2311:
2312: /*
2313: * process all the other attributes
2314: */
2315: if (nb_attributes > 0) {
2316: for (j = 0,i = 0;i < nb_attributes;i++,j+=5) {
2317: xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1],
2318: attributes[j+3], attributes[j+4]);
2319: }
2320: }
2321:
2322: #ifdef LIBXML_VALID_ENABLED
2323: /*
2324: * If it's the Document root, finish the DTD validation and
2325: * check the document root element for validity
2326: */
2327: if ((ctxt->validate) && (ctxt->vctxt.finishDtd == XML_CTXT_FINISH_DTD_0)) {
2328: int chk;
2329:
2330: chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
2331: if (chk <= 0)
2332: ctxt->valid = 0;
2333: if (chk < 0)
2334: ctxt->wellFormed = 0;
2335: ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
2336: ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_1;
2337: }
2338: #endif /* LIBXML_VALID_ENABLED */
2339: }
2340:
2341: /**
2342: * xmlSAX2EndElementNs:
2343: * @ctx: the user data (XML parser context)
2344: * @localname: the local name of the element
2345: * @prefix: the element namespace prefix if available
2346: * @URI: the element namespace name if available
2347: *
2348: * SAX2 callback when an element end has been detected by the parser.
2349: * It provides the namespace informations for the element.
2350: */
2351: void
2352: xmlSAX2EndElementNs(void *ctx,
2353: const xmlChar * localname ATTRIBUTE_UNUSED,
2354: const xmlChar * prefix ATTRIBUTE_UNUSED,
2355: const xmlChar * URI ATTRIBUTE_UNUSED)
2356: {
2357: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2358: xmlParserNodeInfo node_info;
2359: xmlNodePtr cur;
2360:
2361: if (ctx == NULL) return;
2362: cur = ctxt->node;
2363: /* Capture end position and add node */
2364: if ((ctxt->record_info) && (cur != NULL)) {
2365: node_info.end_pos = ctxt->input->cur - ctxt->input->base;
2366: node_info.end_line = ctxt->input->line;
2367: node_info.node = cur;
2368: xmlParserAddNodeInfo(ctxt, &node_info);
2369: }
2370: ctxt->nodemem = -1;
2371:
2372: #ifdef LIBXML_VALID_ENABLED
2373: if (ctxt->validate && ctxt->wellFormed &&
2374: ctxt->myDoc && ctxt->myDoc->intSubset)
2375: ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, cur);
2376: #endif /* LIBXML_VALID_ENABLED */
2377:
2378: /*
2379: * end of parsing of this node.
2380: */
2381: nodePop(ctxt);
2382: }
2383:
2384: /**
2385: * xmlSAX2Reference:
2386: * @ctx: the user data (XML parser context)
2387: * @name: The entity name
2388: *
2389: * called when an entity xmlSAX2Reference is detected.
2390: */
2391: void
2392: xmlSAX2Reference(void *ctx, const xmlChar *name)
2393: {
2394: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2395: xmlNodePtr ret;
2396:
2397: if (ctx == NULL) return;
2398: #ifdef DEBUG_SAX
2399: xmlGenericError(xmlGenericErrorContext,
2400: "SAX.xmlSAX2Reference(%s)\n", name);
2401: #endif
2402: if (name[0] == '#')
2403: ret = xmlNewCharRef(ctxt->myDoc, name);
2404: else
2405: ret = xmlNewReference(ctxt->myDoc, name);
2406: #ifdef DEBUG_SAX_TREE
2407: xmlGenericError(xmlGenericErrorContext,
2408: "add xmlSAX2Reference %s to %s \n", name, ctxt->node->name);
2409: #endif
2410: if (xmlAddChild(ctxt->node, ret) == NULL) {
2411: xmlFreeNode(ret);
2412: }
2413: }
2414:
2415: /**
2416: * xmlSAX2Characters:
2417: * @ctx: the user data (XML parser context)
2418: * @ch: a xmlChar string
2419: * @len: the number of xmlChar
2420: *
2421: * receiving some chars from the parser.
2422: */
2423: void
2424: xmlSAX2Characters(void *ctx, const xmlChar *ch, int len)
2425: {
2426: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2427: xmlNodePtr lastChild;
2428:
2429: if (ctx == NULL) return;
2430: #ifdef DEBUG_SAX
2431: xmlGenericError(xmlGenericErrorContext,
2432: "SAX.xmlSAX2Characters(%.30s, %d)\n", ch, len);
2433: #endif
2434: /*
2435: * Handle the data if any. If there is no child
2436: * add it as content, otherwise if the last child is text,
2437: * concatenate it, else create a new node of type text.
2438: */
2439:
2440: if (ctxt->node == NULL) {
2441: #ifdef DEBUG_SAX_TREE
2442: xmlGenericError(xmlGenericErrorContext,
2443: "add chars: ctxt->node == NULL !\n");
2444: #endif
2445: return;
2446: }
2447: lastChild = ctxt->node->last;
2448: #ifdef DEBUG_SAX_TREE
2449: xmlGenericError(xmlGenericErrorContext,
2450: "add chars to %s \n", ctxt->node->name);
2451: #endif
2452:
2453: /*
2454: * Here we needed an accelerator mechanism in case of very large
2455: * elements. Use an attribute in the structure !!!
2456: */
2457: if (lastChild == NULL) {
2458: lastChild = xmlSAX2TextNode(ctxt, ch, len);
2459: if (lastChild != NULL) {
2460: ctxt->node->children = lastChild;
2461: ctxt->node->last = lastChild;
2462: lastChild->parent = ctxt->node;
2463: lastChild->doc = ctxt->node->doc;
2464: ctxt->nodelen = len;
2465: ctxt->nodemem = len + 1;
2466: } else {
2467: xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
2468: return;
2469: }
2470: } else {
2471: int coalesceText = (lastChild != NULL) &&
2472: (lastChild->type == XML_TEXT_NODE) &&
2473: (lastChild->name == xmlStringText);
2474: if ((coalesceText) && (ctxt->nodemem != 0)) {
2475: /*
2476: * The whole point of maintaining nodelen and nodemem,
2477: * xmlTextConcat is too costly, i.e. compute length,
2478: * reallocate a new buffer, move data, append ch. Here
2479: * We try to minimaze realloc() uses and avoid copying
2480: * and recomputing length over and over.
2481: */
2482: if (lastChild->content == (xmlChar *)&(lastChild->properties)) {
2483: lastChild->content = xmlStrdup(lastChild->content);
2484: lastChild->properties = NULL;
2485: } else if ((ctxt->nodemem == ctxt->nodelen + 1) &&
2486: (xmlDictOwns(ctxt->dict, lastChild->content))) {
2487: lastChild->content = xmlStrdup(lastChild->content);
2488: }
2489: if (((size_t)ctxt->nodelen + (size_t)len > XML_MAX_TEXT_LENGTH) &&
2490: ((ctxt->options & XML_PARSE_HUGE) == 0)) {
2491: xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters: huge text node");
2492: return;
2493: }
2494: if ((size_t)ctxt->nodelen > SIZE_T_MAX - (size_t)len ||
2495: (size_t)ctxt->nodemem + (size_t)len > SIZE_T_MAX / 2) {
2496: xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters overflow prevented");
2497: return;
2498: }
2499: if (ctxt->nodelen + len >= ctxt->nodemem) {
2500: xmlChar *newbuf;
2501: size_t size;
2502:
2503: size = ctxt->nodemem + len;
2504: size *= 2;
2505: newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
2506: if (newbuf == NULL) {
2507: xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
2508: return;
2509: }
2510: ctxt->nodemem = size;
2511: lastChild->content = newbuf;
2512: }
2513: memcpy(&lastChild->content[ctxt->nodelen], ch, len);
2514: ctxt->nodelen += len;
2515: lastChild->content[ctxt->nodelen] = 0;
2516: } else if (coalesceText) {
2517: if (xmlTextConcat(lastChild, ch, len)) {
2518: xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
2519: }
2520: if (ctxt->node->children != NULL) {
2521: ctxt->nodelen = xmlStrlen(lastChild->content);
2522: ctxt->nodemem = ctxt->nodelen + 1;
2523: }
2524: } else {
2525: /* Mixed content, first time */
2526: lastChild = xmlSAX2TextNode(ctxt, ch, len);
2527: if (lastChild != NULL) {
2528: xmlAddChild(ctxt->node, lastChild);
2529: if (ctxt->node->children != NULL) {
2530: ctxt->nodelen = len;
2531: ctxt->nodemem = len + 1;
2532: }
2533: }
2534: }
2535: }
2536: }
2537:
2538: /**
2539: * xmlSAX2IgnorableWhitespace:
2540: * @ctx: the user data (XML parser context)
2541: * @ch: a xmlChar string
2542: * @len: the number of xmlChar
2543: *
2544: * receiving some ignorable whitespaces from the parser.
2545: * UNUSED: by default the DOM building will use xmlSAX2Characters
2546: */
2547: void
2548: xmlSAX2IgnorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
2549: {
2550: /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
2551: #ifdef DEBUG_SAX
2552: xmlGenericError(xmlGenericErrorContext,
2553: "SAX.xmlSAX2IgnorableWhitespace(%.30s, %d)\n", ch, len);
2554: #endif
2555: }
2556:
2557: /**
2558: * xmlSAX2ProcessingInstruction:
2559: * @ctx: the user data (XML parser context)
2560: * @target: the target name
2561: * @data: the PI data's
2562: *
2563: * A processing instruction has been parsed.
2564: */
2565: void
2566: xmlSAX2ProcessingInstruction(void *ctx, const xmlChar *target,
2567: const xmlChar *data)
2568: {
2569: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2570: xmlNodePtr ret;
2571: xmlNodePtr parent;
2572:
2573: if (ctx == NULL) return;
2574: parent = ctxt->node;
2575: #ifdef DEBUG_SAX
2576: xmlGenericError(xmlGenericErrorContext,
2577: "SAX.xmlSAX2ProcessingInstruction(%s, %s)\n", target, data);
2578: #endif
2579:
2580: ret = xmlNewDocPI(ctxt->myDoc, target, data);
2581: if (ret == NULL) return;
2582:
2583: if (ctxt->linenumbers) {
2584: if (ctxt->input != NULL) {
2585: if (ctxt->input->line < 65535)
2586: ret->line = (short) ctxt->input->line;
2587: else
2588: ret->line = 65535;
2589: }
2590: }
2591: if (ctxt->inSubset == 1) {
2592: xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2593: return;
2594: } else if (ctxt->inSubset == 2) {
2595: xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2596: return;
2597: }
2598: if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
2599: #ifdef DEBUG_SAX_TREE
2600: xmlGenericError(xmlGenericErrorContext,
2601: "Setting PI %s as root\n", target);
2602: #endif
2603: xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2604: return;
2605: }
2606: if (parent->type == XML_ELEMENT_NODE) {
2607: #ifdef DEBUG_SAX_TREE
2608: xmlGenericError(xmlGenericErrorContext,
2609: "adding PI %s child to %s\n", target, parent->name);
2610: #endif
2611: xmlAddChild(parent, ret);
2612: } else {
2613: #ifdef DEBUG_SAX_TREE
2614: xmlGenericError(xmlGenericErrorContext,
2615: "adding PI %s sibling to ", target);
2616: xmlDebugDumpOneNode(stderr, parent, 0);
2617: #endif
2618: xmlAddSibling(parent, ret);
2619: }
2620: }
2621:
2622: /**
2623: * xmlSAX2Comment:
2624: * @ctx: the user data (XML parser context)
2625: * @value: the xmlSAX2Comment content
2626: *
2627: * A xmlSAX2Comment has been parsed.
2628: */
2629: void
2630: xmlSAX2Comment(void *ctx, const xmlChar *value)
2631: {
2632: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2633: xmlNodePtr ret;
2634: xmlNodePtr parent;
2635:
2636: if (ctx == NULL) return;
2637: parent = ctxt->node;
2638: #ifdef DEBUG_SAX
2639: xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2Comment(%s)\n", value);
2640: #endif
2641: ret = xmlNewDocComment(ctxt->myDoc, value);
2642: if (ret == NULL) return;
2643: if (ctxt->linenumbers) {
2644: if (ctxt->input != NULL) {
2645: if (ctxt->input->line < 65535)
2646: ret->line = (short) ctxt->input->line;
2647: else
2648: ret->line = 65535;
2649: }
2650: }
2651:
2652: if (ctxt->inSubset == 1) {
2653: xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2654: return;
2655: } else if (ctxt->inSubset == 2) {
2656: xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2657: return;
2658: }
2659: if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
2660: #ifdef DEBUG_SAX_TREE
2661: xmlGenericError(xmlGenericErrorContext,
2662: "Setting xmlSAX2Comment as root\n");
2663: #endif
2664: xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2665: return;
2666: }
2667: if (parent->type == XML_ELEMENT_NODE) {
2668: #ifdef DEBUG_SAX_TREE
2669: xmlGenericError(xmlGenericErrorContext,
2670: "adding xmlSAX2Comment child to %s\n", parent->name);
2671: #endif
2672: xmlAddChild(parent, ret);
2673: } else {
2674: #ifdef DEBUG_SAX_TREE
2675: xmlGenericError(xmlGenericErrorContext,
2676: "adding xmlSAX2Comment sibling to ");
2677: xmlDebugDumpOneNode(stderr, parent, 0);
2678: #endif
2679: xmlAddSibling(parent, ret);
2680: }
2681: }
2682:
2683: /**
2684: * xmlSAX2CDataBlock:
2685: * @ctx: the user data (XML parser context)
2686: * @value: The pcdata content
2687: * @len: the block length
2688: *
2689: * called when a pcdata block has been parsed
2690: */
2691: void
2692: xmlSAX2CDataBlock(void *ctx, const xmlChar *value, int len)
2693: {
2694: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2695: xmlNodePtr ret, lastChild;
2696:
2697: if (ctx == NULL) return;
2698: #ifdef DEBUG_SAX
2699: xmlGenericError(xmlGenericErrorContext,
2700: "SAX.pcdata(%.10s, %d)\n", value, len);
2701: #endif
2702: lastChild = xmlGetLastChild(ctxt->node);
2703: #ifdef DEBUG_SAX_TREE
2704: xmlGenericError(xmlGenericErrorContext,
2705: "add chars to %s \n", ctxt->node->name);
2706: #endif
2707: if ((lastChild != NULL) &&
2708: (lastChild->type == XML_CDATA_SECTION_NODE)) {
2709: xmlTextConcat(lastChild, value, len);
2710: } else {
2711: ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
2712: xmlAddChild(ctxt->node, ret);
2713: }
2714: }
2715:
2716: static int xmlSAX2DefaultVersionValue = 2;
2717:
2718: #ifdef LIBXML_SAX1_ENABLED
2719: /**
2720: * xmlSAXDefaultVersion:
2721: * @version: the version, 1 or 2
2722: *
2723: * Set the default version of SAX used globally by the library.
2724: * By default, during initialization the default is set to 2.
2725: * Note that it is generally a better coding style to use
2726: * xmlSAXVersion() to set up the version explicitly for a given
2727: * parsing context.
2728: *
2729: * Returns the previous value in case of success and -1 in case of error.
2730: */
2731: int
2732: xmlSAXDefaultVersion(int version)
2733: {
2734: int ret = xmlSAX2DefaultVersionValue;
2735:
2736: if ((version != 1) && (version != 2))
2737: return(-1);
2738: xmlSAX2DefaultVersionValue = version;
2739: return(ret);
2740: }
2741: #endif /* LIBXML_SAX1_ENABLED */
2742:
2743: /**
2744: * xmlSAXVersion:
2745: * @hdlr: the SAX handler
2746: * @version: the version, 1 or 2
2747: *
2748: * Initialize the default XML SAX handler according to the version
2749: *
2750: * Returns 0 in case of success and -1 in case of error.
2751: */
2752: int
2753: xmlSAXVersion(xmlSAXHandler *hdlr, int version)
2754: {
2755: if (hdlr == NULL) return(-1);
2756: if (version == 2) {
2757: hdlr->startElement = NULL;
2758: hdlr->endElement = NULL;
2759: hdlr->startElementNs = xmlSAX2StartElementNs;
2760: hdlr->endElementNs = xmlSAX2EndElementNs;
2761: hdlr->serror = NULL;
2762: hdlr->initialized = XML_SAX2_MAGIC;
2763: #ifdef LIBXML_SAX1_ENABLED
2764: } else if (version == 1) {
2765: hdlr->startElement = xmlSAX2StartElement;
2766: hdlr->endElement = xmlSAX2EndElement;
2767: hdlr->initialized = 1;
2768: #endif /* LIBXML_SAX1_ENABLED */
2769: } else
2770: return(-1);
2771: hdlr->internalSubset = xmlSAX2InternalSubset;
2772: hdlr->externalSubset = xmlSAX2ExternalSubset;
2773: hdlr->isStandalone = xmlSAX2IsStandalone;
2774: hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
2775: hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
2776: hdlr->resolveEntity = xmlSAX2ResolveEntity;
2777: hdlr->getEntity = xmlSAX2GetEntity;
2778: hdlr->getParameterEntity = xmlSAX2GetParameterEntity;
2779: hdlr->entityDecl = xmlSAX2EntityDecl;
2780: hdlr->attributeDecl = xmlSAX2AttributeDecl;
2781: hdlr->elementDecl = xmlSAX2ElementDecl;
2782: hdlr->notationDecl = xmlSAX2NotationDecl;
2783: hdlr->unparsedEntityDecl = xmlSAX2UnparsedEntityDecl;
2784: hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2785: hdlr->startDocument = xmlSAX2StartDocument;
2786: hdlr->endDocument = xmlSAX2EndDocument;
2787: hdlr->reference = xmlSAX2Reference;
2788: hdlr->characters = xmlSAX2Characters;
2789: hdlr->cdataBlock = xmlSAX2CDataBlock;
2790: hdlr->ignorableWhitespace = xmlSAX2Characters;
2791: hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
2792: hdlr->comment = xmlSAX2Comment;
2793: hdlr->warning = xmlParserWarning;
2794: hdlr->error = xmlParserError;
2795: hdlr->fatalError = xmlParserError;
2796:
2797: return(0);
2798: }
2799:
2800: /**
2801: * xmlSAX2InitDefaultSAXHandler:
2802: * @hdlr: the SAX handler
2803: * @warning: flag if non-zero sets the handler warning procedure
2804: *
2805: * Initialize the default XML SAX2 handler
2806: */
2807: void
2808: xmlSAX2InitDefaultSAXHandler(xmlSAXHandler *hdlr, int warning)
2809: {
2810: if ((hdlr == NULL) || (hdlr->initialized != 0))
2811: return;
2812:
2813: xmlSAXVersion(hdlr, xmlSAX2DefaultVersionValue);
2814: if (warning == 0)
2815: hdlr->warning = NULL;
2816: else
2817: hdlr->warning = xmlParserWarning;
2818: }
2819:
2820: /**
2821: * xmlDefaultSAXHandlerInit:
2822: *
2823: * Initialize the default SAX2 handler
2824: */
2825: void
2826: xmlDefaultSAXHandlerInit(void)
2827: {
2828: #ifdef LIBXML_SAX1_ENABLED
2829: xmlSAXVersion((xmlSAXHandlerPtr) &xmlDefaultSAXHandler, 1);
2830: #endif /* LIBXML_SAX1_ENABLED */
2831: }
2832:
2833: #ifdef LIBXML_HTML_ENABLED
2834:
2835: /**
2836: * xmlSAX2InitHtmlDefaultSAXHandler:
2837: * @hdlr: the SAX handler
2838: *
2839: * Initialize the default HTML SAX2 handler
2840: */
2841: void
2842: xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr)
2843: {
2844: if ((hdlr == NULL) || (hdlr->initialized != 0))
2845: return;
2846:
2847: hdlr->internalSubset = xmlSAX2InternalSubset;
2848: hdlr->externalSubset = NULL;
2849: hdlr->isStandalone = NULL;
2850: hdlr->hasInternalSubset = NULL;
2851: hdlr->hasExternalSubset = NULL;
2852: hdlr->resolveEntity = NULL;
2853: hdlr->getEntity = xmlSAX2GetEntity;
2854: hdlr->getParameterEntity = NULL;
2855: hdlr->entityDecl = NULL;
2856: hdlr->attributeDecl = NULL;
2857: hdlr->elementDecl = NULL;
2858: hdlr->notationDecl = NULL;
2859: hdlr->unparsedEntityDecl = NULL;
2860: hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2861: hdlr->startDocument = xmlSAX2StartDocument;
2862: hdlr->endDocument = xmlSAX2EndDocument;
2863: hdlr->startElement = xmlSAX2StartElement;
2864: hdlr->endElement = xmlSAX2EndElement;
2865: hdlr->reference = NULL;
2866: hdlr->characters = xmlSAX2Characters;
2867: hdlr->cdataBlock = xmlSAX2CDataBlock;
2868: hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
2869: hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
2870: hdlr->comment = xmlSAX2Comment;
2871: hdlr->warning = xmlParserWarning;
2872: hdlr->error = xmlParserError;
2873: hdlr->fatalError = xmlParserError;
2874:
2875: hdlr->initialized = 1;
2876: }
2877:
2878: /**
2879: * htmlDefaultSAXHandlerInit:
2880: *
2881: * Initialize the default SAX handler
2882: */
2883: void
2884: htmlDefaultSAXHandlerInit(void)
2885: {
2886: xmlSAX2InitHtmlDefaultSAXHandler((xmlSAXHandlerPtr) &htmlDefaultSAXHandler);
2887: }
2888:
2889: #endif /* LIBXML_HTML_ENABLED */
2890:
2891: #ifdef LIBXML_DOCB_ENABLED
2892:
2893: /**
2894: * xmlSAX2InitDocbDefaultSAXHandler:
2895: * @hdlr: the SAX handler
2896: *
2897: * Initialize the default DocBook SAX2 handler
2898: */
2899: void
2900: xmlSAX2InitDocbDefaultSAXHandler(xmlSAXHandler *hdlr)
2901: {
2902: if ((hdlr == NULL) || (hdlr->initialized != 0))
2903: return;
2904:
2905: hdlr->internalSubset = xmlSAX2InternalSubset;
2906: hdlr->externalSubset = NULL;
2907: hdlr->isStandalone = xmlSAX2IsStandalone;
2908: hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
2909: hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
2910: hdlr->resolveEntity = xmlSAX2ResolveEntity;
2911: hdlr->getEntity = xmlSAX2GetEntity;
2912: hdlr->getParameterEntity = NULL;
2913: hdlr->entityDecl = xmlSAX2EntityDecl;
2914: hdlr->attributeDecl = NULL;
2915: hdlr->elementDecl = NULL;
2916: hdlr->notationDecl = NULL;
2917: hdlr->unparsedEntityDecl = NULL;
2918: hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2919: hdlr->startDocument = xmlSAX2StartDocument;
2920: hdlr->endDocument = xmlSAX2EndDocument;
2921: hdlr->startElement = xmlSAX2StartElement;
2922: hdlr->endElement = xmlSAX2EndElement;
2923: hdlr->reference = xmlSAX2Reference;
2924: hdlr->characters = xmlSAX2Characters;
2925: hdlr->cdataBlock = NULL;
2926: hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
2927: hdlr->processingInstruction = NULL;
2928: hdlr->comment = xmlSAX2Comment;
2929: hdlr->warning = xmlParserWarning;
2930: hdlr->error = xmlParserError;
2931: hdlr->fatalError = xmlParserError;
2932:
2933: hdlr->initialized = 1;
2934: }
2935:
2936: /**
2937: * docbDefaultSAXHandlerInit:
2938: *
2939: * Initialize the default SAX handler
2940: */
2941: void
2942: docbDefaultSAXHandlerInit(void)
2943: {
2944: xmlSAX2InitDocbDefaultSAXHandler((xmlSAXHandlerPtr) &docbDefaultSAXHandler);
2945: }
2946:
2947: #endif /* LIBXML_DOCB_ENABLED */
2948: #define bottom_SAX2
2949: #include "elfgcchack.h"
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>