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