mshtml: Implement length prop for Storage.
[wine.git] / libs / xml2 / SAX2.c
blobec89046b1d6507dccae3b09adfe23143431aca50
1 /*
2 * SAX2.c : Default SAX2 handler to build a tree.
4 * See Copyright for the status of this software.
6 * Daniel Veillard <daniel@veillard.com>
7 */
10 #define IN_LIBXML
11 #include "libxml.h"
12 #include <stdlib.h>
13 #include <string.h>
14 #include <limits.h>
15 #include <stddef.h>
16 #include <libxml/xmlmemory.h>
17 #include <libxml/tree.h>
18 #include <libxml/parser.h>
19 #include <libxml/parserInternals.h>
20 #include <libxml/valid.h>
21 #include <libxml/entities.h>
22 #include <libxml/xmlerror.h>
23 #include <libxml/debugXML.h>
24 #include <libxml/xmlIO.h>
25 #include <libxml/SAX.h>
26 #include <libxml/uri.h>
27 #include <libxml/valid.h>
28 #include <libxml/HTMLtree.h>
29 #include <libxml/globals.h>
31 /* Define SIZE_T_MAX unless defined through <limits.h>. */
32 #ifndef SIZE_T_MAX
33 # define SIZE_T_MAX ((size_t)-1)
34 #endif /* !SIZE_T_MAX */
36 /* #define DEBUG_SAX2 */
37 /* #define DEBUG_SAX2_TREE */
39 /**
40 * TODO:
42 * macro to flag unimplemented blocks
43 * XML_CATALOG_PREFER user env to select between system/public preferred
44 * option. C.f. Richard Tobin <richard@cogsci.ed.ac.uk>
45 *> Just FYI, I am using an environment variable XML_CATALOG_PREFER with
46 *> values "system" and "public". I have made the default be "system" to
47 *> match yours.
49 #define TODO \
50 xmlGenericError(xmlGenericErrorContext, \
51 "Unimplemented block at %s:%d\n", \
52 __FILE__, __LINE__);
55 * xmlSAX2ErrMemory:
56 * @ctxt: an XML validation parser context
57 * @msg: a string to accompany the error message
59 static void LIBXML_ATTR_FORMAT(2,0)
60 xmlSAX2ErrMemory(xmlParserCtxtPtr ctxt, const char *msg) {
61 xmlStructuredErrorFunc schannel = NULL;
62 const char *str1 = "out of memory\n";
64 if (ctxt != NULL) {
65 ctxt->errNo = XML_ERR_NO_MEMORY;
66 if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
67 schannel = ctxt->sax->serror;
68 __xmlRaiseError(schannel,
69 ctxt->vctxt.error, ctxt->vctxt.userData,
70 ctxt, NULL, XML_FROM_PARSER, XML_ERR_NO_MEMORY,
71 XML_ERR_ERROR, NULL, 0, (const char *) str1,
72 NULL, NULL, 0, 0,
73 msg, (const char *) str1, NULL);
74 ctxt->errNo = XML_ERR_NO_MEMORY;
75 ctxt->instate = XML_PARSER_EOF;
76 ctxt->disableSAX = 1;
77 } else {
78 __xmlRaiseError(schannel,
79 NULL, NULL,
80 ctxt, NULL, XML_FROM_PARSER, XML_ERR_NO_MEMORY,
81 XML_ERR_ERROR, NULL, 0, (const char *) str1,
82 NULL, NULL, 0, 0,
83 msg, (const char *) str1, NULL);
87 /**
88 * xmlValidError:
89 * @ctxt: an XML validation parser context
90 * @error: the error number
91 * @msg: the error message
92 * @str1: extra data
93 * @str2: extra data
95 * Handle a validation error
97 static void LIBXML_ATTR_FORMAT(3,0)
98 xmlErrValid(xmlParserCtxtPtr ctxt, xmlParserErrors error,
99 const char *msg, const char *str1, const char *str2)
101 xmlStructuredErrorFunc schannel = NULL;
103 if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
104 (ctxt->instate == XML_PARSER_EOF))
105 return;
106 if (ctxt != NULL) {
107 ctxt->errNo = error;
108 if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
109 schannel = ctxt->sax->serror;
110 __xmlRaiseError(schannel,
111 ctxt->vctxt.error, ctxt->vctxt.userData,
112 ctxt, NULL, XML_FROM_DTD, error,
113 XML_ERR_ERROR, NULL, 0, (const char *) str1,
114 (const char *) str2, NULL, 0, 0,
115 msg, (const char *) str1, (const char *) str2);
116 ctxt->valid = 0;
117 } else {
118 __xmlRaiseError(schannel,
119 NULL, NULL,
120 ctxt, NULL, XML_FROM_DTD, error,
121 XML_ERR_ERROR, NULL, 0, (const char *) str1,
122 (const char *) str2, NULL, 0, 0,
123 msg, (const char *) str1, (const char *) str2);
128 * xmlFatalErrMsg:
129 * @ctxt: an XML parser context
130 * @error: the error number
131 * @msg: the error message
132 * @str1: an error string
133 * @str2: an error string
135 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
137 static void LIBXML_ATTR_FORMAT(3,0)
138 xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
139 const char *msg, const xmlChar *str1, const xmlChar *str2)
141 if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
142 (ctxt->instate == XML_PARSER_EOF))
143 return;
144 if (ctxt != NULL)
145 ctxt->errNo = error;
146 __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
147 XML_ERR_FATAL, NULL, 0,
148 (const char *) str1, (const char *) str2,
149 NULL, 0, 0, msg, str1, str2);
150 if (ctxt != NULL) {
151 ctxt->wellFormed = 0;
152 ctxt->valid = 0;
153 if (ctxt->recovery == 0)
154 ctxt->disableSAX = 1;
159 * xmlWarnMsg:
160 * @ctxt: an XML parser context
161 * @error: the error number
162 * @msg: the error message
163 * @str1: an error string
164 * @str2: an error string
166 * Handle a parser warning
168 static void LIBXML_ATTR_FORMAT(3,0)
169 xmlWarnMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
170 const char *msg, const xmlChar *str1)
172 if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
173 (ctxt->instate == XML_PARSER_EOF))
174 return;
175 if (ctxt != NULL)
176 ctxt->errNo = error;
177 __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
178 XML_ERR_WARNING, NULL, 0,
179 (const char *) str1, NULL,
180 NULL, 0, 0, msg, str1);
184 * xmlNsWarnMsg:
185 * @ctxt: an XML parser context
186 * @error: the error number
187 * @msg: the error message
188 * @str1: an error string
190 * Handle a namespace warning
192 static void LIBXML_ATTR_FORMAT(3,0)
193 xmlNsWarnMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
194 const char *msg, const xmlChar *str1, const xmlChar *str2)
196 if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
197 (ctxt->instate == XML_PARSER_EOF))
198 return;
199 if (ctxt != NULL)
200 ctxt->errNo = error;
201 __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
202 XML_ERR_WARNING, NULL, 0,
203 (const char *) str1, (const char *) str2,
204 NULL, 0, 0, msg, str1, str2);
208 * xmlSAX2GetPublicId:
209 * @ctx: the user data (XML parser context)
211 * Provides the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
213 * Returns a xmlChar *
215 const xmlChar *
216 xmlSAX2GetPublicId(void *ctx ATTRIBUTE_UNUSED)
218 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
219 return(NULL);
223 * xmlSAX2GetSystemId:
224 * @ctx: the user data (XML parser context)
226 * Provides the system ID, basically URL or filename e.g.
227 * http://www.sgmlsource.com/dtds/memo.dtd
229 * Returns a xmlChar *
231 const xmlChar *
232 xmlSAX2GetSystemId(void *ctx)
234 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
235 if ((ctx == NULL) || (ctxt->input == NULL)) return(NULL);
236 return((const xmlChar *) ctxt->input->filename);
240 * xmlSAX2GetLineNumber:
241 * @ctx: the user data (XML parser context)
243 * Provide the line number of the current parsing point.
245 * Returns an int
248 xmlSAX2GetLineNumber(void *ctx)
250 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
251 if ((ctx == NULL) || (ctxt->input == NULL)) return(0);
252 return(ctxt->input->line);
256 * xmlSAX2GetColumnNumber:
257 * @ctx: the user data (XML parser context)
259 * Provide the column number of the current parsing point.
261 * Returns an int
264 xmlSAX2GetColumnNumber(void *ctx)
266 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
267 if ((ctx == NULL) || (ctxt->input == NULL)) return(0);
268 return(ctxt->input->col);
272 * xmlSAX2IsStandalone:
273 * @ctx: the user data (XML parser context)
275 * Is this document tagged standalone ?
277 * Returns 1 if true
280 xmlSAX2IsStandalone(void *ctx)
282 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
283 if ((ctx == NULL) || (ctxt->myDoc == NULL)) return(0);
284 return(ctxt->myDoc->standalone == 1);
288 * xmlSAX2HasInternalSubset:
289 * @ctx: the user data (XML parser context)
291 * Does this document has an internal subset
293 * Returns 1 if true
296 xmlSAX2HasInternalSubset(void *ctx)
298 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
299 if ((ctxt == NULL) || (ctxt->myDoc == NULL)) return(0);
300 return(ctxt->myDoc->intSubset != NULL);
304 * xmlSAX2HasExternalSubset:
305 * @ctx: the user data (XML parser context)
307 * Does this document has an external subset
309 * Returns 1 if true
312 xmlSAX2HasExternalSubset(void *ctx)
314 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
315 if ((ctxt == NULL) || (ctxt->myDoc == NULL)) return(0);
316 return(ctxt->myDoc->extSubset != NULL);
320 * xmlSAX2InternalSubset:
321 * @ctx: the user data (XML parser context)
322 * @name: the root element name
323 * @ExternalID: the external ID
324 * @SystemID: the SYSTEM ID (e.g. filename or URL)
326 * Callback on internal subset declaration.
328 void
329 xmlSAX2InternalSubset(void *ctx, const xmlChar *name,
330 const xmlChar *ExternalID, const xmlChar *SystemID)
332 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
333 xmlDtdPtr dtd;
334 if (ctx == NULL) return;
335 #ifdef DEBUG_SAX
336 xmlGenericError(xmlGenericErrorContext,
337 "SAX.xmlSAX2InternalSubset(%s, %s, %s)\n",
338 name, ExternalID, SystemID);
339 #endif
341 if (ctxt->myDoc == NULL)
342 return;
343 dtd = xmlGetIntSubset(ctxt->myDoc);
344 if (dtd != NULL) {
345 if (ctxt->html)
346 return;
347 xmlUnlinkNode((xmlNodePtr) dtd);
348 xmlFreeDtd(dtd);
349 ctxt->myDoc->intSubset = NULL;
351 ctxt->myDoc->intSubset =
352 xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
353 if (ctxt->myDoc->intSubset == NULL)
354 xmlSAX2ErrMemory(ctxt, "xmlSAX2InternalSubset");
358 * xmlSAX2ExternalSubset:
359 * @ctx: the user data (XML parser context)
360 * @name: the root element name
361 * @ExternalID: the external ID
362 * @SystemID: the SYSTEM ID (e.g. filename or URL)
364 * Callback on external subset declaration.
366 void
367 xmlSAX2ExternalSubset(void *ctx, const xmlChar *name,
368 const xmlChar *ExternalID, const xmlChar *SystemID)
370 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
371 if (ctx == NULL) return;
372 #ifdef DEBUG_SAX
373 xmlGenericError(xmlGenericErrorContext,
374 "SAX.xmlSAX2ExternalSubset(%s, %s, %s)\n",
375 name, ExternalID, SystemID);
376 #endif
377 if (((ExternalID != NULL) || (SystemID != NULL)) &&
378 (((ctxt->validate) || (ctxt->loadsubset != 0)) &&
379 (ctxt->wellFormed && ctxt->myDoc))) {
381 * Try to fetch and parse the external subset.
383 xmlParserInputPtr oldinput;
384 int oldinputNr;
385 int oldinputMax;
386 xmlParserInputPtr *oldinputTab;
387 xmlParserInputPtr input = NULL;
388 xmlCharEncoding enc;
389 int oldcharset;
390 const xmlChar *oldencoding;
393 * Ask the Entity resolver to load the damn thing
395 if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
396 input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
397 SystemID);
398 if (input == NULL) {
399 return;
402 xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
405 * make sure we won't destroy the main document context
407 oldinput = ctxt->input;
408 oldinputNr = ctxt->inputNr;
409 oldinputMax = ctxt->inputMax;
410 oldinputTab = ctxt->inputTab;
411 oldcharset = ctxt->charset;
412 oldencoding = ctxt->encoding;
413 ctxt->encoding = NULL;
415 ctxt->inputTab = (xmlParserInputPtr *)
416 xmlMalloc(5 * sizeof(xmlParserInputPtr));
417 if (ctxt->inputTab == NULL) {
418 xmlSAX2ErrMemory(ctxt, "xmlSAX2ExternalSubset");
419 ctxt->input = oldinput;
420 ctxt->inputNr = oldinputNr;
421 ctxt->inputMax = oldinputMax;
422 ctxt->inputTab = oldinputTab;
423 ctxt->charset = oldcharset;
424 ctxt->encoding = oldencoding;
425 return;
427 ctxt->inputNr = 0;
428 ctxt->inputMax = 5;
429 ctxt->input = NULL;
430 xmlPushInput(ctxt, input);
433 * On the fly encoding conversion if needed
435 if (ctxt->input->length >= 4) {
436 enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
437 xmlSwitchEncoding(ctxt, enc);
440 if (input->filename == NULL)
441 input->filename = (char *) xmlCanonicPath(SystemID);
442 input->line = 1;
443 input->col = 1;
444 input->base = ctxt->input->cur;
445 input->cur = ctxt->input->cur;
446 input->free = NULL;
449 * let's parse that entity knowing it's an external subset.
451 xmlParseExternalSubset(ctxt, ExternalID, SystemID);
454 * Free up the external entities
457 while (ctxt->inputNr > 1)
458 xmlPopInput(ctxt);
459 xmlFreeInputStream(ctxt->input);
460 xmlFree(ctxt->inputTab);
463 * Restore the parsing context of the main entity
465 ctxt->input = oldinput;
466 ctxt->inputNr = oldinputNr;
467 ctxt->inputMax = oldinputMax;
468 ctxt->inputTab = oldinputTab;
469 ctxt->charset = oldcharset;
470 if ((ctxt->encoding != NULL) &&
471 ((ctxt->dict == NULL) ||
472 (!xmlDictOwns(ctxt->dict, ctxt->encoding))))
473 xmlFree((xmlChar *) ctxt->encoding);
474 ctxt->encoding = oldencoding;
475 /* ctxt->wellFormed = oldwellFormed; */
480 * xmlSAX2ResolveEntity:
481 * @ctx: the user data (XML parser context)
482 * @publicId: The public ID of the entity
483 * @systemId: The system ID of the entity
485 * The entity loader, to control the loading of external entities,
486 * the application can either:
487 * - override this xmlSAX2ResolveEntity() callback in the SAX block
488 * - or better use the xmlSetExternalEntityLoader() function to
489 * set up it's own entity resolution routine
491 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
493 xmlParserInputPtr
494 xmlSAX2ResolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
496 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
497 xmlParserInputPtr ret;
498 xmlChar *URI;
499 const char *base = NULL;
501 if (ctx == NULL) return(NULL);
502 if (ctxt->input != NULL)
503 base = ctxt->input->filename;
504 if (base == NULL)
505 base = ctxt->directory;
507 URI = xmlBuildURI(systemId, (const xmlChar *) base);
509 #ifdef DEBUG_SAX
510 xmlGenericError(xmlGenericErrorContext,
511 "SAX.xmlSAX2ResolveEntity(%s, %s)\n", publicId, systemId);
512 #endif
514 ret = xmlLoadExternalEntity((const char *) URI,
515 (const char *) publicId, ctxt);
516 if (URI != NULL)
517 xmlFree(URI);
518 return(ret);
522 * xmlSAX2GetEntity:
523 * @ctx: the user data (XML parser context)
524 * @name: The entity name
526 * Get an entity by name
528 * Returns the xmlEntityPtr if found.
530 xmlEntityPtr
531 xmlSAX2GetEntity(void *ctx, const xmlChar *name)
533 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
534 xmlEntityPtr ret = NULL;
536 if (ctx == NULL) return(NULL);
537 #ifdef DEBUG_SAX
538 xmlGenericError(xmlGenericErrorContext,
539 "SAX.xmlSAX2GetEntity(%s)\n", name);
540 #endif
542 if (ctxt->inSubset == 0) {
543 ret = xmlGetPredefinedEntity(name);
544 if (ret != NULL)
545 return(ret);
547 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->standalone == 1)) {
548 if (ctxt->inSubset == 2) {
549 ctxt->myDoc->standalone = 0;
550 ret = xmlGetDocEntity(ctxt->myDoc, name);
551 ctxt->myDoc->standalone = 1;
552 } else {
553 ret = xmlGetDocEntity(ctxt->myDoc, name);
554 if (ret == NULL) {
555 ctxt->myDoc->standalone = 0;
556 ret = xmlGetDocEntity(ctxt->myDoc, name);
557 if (ret != NULL) {
558 xmlFatalErrMsg(ctxt, XML_ERR_NOT_STANDALONE,
559 "Entity(%s) document marked standalone but requires external subset\n",
560 name, NULL);
562 ctxt->myDoc->standalone = 1;
565 } else {
566 ret = xmlGetDocEntity(ctxt->myDoc, name);
568 return(ret);
572 * xmlSAX2GetParameterEntity:
573 * @ctx: the user data (XML parser context)
574 * @name: The entity name
576 * Get a parameter entity by name
578 * Returns the xmlEntityPtr if found.
580 xmlEntityPtr
581 xmlSAX2GetParameterEntity(void *ctx, const xmlChar *name)
583 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
584 xmlEntityPtr ret;
586 if (ctx == NULL) return(NULL);
587 #ifdef DEBUG_SAX
588 xmlGenericError(xmlGenericErrorContext,
589 "SAX.xmlSAX2GetParameterEntity(%s)\n", name);
590 #endif
592 ret = xmlGetParameterEntity(ctxt->myDoc, name);
593 return(ret);
598 * xmlSAX2EntityDecl:
599 * @ctx: the user data (XML parser context)
600 * @name: the entity name
601 * @type: the entity type
602 * @publicId: The public ID of the entity
603 * @systemId: The system ID of the entity
604 * @content: the entity value (without processing).
606 * An entity definition has been parsed
608 void
609 xmlSAX2EntityDecl(void *ctx, const xmlChar *name, int type,
610 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
612 xmlEntityPtr ent;
613 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
615 if (ctx == NULL) return;
616 #ifdef DEBUG_SAX
617 xmlGenericError(xmlGenericErrorContext,
618 "SAX.xmlSAX2EntityDecl(%s, %d, %s, %s, %s)\n",
619 name, type, publicId, systemId, content);
620 #endif
621 if (ctxt->inSubset == 1) {
622 ent = xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
623 systemId, content);
624 if ((ent == NULL) && (ctxt->pedantic))
625 xmlWarnMsg(ctxt, XML_WAR_ENTITY_REDEFINED,
626 "Entity(%s) already defined in the internal subset\n",
627 name);
628 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
629 xmlChar *URI;
630 const char *base = NULL;
632 if (ctxt->input != NULL)
633 base = ctxt->input->filename;
634 if (base == NULL)
635 base = ctxt->directory;
637 URI = xmlBuildURI(systemId, (const xmlChar *) base);
638 ent->URI = URI;
640 } else if (ctxt->inSubset == 2) {
641 ent = xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
642 systemId, content);
643 if ((ent == NULL) && (ctxt->pedantic) &&
644 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
645 ctxt->sax->warning(ctxt->userData,
646 "Entity(%s) already defined in the external subset\n", name);
647 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
648 xmlChar *URI;
649 const char *base = NULL;
651 if (ctxt->input != NULL)
652 base = ctxt->input->filename;
653 if (base == NULL)
654 base = ctxt->directory;
656 URI = xmlBuildURI(systemId, (const xmlChar *) base);
657 ent->URI = URI;
659 } else {
660 xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_PROCESSING,
661 "SAX.xmlSAX2EntityDecl(%s) called while not in subset\n",
662 name, NULL);
667 * xmlSAX2AttributeDecl:
668 * @ctx: the user data (XML parser context)
669 * @elem: the name of the element
670 * @fullname: the attribute name
671 * @type: the attribute type
672 * @def: the type of default value
673 * @defaultValue: the attribute default value
674 * @tree: the tree of enumerated value set
676 * An attribute definition has been parsed
678 void
679 xmlSAX2AttributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
680 int type, int def, const xmlChar *defaultValue,
681 xmlEnumerationPtr tree)
683 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
684 xmlAttributePtr attr;
685 xmlChar *name = NULL, *prefix = NULL;
687 /* Avoid unused variable warning if features are disabled. */
688 (void) attr;
690 if ((ctxt == NULL) || (ctxt->myDoc == NULL))
691 return;
693 #ifdef DEBUG_SAX
694 xmlGenericError(xmlGenericErrorContext,
695 "SAX.xmlSAX2AttributeDecl(%s, %s, %d, %d, %s, ...)\n",
696 elem, fullname, type, def, defaultValue);
697 #endif
698 if ((xmlStrEqual(fullname, BAD_CAST "xml:id")) &&
699 (type != XML_ATTRIBUTE_ID)) {
701 * Raise the error but keep the validity flag
703 int tmp = ctxt->valid;
704 xmlErrValid(ctxt, XML_DTD_XMLID_TYPE,
705 "xml:id : attribute type should be ID\n", NULL, NULL);
706 ctxt->valid = tmp;
708 /* TODO: optimize name/prefix allocation */
709 name = xmlSplitQName(ctxt, fullname, &prefix);
710 ctxt->vctxt.valid = 1;
711 if (ctxt->inSubset == 1)
712 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
713 name, prefix, (xmlAttributeType) type,
714 (xmlAttributeDefault) def, defaultValue, tree);
715 else if (ctxt->inSubset == 2)
716 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
717 name, prefix, (xmlAttributeType) type,
718 (xmlAttributeDefault) def, defaultValue, tree);
719 else {
720 xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
721 "SAX.xmlSAX2AttributeDecl(%s) called while not in subset\n",
722 name, NULL);
723 xmlFree(name);
724 xmlFreeEnumeration(tree);
725 return;
727 #ifdef LIBXML_VALID_ENABLED
728 if (ctxt->vctxt.valid == 0)
729 ctxt->valid = 0;
730 if ((attr != NULL) && (ctxt->validate) && (ctxt->wellFormed) &&
731 (ctxt->myDoc->intSubset != NULL))
732 ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
733 attr);
734 #endif /* LIBXML_VALID_ENABLED */
735 if (prefix != NULL)
736 xmlFree(prefix);
737 if (name != NULL)
738 xmlFree(name);
742 * xmlSAX2ElementDecl:
743 * @ctx: the user data (XML parser context)
744 * @name: the element name
745 * @type: the element type
746 * @content: the element value tree
748 * An element definition has been parsed
750 void
751 xmlSAX2ElementDecl(void *ctx, const xmlChar * name, int type,
752 xmlElementContentPtr content)
754 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
755 xmlElementPtr elem = NULL;
757 /* Avoid unused variable warning if features are disabled. */
758 (void) elem;
760 if ((ctxt == NULL) || (ctxt->myDoc == NULL))
761 return;
763 #ifdef DEBUG_SAX
764 xmlGenericError(xmlGenericErrorContext,
765 "SAX.xmlSAX2ElementDecl(%s, %d, ...)\n", name, type);
766 #endif
768 if (ctxt->inSubset == 1)
769 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
770 name, (xmlElementTypeVal) type, content);
771 else if (ctxt->inSubset == 2)
772 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
773 name, (xmlElementTypeVal) type, content);
774 else {
775 xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
776 "SAX.xmlSAX2ElementDecl(%s) called while not in subset\n",
777 name, NULL);
778 return;
780 #ifdef LIBXML_VALID_ENABLED
781 if (elem == NULL)
782 ctxt->valid = 0;
783 if (ctxt->validate && ctxt->wellFormed &&
784 ctxt->myDoc && ctxt->myDoc->intSubset)
785 ctxt->valid &=
786 xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
787 #endif /* LIBXML_VALID_ENABLED */
791 * xmlSAX2NotationDecl:
792 * @ctx: the user data (XML parser context)
793 * @name: The name of the notation
794 * @publicId: The public ID of the entity
795 * @systemId: The system ID of the entity
797 * What to do when a notation declaration has been parsed.
799 void
800 xmlSAX2NotationDecl(void *ctx, const xmlChar *name,
801 const xmlChar *publicId, const xmlChar *systemId)
803 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
804 xmlNotationPtr nota = NULL;
806 /* Avoid unused variable warning if features are disabled. */
807 (void) nota;
809 if ((ctxt == NULL) || (ctxt->myDoc == NULL))
810 return;
812 #ifdef DEBUG_SAX
813 xmlGenericError(xmlGenericErrorContext,
814 "SAX.xmlSAX2NotationDecl(%s, %s, %s)\n", name, publicId, systemId);
815 #endif
817 if ((publicId == NULL) && (systemId == NULL)) {
818 xmlFatalErrMsg(ctxt, XML_ERR_NOTATION_PROCESSING,
819 "SAX.xmlSAX2NotationDecl(%s) externalID or PublicID missing\n",
820 name, NULL);
821 return;
822 } else if (ctxt->inSubset == 1)
823 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
824 publicId, systemId);
825 else if (ctxt->inSubset == 2)
826 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, name,
827 publicId, systemId);
828 else {
829 xmlFatalErrMsg(ctxt, XML_ERR_NOTATION_PROCESSING,
830 "SAX.xmlSAX2NotationDecl(%s) called while not in subset\n",
831 name, NULL);
832 return;
834 #ifdef LIBXML_VALID_ENABLED
835 if (nota == NULL) ctxt->valid = 0;
836 if ((ctxt->validate) && (ctxt->wellFormed) &&
837 (ctxt->myDoc->intSubset != NULL))
838 ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
839 nota);
840 #endif /* LIBXML_VALID_ENABLED */
844 * xmlSAX2UnparsedEntityDecl:
845 * @ctx: the user data (XML parser context)
846 * @name: The name of the entity
847 * @publicId: The public ID of the entity
848 * @systemId: The system ID of the entity
849 * @notationName: the name of the notation
851 * What to do when an unparsed entity declaration is parsed
853 void
854 xmlSAX2UnparsedEntityDecl(void *ctx, const xmlChar *name,
855 const xmlChar *publicId, const xmlChar *systemId,
856 const xmlChar *notationName)
858 xmlEntityPtr ent;
859 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
860 if (ctx == NULL) return;
861 #ifdef DEBUG_SAX
862 xmlGenericError(xmlGenericErrorContext,
863 "SAX.xmlSAX2UnparsedEntityDecl(%s, %s, %s, %s)\n",
864 name, publicId, systemId, notationName);
865 #endif
866 if (ctxt->inSubset == 1) {
867 ent = xmlAddDocEntity(ctxt->myDoc, name,
868 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
869 publicId, systemId, notationName);
870 if ((ent == NULL) && (ctxt->pedantic) &&
871 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
872 ctxt->sax->warning(ctxt->userData,
873 "Entity(%s) already defined in the internal subset\n", name);
874 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
875 xmlChar *URI;
876 const char *base = NULL;
878 if (ctxt->input != NULL)
879 base = ctxt->input->filename;
880 if (base == NULL)
881 base = ctxt->directory;
883 URI = xmlBuildURI(systemId, (const xmlChar *) base);
884 ent->URI = URI;
886 } else if (ctxt->inSubset == 2) {
887 ent = xmlAddDtdEntity(ctxt->myDoc, name,
888 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
889 publicId, systemId, notationName);
890 if ((ent == NULL) && (ctxt->pedantic) &&
891 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
892 ctxt->sax->warning(ctxt->userData,
893 "Entity(%s) already defined in the external subset\n", name);
894 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
895 xmlChar *URI;
896 const char *base = NULL;
898 if (ctxt->input != NULL)
899 base = ctxt->input->filename;
900 if (base == NULL)
901 base = ctxt->directory;
903 URI = xmlBuildURI(systemId, (const xmlChar *) base);
904 ent->URI = URI;
906 } else {
907 xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
908 "SAX.xmlSAX2UnparsedEntityDecl(%s) called while not in subset\n",
909 name, NULL);
914 * xmlSAX2SetDocumentLocator:
915 * @ctx: the user data (XML parser context)
916 * @loc: A SAX Locator
918 * Receive the document locator at startup, actually xmlDefaultSAXLocator
919 * Everything is available on the context, so this is useless in our case.
921 void
922 xmlSAX2SetDocumentLocator(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
924 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
925 #ifdef DEBUG_SAX
926 xmlGenericError(xmlGenericErrorContext,
927 "SAX.xmlSAX2SetDocumentLocator()\n");
928 #endif
932 * xmlSAX2StartDocument:
933 * @ctx: the user data (XML parser context)
935 * called when the document start being processed.
937 void
938 xmlSAX2StartDocument(void *ctx)
940 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
941 xmlDocPtr doc;
943 if (ctx == NULL) return;
945 #ifdef DEBUG_SAX
946 xmlGenericError(xmlGenericErrorContext,
947 "SAX.xmlSAX2StartDocument()\n");
948 #endif
949 if (ctxt->html) {
950 #ifdef LIBXML_HTML_ENABLED
951 if (ctxt->myDoc == NULL)
952 ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
953 if (ctxt->myDoc == NULL) {
954 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
955 return;
957 ctxt->myDoc->properties = XML_DOC_HTML;
958 ctxt->myDoc->parseFlags = ctxt->options;
959 #else
960 xmlGenericError(xmlGenericErrorContext,
961 "libxml2 built without HTML support\n");
962 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
963 ctxt->instate = XML_PARSER_EOF;
964 ctxt->disableSAX = 1;
965 return;
966 #endif
967 } else {
968 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
969 if (doc != NULL) {
970 doc->properties = 0;
971 if (ctxt->options & XML_PARSE_OLD10)
972 doc->properties |= XML_DOC_OLD10;
973 doc->parseFlags = ctxt->options;
974 if (ctxt->encoding != NULL)
975 doc->encoding = xmlStrdup(ctxt->encoding);
976 else
977 doc->encoding = NULL;
978 doc->standalone = ctxt->standalone;
979 } else {
980 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
981 return;
983 if ((ctxt->dictNames) && (doc != NULL)) {
984 doc->dict = ctxt->dict;
985 xmlDictReference(doc->dict);
988 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
989 (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
990 ctxt->myDoc->URL = xmlPathToURI((const xmlChar *)ctxt->input->filename);
991 if (ctxt->myDoc->URL == NULL)
992 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
997 * xmlSAX2EndDocument:
998 * @ctx: the user data (XML parser context)
1000 * called when the document end has been detected.
1002 void
1003 xmlSAX2EndDocument(void *ctx)
1005 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1006 #ifdef DEBUG_SAX
1007 xmlGenericError(xmlGenericErrorContext,
1008 "SAX.xmlSAX2EndDocument()\n");
1009 #endif
1010 if (ctx == NULL) return;
1011 #ifdef LIBXML_VALID_ENABLED
1012 if (ctxt->validate && ctxt->wellFormed &&
1013 ctxt->myDoc && ctxt->myDoc->intSubset)
1014 ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
1015 #endif /* LIBXML_VALID_ENABLED */
1018 * Grab the encoding if it was added on-the-fly
1020 if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
1021 (ctxt->myDoc->encoding == NULL)) {
1022 ctxt->myDoc->encoding = ctxt->encoding;
1023 ctxt->encoding = NULL;
1025 if ((ctxt->inputTab != NULL) &&
1026 (ctxt->inputNr > 0) && (ctxt->inputTab[0] != NULL) &&
1027 (ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
1028 (ctxt->myDoc->encoding == NULL)) {
1029 ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
1031 if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
1032 (ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
1033 ctxt->myDoc->charset = ctxt->charset;
1037 #if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_LEGACY_ENABLED)
1039 * xmlNsErrMsg:
1040 * @ctxt: an XML parser context
1041 * @error: the error number
1042 * @msg: the error message
1043 * @str1: an error string
1044 * @str2: an error string
1046 * Handle a namespace error
1048 static void LIBXML_ATTR_FORMAT(3,0)
1049 xmlNsErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
1050 const char *msg, const xmlChar *str1, const xmlChar *str2)
1052 if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
1053 (ctxt->instate == XML_PARSER_EOF))
1054 return;
1055 if (ctxt != NULL)
1056 ctxt->errNo = error;
1057 __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
1058 XML_ERR_ERROR, NULL, 0,
1059 (const char *) str1, (const char *) str2,
1060 NULL, 0, 0, msg, str1, str2);
1064 * xmlSAX2AttributeInternal:
1065 * @ctx: the user data (XML parser context)
1066 * @fullname: The attribute name, including namespace prefix
1067 * @value: The attribute value
1068 * @prefix: the prefix on the element node
1070 * Handle an attribute that has been read by the parser.
1071 * The default handling is to convert the attribute into an
1072 * DOM subtree and past it in a new xmlAttr element added to
1073 * the element.
1075 static void
1076 xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
1077 const xmlChar *value, const xmlChar *prefix ATTRIBUTE_UNUSED)
1079 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1080 xmlAttrPtr ret;
1081 xmlChar *name;
1082 xmlChar *ns;
1083 xmlChar *nval;
1084 xmlNsPtr namespace;
1086 if (ctxt->html) {
1087 name = xmlStrdup(fullname);
1088 ns = NULL;
1089 namespace = NULL;
1090 } else {
1092 * Split the full name into a namespace prefix and the tag name
1094 name = xmlSplitQName(ctxt, fullname, &ns);
1095 if ((name != NULL) && (name[0] == 0)) {
1096 if (xmlStrEqual(ns, BAD_CAST "xmlns")) {
1097 xmlNsErrMsg(ctxt, XML_ERR_NS_DECL_ERROR,
1098 "invalid namespace declaration '%s'\n",
1099 fullname, NULL);
1100 } else {
1101 xmlNsWarnMsg(ctxt, XML_WAR_NS_COLUMN,
1102 "Avoid attribute ending with ':' like '%s'\n",
1103 fullname, NULL);
1105 if (ns != NULL)
1106 xmlFree(ns);
1107 ns = NULL;
1108 xmlFree(name);
1109 name = xmlStrdup(fullname);
1112 if (name == NULL) {
1113 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
1114 if (ns != NULL)
1115 xmlFree(ns);
1116 return;
1119 #ifdef LIBXML_HTML_ENABLED
1120 if ((ctxt->html) &&
1121 (value == NULL) && (htmlIsBooleanAttr(fullname))) {
1122 nval = xmlStrdup(fullname);
1123 value = (const xmlChar *) nval;
1124 } else
1125 #endif
1127 #ifdef LIBXML_VALID_ENABLED
1129 * Do the last stage of the attribute normalization
1130 * Needed for HTML too:
1131 * http://www.w3.org/TR/html4/types.html#h-6.2
1133 ctxt->vctxt.valid = 1;
1134 nval = xmlValidCtxtNormalizeAttributeValue(&ctxt->vctxt,
1135 ctxt->myDoc, ctxt->node,
1136 fullname, value);
1137 if (ctxt->vctxt.valid != 1) {
1138 ctxt->valid = 0;
1140 if (nval != NULL)
1141 value = nval;
1142 #else
1143 nval = NULL;
1144 #endif /* LIBXML_VALID_ENABLED */
1148 * Check whether it's a namespace definition
1150 if ((!ctxt->html) && (ns == NULL) &&
1151 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
1152 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
1153 xmlNsPtr nsret;
1154 xmlChar *val;
1156 /* Avoid unused variable warning if features are disabled. */
1157 (void) nsret;
1159 if (!ctxt->replaceEntities) {
1160 ctxt->depth++;
1161 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1162 0,0,0);
1163 ctxt->depth--;
1164 if (val == NULL) {
1165 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
1166 if (name != NULL)
1167 xmlFree(name);
1168 if (nval != NULL)
1169 xmlFree(nval);
1170 return;
1172 } else {
1173 val = (xmlChar *) value;
1176 if (val[0] != 0) {
1177 xmlURIPtr uri;
1179 uri = xmlParseURI((const char *)val);
1180 if (uri == NULL) {
1181 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1182 ctxt->sax->warning(ctxt->userData,
1183 "xmlns: %s not a valid URI\n", val);
1184 } else {
1185 if (uri->scheme == NULL) {
1186 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1187 ctxt->sax->warning(ctxt->userData,
1188 "xmlns: URI %s is not absolute\n", val);
1190 xmlFreeURI(uri);
1194 /* a default namespace definition */
1195 nsret = xmlNewNs(ctxt->node, val, NULL);
1197 #ifdef LIBXML_VALID_ENABLED
1199 * Validate also for namespace decls, they are attributes from
1200 * an XML-1.0 perspective
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, val);
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;
1215 if ((!ctxt->html) &&
1216 (ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
1217 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
1218 xmlNsPtr nsret;
1219 xmlChar *val;
1221 /* Avoid unused variable warning if features are disabled. */
1222 (void) nsret;
1224 if (!ctxt->replaceEntities) {
1225 ctxt->depth++;
1226 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1227 0,0,0);
1228 ctxt->depth--;
1229 if (val == NULL) {
1230 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
1231 xmlFree(ns);
1232 if (name != NULL)
1233 xmlFree(name);
1234 if (nval != NULL)
1235 xmlFree(nval);
1236 return;
1238 } else {
1239 val = (xmlChar *) value;
1242 if (val[0] == 0) {
1243 xmlNsErrMsg(ctxt, XML_NS_ERR_EMPTY,
1244 "Empty namespace name for prefix %s\n", name, NULL);
1246 if ((ctxt->pedantic != 0) && (val[0] != 0)) {
1247 xmlURIPtr uri;
1249 uri = xmlParseURI((const char *)val);
1250 if (uri == NULL) {
1251 xmlNsWarnMsg(ctxt, XML_WAR_NS_URI,
1252 "xmlns:%s: %s not a valid URI\n", name, value);
1253 } else {
1254 if (uri->scheme == NULL) {
1255 xmlNsWarnMsg(ctxt, XML_WAR_NS_URI_RELATIVE,
1256 "xmlns:%s: URI %s is not absolute\n", name, value);
1258 xmlFreeURI(uri);
1262 /* a standard namespace definition */
1263 nsret = xmlNewNs(ctxt->node, val, name);
1264 xmlFree(ns);
1265 #ifdef LIBXML_VALID_ENABLED
1267 * Validate also for namespace decls, they are attributes from
1268 * an XML-1.0 perspective
1270 if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
1271 ctxt->myDoc && ctxt->myDoc->intSubset)
1272 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
1273 ctxt->node, prefix, nsret, value);
1274 #endif /* LIBXML_VALID_ENABLED */
1275 if (name != NULL)
1276 xmlFree(name);
1277 if (nval != NULL)
1278 xmlFree(nval);
1279 if (val != value)
1280 xmlFree(val);
1281 return;
1284 if (ns != NULL) {
1285 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
1287 if (namespace == NULL) {
1288 xmlNsErrMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
1289 "Namespace prefix %s of attribute %s is not defined\n",
1290 ns, name);
1291 } else {
1292 xmlAttrPtr prop;
1294 prop = ctxt->node->properties;
1295 while (prop != NULL) {
1296 if (prop->ns != NULL) {
1297 if ((xmlStrEqual(name, prop->name)) &&
1298 ((namespace == prop->ns) ||
1299 (xmlStrEqual(namespace->href, prop->ns->href)))) {
1300 xmlNsErrMsg(ctxt, XML_ERR_ATTRIBUTE_REDEFINED,
1301 "Attribute %s in %s redefined\n",
1302 name, namespace->href);
1303 ctxt->wellFormed = 0;
1304 if (ctxt->recovery == 0) ctxt->disableSAX = 1;
1305 if (name != NULL)
1306 xmlFree(name);
1307 goto error;
1310 prop = prop->next;
1313 } else {
1314 namespace = NULL;
1317 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
1318 ret = xmlNewNsPropEatName(ctxt->node, namespace, name, NULL);
1320 if (ret != NULL) {
1321 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
1322 xmlNodePtr tmp;
1324 ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
1325 tmp = ret->children;
1326 while (tmp != NULL) {
1327 tmp->parent = (xmlNodePtr) ret;
1328 if (tmp->next == NULL)
1329 ret->last = tmp;
1330 tmp = tmp->next;
1332 } else if (value != NULL) {
1333 ret->children = xmlNewDocText(ctxt->myDoc, value);
1334 ret->last = ret->children;
1335 if (ret->children != NULL)
1336 ret->children->parent = (xmlNodePtr) ret;
1340 #ifdef LIBXML_VALID_ENABLED
1341 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
1342 ctxt->myDoc && ctxt->myDoc->intSubset) {
1345 * If we don't substitute entities, the validation should be
1346 * done on a value with replaced entities anyway.
1348 if (!ctxt->replaceEntities) {
1349 xmlChar *val;
1351 ctxt->depth++;
1352 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1353 0,0,0);
1354 ctxt->depth--;
1356 if (val == NULL)
1357 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1358 ctxt->myDoc, ctxt->node, ret, value);
1359 else {
1360 xmlChar *nvalnorm;
1363 * Do the last stage of the attribute normalization
1364 * It need to be done twice ... it's an extra burden related
1365 * to the ability to keep xmlSAX2References in attributes
1367 nvalnorm = xmlValidNormalizeAttributeValue(ctxt->myDoc,
1368 ctxt->node, fullname, val);
1369 if (nvalnorm != NULL) {
1370 xmlFree(val);
1371 val = nvalnorm;
1374 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1375 ctxt->myDoc, ctxt->node, ret, val);
1376 xmlFree(val);
1378 } else {
1379 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
1380 ctxt->node, ret, value);
1382 } else
1383 #endif /* LIBXML_VALID_ENABLED */
1384 if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
1385 (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
1386 ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0))) &&
1387 /* Don't create IDs containing entity references */
1388 (ret->children != NULL) &&
1389 (ret->children->type == XML_TEXT_NODE) &&
1390 (ret->children->next == NULL)) {
1391 xmlChar *content = ret->children->content;
1393 * when validating, the ID registration is done at the attribute
1394 * validation level. Otherwise we have to do specific handling here.
1396 if (xmlStrEqual(fullname, BAD_CAST "xml:id")) {
1398 * Add the xml:id value
1400 * Open issue: normalization of the value.
1402 if (xmlValidateNCName(content, 1) != 0) {
1403 xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
1404 "xml:id : attribute value %s is not an NCName\n",
1405 (const char *) content, NULL);
1407 xmlAddID(&ctxt->vctxt, ctxt->myDoc, content, ret);
1408 } else if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
1409 xmlAddID(&ctxt->vctxt, ctxt->myDoc, content, ret);
1410 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
1411 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, content, ret);
1414 error:
1415 if (nval != NULL)
1416 xmlFree(nval);
1417 if (ns != NULL)
1418 xmlFree(ns);
1422 * xmlCheckDefaultedAttributes:
1424 * Check defaulted attributes from the DTD
1426 static void
1427 xmlCheckDefaultedAttributes(xmlParserCtxtPtr ctxt, const xmlChar *name,
1428 const xmlChar *prefix, const xmlChar **atts) {
1429 xmlElementPtr elemDecl;
1430 const xmlChar *att;
1431 int internal = 1;
1432 int i;
1434 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset, name, prefix);
1435 if (elemDecl == NULL) {
1436 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset, name, prefix);
1437 internal = 0;
1440 process_external_subset:
1442 if (elemDecl != NULL) {
1443 xmlAttributePtr attr = elemDecl->attributes;
1445 * Check against defaulted attributes from the external subset
1446 * if the document is stamped as standalone
1448 if ((ctxt->myDoc->standalone == 1) &&
1449 (ctxt->myDoc->extSubset != NULL) &&
1450 (ctxt->validate)) {
1451 while (attr != NULL) {
1452 if ((attr->defaultValue != NULL) &&
1453 (xmlGetDtdQAttrDesc(ctxt->myDoc->extSubset,
1454 attr->elem, attr->name,
1455 attr->prefix) == attr) &&
1456 (xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1457 attr->elem, attr->name,
1458 attr->prefix) == NULL)) {
1459 xmlChar *fulln;
1461 if (attr->prefix != NULL) {
1462 fulln = xmlStrdup(attr->prefix);
1463 fulln = xmlStrcat(fulln, BAD_CAST ":");
1464 fulln = xmlStrcat(fulln, attr->name);
1465 } else {
1466 fulln = xmlStrdup(attr->name);
1468 if (fulln == NULL) {
1469 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
1470 break;
1474 * Check that the attribute is not declared in the
1475 * serialization
1477 att = NULL;
1478 if (atts != NULL) {
1479 i = 0;
1480 att = atts[i];
1481 while (att != NULL) {
1482 if (xmlStrEqual(att, fulln))
1483 break;
1484 i += 2;
1485 att = atts[i];
1488 if (att == NULL) {
1489 xmlErrValid(ctxt, XML_DTD_STANDALONE_DEFAULTED,
1490 "standalone: attribute %s on %s defaulted from external subset\n",
1491 (const char *)fulln,
1492 (const char *)attr->elem);
1494 xmlFree(fulln);
1496 attr = attr->nexth;
1501 * Actually insert defaulted values when needed
1503 attr = elemDecl->attributes;
1504 while (attr != NULL) {
1506 * Make sure that attributes redefinition occurring in the
1507 * internal subset are not overridden by definitions in the
1508 * external subset.
1510 if (attr->defaultValue != NULL) {
1512 * the element should be instantiated in the tree if:
1513 * - this is a namespace prefix
1514 * - the user required for completion in the tree
1515 * like XSLT
1516 * - there isn't already an attribute definition
1517 * in the internal subset overriding it.
1519 if (((attr->prefix != NULL) &&
1520 (xmlStrEqual(attr->prefix, BAD_CAST "xmlns"))) ||
1521 ((attr->prefix == NULL) &&
1522 (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) ||
1523 (ctxt->loadsubset & XML_COMPLETE_ATTRS)) {
1524 xmlAttributePtr tst;
1526 tst = xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1527 attr->elem, attr->name,
1528 attr->prefix);
1529 if ((tst == attr) || (tst == NULL)) {
1530 xmlChar fn[50];
1531 xmlChar *fulln;
1533 fulln = xmlBuildQName(attr->name, attr->prefix, fn, 50);
1534 if (fulln == NULL) {
1535 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
1536 return;
1540 * Check that the attribute is not declared in the
1541 * serialization
1543 att = NULL;
1544 if (atts != NULL) {
1545 i = 0;
1546 att = atts[i];
1547 while (att != NULL) {
1548 if (xmlStrEqual(att, fulln))
1549 break;
1550 i += 2;
1551 att = atts[i];
1554 if (att == NULL) {
1555 xmlSAX2AttributeInternal(ctxt, fulln,
1556 attr->defaultValue, prefix);
1558 if ((fulln != fn) && (fulln != attr->name))
1559 xmlFree(fulln);
1563 attr = attr->nexth;
1565 if (internal == 1) {
1566 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset,
1567 name, prefix);
1568 internal = 0;
1569 goto process_external_subset;
1575 * xmlSAX2StartElement:
1576 * @ctx: the user data (XML parser context)
1577 * @fullname: The element name, including namespace prefix
1578 * @atts: An array of name/value attributes pairs, NULL terminated
1580 * called when an opening tag has been processed.
1582 void
1583 xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
1585 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1586 xmlNodePtr ret;
1587 xmlNodePtr parent;
1588 xmlNsPtr ns;
1589 xmlChar *name;
1590 xmlChar *prefix;
1591 const xmlChar *att;
1592 const xmlChar *value;
1593 int i;
1595 if ((ctx == NULL) || (fullname == NULL) || (ctxt->myDoc == NULL)) return;
1596 parent = ctxt->node;
1597 #ifdef DEBUG_SAX
1598 xmlGenericError(xmlGenericErrorContext,
1599 "SAX.xmlSAX2StartElement(%s)\n", fullname);
1600 #endif
1603 * First check on validity:
1605 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
1606 ((ctxt->myDoc->intSubset == NULL) ||
1607 ((ctxt->myDoc->intSubset->notations == NULL) &&
1608 (ctxt->myDoc->intSubset->elements == NULL) &&
1609 (ctxt->myDoc->intSubset->attributes == NULL) &&
1610 (ctxt->myDoc->intSubset->entities == NULL)))) {
1611 xmlErrValid(ctxt, XML_ERR_NO_DTD,
1612 "Validation failed: no DTD found !", NULL, NULL);
1613 ctxt->validate = 0;
1618 * Split the full name into a namespace prefix and the tag name
1620 name = xmlSplitQName(ctxt, fullname, &prefix);
1624 * Note : the namespace resolution is deferred until the end of the
1625 * attributes parsing, since local namespace can be defined as
1626 * an attribute at this level.
1628 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL);
1629 if (ret == NULL) {
1630 if (prefix != NULL)
1631 xmlFree(prefix);
1632 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
1633 return;
1635 if (ctxt->myDoc->children == NULL) {
1636 #ifdef DEBUG_SAX_TREE
1637 xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
1638 #endif
1639 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1640 } else if (parent == NULL) {
1641 parent = ctxt->myDoc->children;
1643 ctxt->nodemem = -1;
1644 if (ctxt->linenumbers) {
1645 if (ctxt->input != NULL) {
1646 if (ctxt->input->line < USHRT_MAX)
1647 ret->line = (unsigned short) ctxt->input->line;
1648 else
1649 ret->line = USHRT_MAX;
1654 * We are parsing a new node.
1656 #ifdef DEBUG_SAX_TREE
1657 xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);
1658 #endif
1659 if (nodePush(ctxt, ret) < 0) {
1660 xmlUnlinkNode(ret);
1661 xmlFreeNode(ret);
1662 if (prefix != NULL)
1663 xmlFree(prefix);
1664 return;
1668 * Link the child element
1670 if (parent != NULL) {
1671 if (parent->type == XML_ELEMENT_NODE) {
1672 #ifdef DEBUG_SAX_TREE
1673 xmlGenericError(xmlGenericErrorContext,
1674 "adding child %s to %s\n", name, parent->name);
1675 #endif
1676 xmlAddChild(parent, ret);
1677 } else {
1678 #ifdef DEBUG_SAX_TREE
1679 xmlGenericError(xmlGenericErrorContext,
1680 "adding sibling %s to ", name);
1681 xmlDebugDumpOneNode(stderr, parent, 0);
1682 #endif
1683 xmlAddSibling(parent, ret);
1687 if (!ctxt->html) {
1689 * Insert all the defaulted attributes from the DTD especially
1690 * namespaces
1692 if ((ctxt->myDoc->intSubset != NULL) ||
1693 (ctxt->myDoc->extSubset != NULL)) {
1694 xmlCheckDefaultedAttributes(ctxt, name, prefix, atts);
1698 * process all the attributes whose name start with "xmlns"
1700 if (atts != NULL) {
1701 i = 0;
1702 att = atts[i++];
1703 value = atts[i++];
1704 while ((att != NULL) && (value != NULL)) {
1705 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l') &&
1706 (att[3] == 'n') && (att[4] == 's'))
1707 xmlSAX2AttributeInternal(ctxt, att, value, prefix);
1709 att = atts[i++];
1710 value = atts[i++];
1715 * Search the namespace, note that since the attributes have been
1716 * processed, the local namespaces are available.
1718 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
1719 if ((ns == NULL) && (parent != NULL))
1720 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
1721 if ((prefix != NULL) && (ns == NULL)) {
1722 ns = xmlNewNs(ret, NULL, prefix);
1723 xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
1724 "Namespace prefix %s is not defined\n",
1725 prefix, NULL);
1729 * set the namespace node, making sure that if the default namespace
1730 * is unbound on a parent we simply keep it NULL
1732 if ((ns != NULL) && (ns->href != NULL) &&
1733 ((ns->href[0] != 0) || (ns->prefix != NULL)))
1734 xmlSetNs(ret, ns);
1738 * process all the other attributes
1740 if (atts != NULL) {
1741 i = 0;
1742 att = atts[i++];
1743 value = atts[i++];
1744 if (ctxt->html) {
1745 while (att != NULL) {
1746 xmlSAX2AttributeInternal(ctxt, att, value, NULL);
1747 att = atts[i++];
1748 value = atts[i++];
1750 } else {
1751 while ((att != NULL) && (value != NULL)) {
1752 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l') ||
1753 (att[3] != 'n') || (att[4] != 's'))
1754 xmlSAX2AttributeInternal(ctxt, att, value, NULL);
1757 * Next ones
1759 att = atts[i++];
1760 value = atts[i++];
1765 #ifdef LIBXML_VALID_ENABLED
1767 * If it's the Document root, finish the DTD validation and
1768 * check the document root element for validity
1770 if ((ctxt->validate) &&
1771 ((ctxt->vctxt.flags & XML_VCTXT_DTD_VALIDATED) == 0)) {
1772 int chk;
1774 chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
1775 if (chk <= 0)
1776 ctxt->valid = 0;
1777 if (chk < 0)
1778 ctxt->wellFormed = 0;
1779 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
1780 ctxt->vctxt.flags |= XML_VCTXT_DTD_VALIDATED;
1782 #endif /* LIBXML_VALID_ENABLED */
1784 if (prefix != NULL)
1785 xmlFree(prefix);
1790 * xmlSAX2EndElement:
1791 * @ctx: the user data (XML parser context)
1792 * @name: The element name
1794 * called when the end of an element has been detected.
1796 void
1797 xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
1799 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1800 xmlNodePtr cur;
1802 if (ctx == NULL) return;
1803 cur = ctxt->node;
1804 #ifdef DEBUG_SAX
1805 if (name == NULL)
1806 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(NULL)\n");
1807 else
1808 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(%s)\n", name);
1809 #endif
1811 /* Capture end position and add node */
1812 if (cur != NULL && ctxt->record_info) {
1813 ctxt->nodeInfo->end_pos = ctxt->input->cur - ctxt->input->base;
1814 ctxt->nodeInfo->end_line = ctxt->input->line;
1815 ctxt->nodeInfo->node = cur;
1816 xmlParserAddNodeInfo(ctxt, ctxt->nodeInfo);
1818 ctxt->nodemem = -1;
1820 #ifdef LIBXML_VALID_ENABLED
1821 if (ctxt->validate && ctxt->wellFormed &&
1822 ctxt->myDoc && ctxt->myDoc->intSubset)
1823 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
1824 cur);
1825 #endif /* LIBXML_VALID_ENABLED */
1829 * end of parsing of this node.
1831 #ifdef DEBUG_SAX_TREE
1832 xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);
1833 #endif
1834 nodePop(ctxt);
1836 #endif /* LIBXML_SAX1_ENABLED || LIBXML_HTML_ENABLED || LIBXML_LEGACY_ENABLED */
1839 * xmlSAX2TextNode:
1840 * @ctxt: the parser context
1841 * @str: the input string
1842 * @len: the string length
1844 * Callback for a text node
1846 * Returns the newly allocated string or NULL if not needed or error
1848 static xmlNodePtr
1849 xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
1850 xmlNodePtr ret;
1851 const xmlChar *intern = NULL;
1854 * Allocate
1856 if (ctxt->freeElems != NULL) {
1857 ret = ctxt->freeElems;
1858 ctxt->freeElems = ret->next;
1859 ctxt->freeElemsNr--;
1860 } else {
1861 ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1863 if (ret == NULL) {
1864 xmlErrMemory(ctxt, "xmlSAX2Characters");
1865 return(NULL);
1867 memset(ret, 0, sizeof(xmlNode));
1869 * intern the formatting blanks found between tags, or the
1870 * very short strings
1872 if (ctxt->dictNames) {
1873 xmlChar cur = str[len];
1875 if ((len < (int) (2 * sizeof(void *))) &&
1876 (ctxt->options & XML_PARSE_COMPACT)) {
1877 /* store the string in the node overriding properties and nsDef */
1878 xmlChar *tmp = (xmlChar *) &(ret->properties);
1879 memcpy(tmp, str, len);
1880 tmp[len] = 0;
1881 intern = tmp;
1882 } else if ((len <= 3) && ((cur == '"') || (cur == '\'') ||
1883 ((cur == '<') && (str[len + 1] != '!')))) {
1884 intern = xmlDictLookup(ctxt->dict, str, len);
1885 } else if (IS_BLANK_CH(*str) && (len < 60) && (cur == '<') &&
1886 (str[len + 1] != '!')) {
1887 int i;
1889 for (i = 1;i < len;i++) {
1890 if (!IS_BLANK_CH(str[i])) goto skip;
1892 intern = xmlDictLookup(ctxt->dict, str, len);
1895 skip:
1896 ret->type = XML_TEXT_NODE;
1898 ret->name = xmlStringText;
1899 if (intern == NULL) {
1900 ret->content = xmlStrndup(str, len);
1901 if (ret->content == NULL) {
1902 xmlSAX2ErrMemory(ctxt, "xmlSAX2TextNode");
1903 xmlFree(ret);
1904 return(NULL);
1906 } else
1907 ret->content = (xmlChar *) intern;
1909 if (ctxt->linenumbers) {
1910 if (ctxt->input != NULL) {
1911 if (ctxt->input->line < USHRT_MAX)
1912 ret->line = (unsigned short) ctxt->input->line;
1913 else {
1914 ret->line = USHRT_MAX;
1915 if (ctxt->options & XML_PARSE_BIG_LINES)
1916 ret->psvi = (void *) (ptrdiff_t) ctxt->input->line;
1921 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1922 xmlRegisterNodeDefaultValue(ret);
1923 return(ret);
1926 #ifdef LIBXML_VALID_ENABLED
1928 * xmlSAX2DecodeAttrEntities:
1929 * @ctxt: the parser context
1930 * @str: the input string
1931 * @len: the string length
1933 * Remove the entities from an attribute value
1935 * Returns the newly allocated string or NULL if not needed or error
1937 static xmlChar *
1938 xmlSAX2DecodeAttrEntities(xmlParserCtxtPtr ctxt, const xmlChar *str,
1939 const xmlChar *end) {
1940 const xmlChar *in;
1941 xmlChar *ret;
1943 in = str;
1944 while (in < end)
1945 if (*in++ == '&')
1946 goto decode;
1947 return(NULL);
1948 decode:
1949 ctxt->depth++;
1950 ret = xmlStringLenDecodeEntities(ctxt, str, end - str,
1951 XML_SUBSTITUTE_REF, 0,0,0);
1952 ctxt->depth--;
1953 return(ret);
1955 #endif /* LIBXML_VALID_ENABLED */
1958 * xmlSAX2AttributeNs:
1959 * @ctx: the user data (XML parser context)
1960 * @localname: the local name of the attribute
1961 * @prefix: the attribute namespace prefix if available
1962 * @URI: the attribute namespace name if available
1963 * @value: Start of the attribute value
1964 * @valueend: end of the attribute value
1966 * Handle an attribute that has been read by the parser.
1967 * The default handling is to convert the attribute into an
1968 * DOM subtree and past it in a new xmlAttr element added to
1969 * the element.
1971 static void
1972 xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
1973 const xmlChar * localname,
1974 const xmlChar * prefix,
1975 const xmlChar * value,
1976 const xmlChar * valueend)
1978 xmlAttrPtr ret;
1979 xmlNsPtr namespace = NULL;
1980 xmlChar *dup = NULL;
1983 * Note: if prefix == NULL, the attribute is not in the default namespace
1985 if (prefix != NULL)
1986 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, prefix);
1989 * allocate the node
1991 if (ctxt->freeAttrs != NULL) {
1992 ret = ctxt->freeAttrs;
1993 ctxt->freeAttrs = ret->next;
1994 ctxt->freeAttrsNr--;
1995 memset(ret, 0, sizeof(xmlAttr));
1996 ret->type = XML_ATTRIBUTE_NODE;
1998 ret->parent = ctxt->node;
1999 ret->doc = ctxt->myDoc;
2000 ret->ns = namespace;
2002 if (ctxt->dictNames)
2003 ret->name = localname;
2004 else
2005 ret->name = xmlStrdup(localname);
2007 /* link at the end to preserve order, TODO speed up with a last */
2008 if (ctxt->node->properties == NULL) {
2009 ctxt->node->properties = ret;
2010 } else {
2011 xmlAttrPtr prev = ctxt->node->properties;
2013 while (prev->next != NULL) prev = prev->next;
2014 prev->next = ret;
2015 ret->prev = prev;
2018 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2019 xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
2020 } else {
2021 if (ctxt->dictNames)
2022 ret = xmlNewNsPropEatName(ctxt->node, namespace,
2023 (xmlChar *) localname, NULL);
2024 else
2025 ret = xmlNewNsProp(ctxt->node, namespace, localname, NULL);
2026 if (ret == NULL) {
2027 xmlErrMemory(ctxt, "xmlSAX2AttributeNs");
2028 return;
2032 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
2033 xmlNodePtr tmp;
2036 * We know that if there is an entity reference, then
2037 * the string has been dup'ed and terminates with 0
2038 * otherwise with ' or "
2040 if (*valueend != 0) {
2041 tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
2042 ret->children = tmp;
2043 ret->last = tmp;
2044 if (tmp != NULL) {
2045 tmp->doc = ret->doc;
2046 tmp->parent = (xmlNodePtr) ret;
2048 } else {
2049 ret->children = xmlStringLenGetNodeList(ctxt->myDoc, value,
2050 valueend - value);
2051 tmp = ret->children;
2052 while (tmp != NULL) {
2053 tmp->doc = ret->doc;
2054 tmp->parent = (xmlNodePtr) ret;
2055 if (tmp->next == NULL)
2056 ret->last = tmp;
2057 tmp = tmp->next;
2060 } else if (value != NULL) {
2061 xmlNodePtr tmp;
2063 tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
2064 ret->children = tmp;
2065 ret->last = tmp;
2066 if (tmp != NULL) {
2067 tmp->doc = ret->doc;
2068 tmp->parent = (xmlNodePtr) ret;
2072 #ifdef LIBXML_VALID_ENABLED
2073 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
2074 ctxt->myDoc && ctxt->myDoc->intSubset) {
2076 * If we don't substitute entities, the validation should be
2077 * done on a value with replaced entities anyway.
2079 if (!ctxt->replaceEntities) {
2080 dup = xmlSAX2DecodeAttrEntities(ctxt, value, valueend);
2081 if (dup == NULL) {
2082 if (*valueend == 0) {
2083 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2084 ctxt->myDoc, ctxt->node, ret, value);
2085 } else {
2087 * That should already be normalized.
2088 * cheaper to finally allocate here than duplicate
2089 * entry points in the full validation code
2091 dup = xmlStrndup(value, valueend - value);
2093 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2094 ctxt->myDoc, ctxt->node, ret, dup);
2096 } else {
2098 * dup now contains a string of the flattened attribute
2099 * content with entities substituted. Check if we need to
2100 * apply an extra layer of normalization.
2101 * It need to be done twice ... it's an extra burden related
2102 * to the ability to keep references in attributes
2104 if (ctxt->attsSpecial != NULL) {
2105 xmlChar *nvalnorm;
2106 xmlChar fn[50];
2107 xmlChar *fullname;
2109 fullname = xmlBuildQName(localname, prefix, fn, 50);
2110 if (fullname != NULL) {
2111 ctxt->vctxt.valid = 1;
2112 nvalnorm = xmlValidCtxtNormalizeAttributeValue(
2113 &ctxt->vctxt, ctxt->myDoc,
2114 ctxt->node, fullname, dup);
2115 if (ctxt->vctxt.valid != 1)
2116 ctxt->valid = 0;
2118 if ((fullname != fn) && (fullname != localname))
2119 xmlFree(fullname);
2120 if (nvalnorm != NULL) {
2121 xmlFree(dup);
2122 dup = nvalnorm;
2127 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2128 ctxt->myDoc, ctxt->node, ret, dup);
2130 } else {
2132 * if entities already have been substituted, then
2133 * the attribute as passed is already normalized
2135 dup = xmlStrndup(value, valueend - value);
2137 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2138 ctxt->myDoc, ctxt->node, ret, dup);
2140 } else
2141 #endif /* LIBXML_VALID_ENABLED */
2142 if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
2143 (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
2144 ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0))) &&
2145 /* Don't create IDs containing entity references */
2146 (ret->children != NULL) &&
2147 (ret->children->type == XML_TEXT_NODE) &&
2148 (ret->children->next == NULL)) {
2149 xmlChar *content = ret->children->content;
2151 * when validating, the ID registration is done at the attribute
2152 * validation level. Otherwise we have to do specific handling here.
2154 if ((prefix == ctxt->str_xml) &&
2155 (localname[0] == 'i') && (localname[1] == 'd') &&
2156 (localname[2] == 0)) {
2158 * Add the xml:id value
2160 * Open issue: normalization of the value.
2162 #if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_LEGACY_ENABLED)
2163 #ifdef LIBXML_VALID_ENABLED
2164 if (xmlValidateNCName(content, 1) != 0) {
2165 xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
2166 "xml:id : attribute value %s is not an NCName\n",
2167 (const char *) content, NULL);
2169 #endif
2170 #endif
2171 xmlAddID(&ctxt->vctxt, ctxt->myDoc, content, ret);
2172 } else if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) {
2173 xmlAddID(&ctxt->vctxt, ctxt->myDoc, content, ret);
2174 } else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) {
2175 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, content, ret);
2178 if (dup != NULL)
2179 xmlFree(dup);
2183 * xmlSAX2StartElementNs:
2184 * @ctx: the user data (XML parser context)
2185 * @localname: the local name of the element
2186 * @prefix: the element namespace prefix if available
2187 * @URI: the element namespace name if available
2188 * @nb_namespaces: number of namespace definitions on that node
2189 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
2190 * @nb_attributes: the number of attributes on that node
2191 * @nb_defaulted: the number of defaulted attributes.
2192 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
2193 * attribute values.
2195 * SAX2 callback when an element start has been detected by the parser.
2196 * It provides the namespace information for the element, as well as
2197 * the new namespace declarations on the element.
2199 void
2200 xmlSAX2StartElementNs(void *ctx,
2201 const xmlChar *localname,
2202 const xmlChar *prefix,
2203 const xmlChar *URI,
2204 int nb_namespaces,
2205 const xmlChar **namespaces,
2206 int nb_attributes,
2207 int nb_defaulted,
2208 const xmlChar **attributes)
2210 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2211 xmlNodePtr ret;
2212 xmlNodePtr parent;
2213 xmlNsPtr last = NULL, ns;
2214 const xmlChar *uri, *pref;
2215 xmlChar *lname = NULL;
2216 int i, j;
2218 if (ctx == NULL) return;
2219 parent = ctxt->node;
2221 * First check on validity:
2223 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
2224 ((ctxt->myDoc->intSubset == NULL) ||
2225 ((ctxt->myDoc->intSubset->notations == NULL) &&
2226 (ctxt->myDoc->intSubset->elements == NULL) &&
2227 (ctxt->myDoc->intSubset->attributes == NULL) &&
2228 (ctxt->myDoc->intSubset->entities == NULL)))) {
2229 xmlErrValid(ctxt, XML_DTD_NO_DTD,
2230 "Validation failed: no DTD found !", NULL, NULL);
2231 ctxt->validate = 0;
2235 * Take care of the rare case of an undefined namespace prefix
2237 if ((prefix != NULL) && (URI == NULL)) {
2238 if (ctxt->dictNames) {
2239 const xmlChar *fullname;
2241 fullname = xmlDictQLookup(ctxt->dict, prefix, localname);
2242 if (fullname != NULL)
2243 localname = fullname;
2244 } else {
2245 lname = xmlBuildQName(localname, prefix, NULL, 0);
2249 * allocate the node
2251 if (ctxt->freeElems != NULL) {
2252 ret = ctxt->freeElems;
2253 ctxt->freeElems = ret->next;
2254 ctxt->freeElemsNr--;
2255 memset(ret, 0, sizeof(xmlNode));
2256 ret->doc = ctxt->myDoc;
2257 ret->type = XML_ELEMENT_NODE;
2259 if (ctxt->dictNames)
2260 ret->name = localname;
2261 else {
2262 if (lname == NULL)
2263 ret->name = xmlStrdup(localname);
2264 else
2265 ret->name = lname;
2266 if (ret->name == NULL) {
2267 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
2268 return;
2271 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2272 xmlRegisterNodeDefaultValue(ret);
2273 } else {
2274 if (ctxt->dictNames)
2275 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
2276 (xmlChar *) localname, NULL);
2277 else if (lname == NULL)
2278 ret = xmlNewDocNode(ctxt->myDoc, NULL, localname, NULL);
2279 else
2280 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
2281 (xmlChar *) lname, NULL);
2282 if (ret == NULL) {
2283 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
2284 return;
2287 if (ctxt->linenumbers) {
2288 if (ctxt->input != NULL) {
2289 if (ctxt->input->line < USHRT_MAX)
2290 ret->line = (unsigned short) ctxt->input->line;
2291 else
2292 ret->line = USHRT_MAX;
2296 if (parent == NULL) {
2297 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2300 * Build the namespace list
2302 for (i = 0,j = 0;j < nb_namespaces;j++) {
2303 pref = namespaces[i++];
2304 uri = namespaces[i++];
2305 ns = xmlNewNs(NULL, uri, pref);
2306 if (ns != NULL) {
2307 if (last == NULL) {
2308 ret->nsDef = last = ns;
2309 } else {
2310 last->next = ns;
2311 last = ns;
2313 if ((URI != NULL) && (prefix == pref))
2314 ret->ns = ns;
2315 } else {
2317 * any out of memory error would already have been raised
2318 * but we can't be guaranteed it's the actual error due to the
2319 * API, best is to skip in this case
2321 continue;
2323 #ifdef LIBXML_VALID_ENABLED
2324 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
2325 ctxt->myDoc && ctxt->myDoc->intSubset) {
2326 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
2327 ret, prefix, ns, uri);
2329 #endif /* LIBXML_VALID_ENABLED */
2331 ctxt->nodemem = -1;
2334 * We are parsing a new node.
2336 if (nodePush(ctxt, ret) < 0) {
2337 xmlUnlinkNode(ret);
2338 xmlFreeNode(ret);
2339 return;
2343 * Link the child element
2345 if (parent != NULL) {
2346 if (parent->type == XML_ELEMENT_NODE) {
2347 xmlAddChild(parent, ret);
2348 } else {
2349 xmlAddSibling(parent, ret);
2354 * Insert the defaulted attributes from the DTD only if requested:
2356 if ((nb_defaulted != 0) &&
2357 ((ctxt->loadsubset & XML_COMPLETE_ATTRS) == 0))
2358 nb_attributes -= nb_defaulted;
2361 * Search the namespace if it wasn't already found
2362 * Note that, if prefix is NULL, this searches for the default Ns
2364 if ((URI != NULL) && (ret->ns == NULL)) {
2365 ret->ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
2366 if ((ret->ns == NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) {
2367 ret->ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
2369 if (ret->ns == NULL) {
2370 ns = xmlNewNs(ret, NULL, prefix);
2371 if (ns == NULL) {
2373 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
2374 return;
2376 if (prefix != NULL)
2377 xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
2378 "Namespace prefix %s was not found\n",
2379 prefix, NULL);
2380 else
2381 xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
2382 "Namespace default prefix was not found\n",
2383 NULL, NULL);
2388 * process all the other attributes
2390 if (nb_attributes > 0) {
2391 for (j = 0,i = 0;i < nb_attributes;i++,j+=5) {
2393 * Handle the rare case of an undefined attribute prefix
2395 if ((attributes[j+1] != NULL) && (attributes[j+2] == NULL)) {
2396 if (ctxt->dictNames) {
2397 const xmlChar *fullname;
2399 fullname = xmlDictQLookup(ctxt->dict, attributes[j+1],
2400 attributes[j]);
2401 if (fullname != NULL) {
2402 xmlSAX2AttributeNs(ctxt, fullname, NULL,
2403 attributes[j+3], attributes[j+4]);
2404 continue;
2406 } else {
2407 lname = xmlBuildQName(attributes[j], attributes[j+1],
2408 NULL, 0);
2409 if (lname != NULL) {
2410 xmlSAX2AttributeNs(ctxt, lname, NULL,
2411 attributes[j+3], attributes[j+4]);
2412 xmlFree(lname);
2413 continue;
2417 xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1],
2418 attributes[j+3], attributes[j+4]);
2422 #ifdef LIBXML_VALID_ENABLED
2424 * If it's the Document root, finish the DTD validation and
2425 * check the document root element for validity
2427 if ((ctxt->validate) &&
2428 ((ctxt->vctxt.flags & XML_VCTXT_DTD_VALIDATED) == 0)) {
2429 int chk;
2431 chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
2432 if (chk <= 0)
2433 ctxt->valid = 0;
2434 if (chk < 0)
2435 ctxt->wellFormed = 0;
2436 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
2437 ctxt->vctxt.flags |= XML_VCTXT_DTD_VALIDATED;
2439 #endif /* LIBXML_VALID_ENABLED */
2443 * xmlSAX2EndElementNs:
2444 * @ctx: the user data (XML parser context)
2445 * @localname: the local name of the element
2446 * @prefix: the element namespace prefix if available
2447 * @URI: the element namespace name if available
2449 * SAX2 callback when an element end has been detected by the parser.
2450 * It provides the namespace information for the element.
2452 void
2453 xmlSAX2EndElementNs(void *ctx,
2454 const xmlChar * localname ATTRIBUTE_UNUSED,
2455 const xmlChar * prefix ATTRIBUTE_UNUSED,
2456 const xmlChar * URI ATTRIBUTE_UNUSED)
2458 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2459 xmlParserNodeInfo node_info;
2460 xmlNodePtr cur;
2462 if (ctx == NULL) return;
2463 cur = ctxt->node;
2464 /* Capture end position and add node */
2465 if ((ctxt->record_info) && (cur != NULL)) {
2466 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
2467 node_info.end_line = ctxt->input->line;
2468 node_info.node = cur;
2469 xmlParserAddNodeInfo(ctxt, &node_info);
2471 ctxt->nodemem = -1;
2473 #ifdef LIBXML_VALID_ENABLED
2474 if (ctxt->validate && ctxt->wellFormed &&
2475 ctxt->myDoc && ctxt->myDoc->intSubset)
2476 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, cur);
2477 #endif /* LIBXML_VALID_ENABLED */
2480 * end of parsing of this node.
2482 nodePop(ctxt);
2486 * xmlSAX2Reference:
2487 * @ctx: the user data (XML parser context)
2488 * @name: The entity name
2490 * called when an entity xmlSAX2Reference is detected.
2492 void
2493 xmlSAX2Reference(void *ctx, const xmlChar *name)
2495 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2496 xmlNodePtr ret;
2498 if (ctx == NULL) return;
2499 #ifdef DEBUG_SAX
2500 xmlGenericError(xmlGenericErrorContext,
2501 "SAX.xmlSAX2Reference(%s)\n", name);
2502 #endif
2503 if (name[0] == '#')
2504 ret = xmlNewCharRef(ctxt->myDoc, name);
2505 else
2506 ret = xmlNewReference(ctxt->myDoc, name);
2507 #ifdef DEBUG_SAX_TREE
2508 xmlGenericError(xmlGenericErrorContext,
2509 "add xmlSAX2Reference %s to %s \n", name, ctxt->node->name);
2510 #endif
2511 if (xmlAddChild(ctxt->node, ret) == NULL) {
2512 xmlFreeNode(ret);
2517 * xmlSAX2Text:
2518 * @ctx: the user data (XML parser context)
2519 * @ch: a xmlChar string
2520 * @len: the number of xmlChar
2521 * @type: text or cdata
2523 * Append characters.
2525 static void
2526 xmlSAX2Text(xmlParserCtxtPtr ctxt, const xmlChar *ch, int len,
2527 xmlElementType type)
2529 xmlNodePtr lastChild;
2531 if (ctxt == NULL) return;
2532 #ifdef DEBUG_SAX
2533 xmlGenericError(xmlGenericErrorContext,
2534 "SAX.xmlSAX2Characters(%.30s, %d)\n", ch, len);
2535 #endif
2537 * Handle the data if any. If there is no child
2538 * add it as content, otherwise if the last child is text,
2539 * concatenate it, else create a new node of type text.
2542 if (ctxt->node == NULL) {
2543 #ifdef DEBUG_SAX_TREE
2544 xmlGenericError(xmlGenericErrorContext,
2545 "add chars: ctxt->node == NULL !\n");
2546 #endif
2547 return;
2549 lastChild = ctxt->node->last;
2550 #ifdef DEBUG_SAX_TREE
2551 xmlGenericError(xmlGenericErrorContext,
2552 "add chars to %s \n", ctxt->node->name);
2553 #endif
2556 * Here we needed an accelerator mechanism in case of very large
2557 * elements. Use an attribute in the structure !!!
2559 if (lastChild == NULL) {
2560 if (type == XML_TEXT_NODE)
2561 lastChild = xmlSAX2TextNode(ctxt, ch, len);
2562 else
2563 lastChild = xmlNewCDataBlock(ctxt->myDoc, ch, len);
2564 if (lastChild != NULL) {
2565 ctxt->node->children = lastChild;
2566 ctxt->node->last = lastChild;
2567 lastChild->parent = ctxt->node;
2568 lastChild->doc = ctxt->node->doc;
2569 ctxt->nodelen = len;
2570 ctxt->nodemem = len + 1;
2571 } else {
2572 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
2573 return;
2575 } else {
2576 int coalesceText = (lastChild != NULL) &&
2577 (lastChild->type == type) &&
2578 ((type != XML_TEXT_NODE) ||
2579 (lastChild->name == xmlStringText));
2580 if ((coalesceText) && (ctxt->nodemem != 0)) {
2582 * The whole point of maintaining nodelen and nodemem,
2583 * xmlTextConcat is too costly, i.e. compute length,
2584 * reallocate a new buffer, move data, append ch. Here
2585 * We try to minimize realloc() uses and avoid copying
2586 * and recomputing length over and over.
2588 if (lastChild->content == (xmlChar *)&(lastChild->properties)) {
2589 lastChild->content = xmlStrdup(lastChild->content);
2590 lastChild->properties = NULL;
2591 } else if ((ctxt->nodemem == ctxt->nodelen + 1) &&
2592 (xmlDictOwns(ctxt->dict, lastChild->content))) {
2593 lastChild->content = xmlStrdup(lastChild->content);
2595 if (lastChild->content == NULL) {
2596 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters: xmlStrdup returned NULL");
2597 return;
2599 if (((size_t)ctxt->nodelen + (size_t)len > XML_MAX_TEXT_LENGTH) &&
2600 ((ctxt->options & XML_PARSE_HUGE) == 0)) {
2601 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters: huge text node");
2602 return;
2604 if ((size_t)ctxt->nodelen > SIZE_T_MAX - (size_t)len ||
2605 (size_t)ctxt->nodemem + (size_t)len > SIZE_T_MAX / 2) {
2606 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters overflow prevented");
2607 return;
2609 if (ctxt->nodelen + len >= ctxt->nodemem) {
2610 xmlChar *newbuf;
2611 size_t size;
2613 size = ctxt->nodemem + len;
2614 size *= 2;
2615 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
2616 if (newbuf == NULL) {
2617 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
2618 return;
2620 ctxt->nodemem = size;
2621 lastChild->content = newbuf;
2623 memcpy(&lastChild->content[ctxt->nodelen], ch, len);
2624 ctxt->nodelen += len;
2625 lastChild->content[ctxt->nodelen] = 0;
2626 } else if (coalesceText) {
2627 if (xmlTextConcat(lastChild, ch, len)) {
2628 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
2630 if (ctxt->node->children != NULL) {
2631 ctxt->nodelen = xmlStrlen(lastChild->content);
2632 ctxt->nodemem = ctxt->nodelen + 1;
2634 } else {
2635 /* Mixed content, first time */
2636 if (type == XML_TEXT_NODE) {
2637 lastChild = xmlSAX2TextNode(ctxt, ch, len);
2638 lastChild->doc = ctxt->myDoc;
2639 } else
2640 lastChild = xmlNewCDataBlock(ctxt->myDoc, ch, len);
2641 if (lastChild != NULL) {
2642 xmlAddChild(ctxt->node, lastChild);
2643 if (ctxt->node->children != NULL) {
2644 ctxt->nodelen = len;
2645 ctxt->nodemem = len + 1;
2653 * xmlSAX2Characters:
2654 * @ctx: the user data (XML parser context)
2655 * @ch: a xmlChar string
2656 * @len: the number of xmlChar
2658 * receiving some chars from the parser.
2660 void
2661 xmlSAX2Characters(void *ctx, const xmlChar *ch, int len)
2663 xmlSAX2Text((xmlParserCtxtPtr) ctx, ch, len, XML_TEXT_NODE);
2667 * xmlSAX2IgnorableWhitespace:
2668 * @ctx: the user data (XML parser context)
2669 * @ch: a xmlChar string
2670 * @len: the number of xmlChar
2672 * receiving some ignorable whitespaces from the parser.
2673 * UNUSED: by default the DOM building will use xmlSAX2Characters
2675 void
2676 xmlSAX2IgnorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
2678 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
2679 #ifdef DEBUG_SAX
2680 xmlGenericError(xmlGenericErrorContext,
2681 "SAX.xmlSAX2IgnorableWhitespace(%.30s, %d)\n", ch, len);
2682 #endif
2686 * xmlSAX2ProcessingInstruction:
2687 * @ctx: the user data (XML parser context)
2688 * @target: the target name
2689 * @data: the PI data's
2691 * A processing instruction has been parsed.
2693 void
2694 xmlSAX2ProcessingInstruction(void *ctx, const xmlChar *target,
2695 const xmlChar *data)
2697 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2698 xmlNodePtr ret;
2699 xmlNodePtr parent;
2701 if (ctx == NULL) return;
2702 parent = ctxt->node;
2703 #ifdef DEBUG_SAX
2704 xmlGenericError(xmlGenericErrorContext,
2705 "SAX.xmlSAX2ProcessingInstruction(%s, %s)\n", target, data);
2706 #endif
2708 ret = xmlNewDocPI(ctxt->myDoc, target, data);
2709 if (ret == NULL) return;
2711 if (ctxt->linenumbers) {
2712 if (ctxt->input != NULL) {
2713 if (ctxt->input->line < USHRT_MAX)
2714 ret->line = (unsigned short) ctxt->input->line;
2715 else
2716 ret->line = USHRT_MAX;
2719 if (ctxt->inSubset == 1) {
2720 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2721 return;
2722 } else if (ctxt->inSubset == 2) {
2723 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2724 return;
2726 if (parent == NULL) {
2727 #ifdef DEBUG_SAX_TREE
2728 xmlGenericError(xmlGenericErrorContext,
2729 "Setting PI %s as root\n", target);
2730 #endif
2731 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2732 return;
2734 if (parent->type == XML_ELEMENT_NODE) {
2735 #ifdef DEBUG_SAX_TREE
2736 xmlGenericError(xmlGenericErrorContext,
2737 "adding PI %s child to %s\n", target, parent->name);
2738 #endif
2739 xmlAddChild(parent, ret);
2740 } else {
2741 #ifdef DEBUG_SAX_TREE
2742 xmlGenericError(xmlGenericErrorContext,
2743 "adding PI %s sibling to ", target);
2744 xmlDebugDumpOneNode(stderr, parent, 0);
2745 #endif
2746 xmlAddSibling(parent, ret);
2751 * xmlSAX2Comment:
2752 * @ctx: the user data (XML parser context)
2753 * @value: the xmlSAX2Comment content
2755 * A xmlSAX2Comment has been parsed.
2757 void
2758 xmlSAX2Comment(void *ctx, const xmlChar *value)
2760 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2761 xmlNodePtr ret;
2762 xmlNodePtr parent;
2764 if (ctx == NULL) return;
2765 parent = ctxt->node;
2766 #ifdef DEBUG_SAX
2767 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2Comment(%s)\n", value);
2768 #endif
2769 ret = xmlNewDocComment(ctxt->myDoc, value);
2770 if (ret == NULL) return;
2771 if (ctxt->linenumbers) {
2772 if (ctxt->input != NULL) {
2773 if (ctxt->input->line < USHRT_MAX)
2774 ret->line = (unsigned short) ctxt->input->line;
2775 else
2776 ret->line = USHRT_MAX;
2780 if (ctxt->inSubset == 1) {
2781 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2782 return;
2783 } else if (ctxt->inSubset == 2) {
2784 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2785 return;
2787 if (parent == NULL) {
2788 #ifdef DEBUG_SAX_TREE
2789 xmlGenericError(xmlGenericErrorContext,
2790 "Setting xmlSAX2Comment as root\n");
2791 #endif
2792 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2793 return;
2795 if (parent->type == XML_ELEMENT_NODE) {
2796 #ifdef DEBUG_SAX_TREE
2797 xmlGenericError(xmlGenericErrorContext,
2798 "adding xmlSAX2Comment child to %s\n", parent->name);
2799 #endif
2800 xmlAddChild(parent, ret);
2801 } else {
2802 #ifdef DEBUG_SAX_TREE
2803 xmlGenericError(xmlGenericErrorContext,
2804 "adding xmlSAX2Comment sibling to ");
2805 xmlDebugDumpOneNode(stderr, parent, 0);
2806 #endif
2807 xmlAddSibling(parent, ret);
2812 * xmlSAX2CDataBlock:
2813 * @ctx: the user data (XML parser context)
2814 * @value: The pcdata content
2815 * @len: the block length
2817 * called when a pcdata block has been parsed
2819 void
2820 xmlSAX2CDataBlock(void *ctx, const xmlChar *value, int len)
2822 xmlSAX2Text((xmlParserCtxtPtr) ctx, value, len, XML_CDATA_SECTION_NODE);
2825 static int xmlSAX2DefaultVersionValue = 2;
2827 #ifdef LIBXML_SAX1_ENABLED
2829 * xmlSAXDefaultVersion:
2830 * @version: the version, 1 or 2
2832 * Set the default version of SAX used globally by the library.
2833 * By default, during initialization the default is set to 2.
2834 * Note that it is generally a better coding style to use
2835 * xmlSAXVersion() to set up the version explicitly for a given
2836 * parsing context.
2838 * Returns the previous value in case of success and -1 in case of error.
2841 xmlSAXDefaultVersion(int version)
2843 int ret = xmlSAX2DefaultVersionValue;
2845 if ((version != 1) && (version != 2))
2846 return(-1);
2847 xmlSAX2DefaultVersionValue = version;
2848 return(ret);
2850 #endif /* LIBXML_SAX1_ENABLED */
2853 * xmlSAXVersion:
2854 * @hdlr: the SAX handler
2855 * @version: the version, 1 or 2
2857 * Initialize the default XML SAX handler according to the version
2859 * Returns 0 in case of success and -1 in case of error.
2862 xmlSAXVersion(xmlSAXHandler *hdlr, int version)
2864 if (hdlr == NULL) return(-1);
2865 if (version == 2) {
2866 hdlr->startElement = NULL;
2867 hdlr->endElement = NULL;
2868 hdlr->startElementNs = xmlSAX2StartElementNs;
2869 hdlr->endElementNs = xmlSAX2EndElementNs;
2870 hdlr->serror = NULL;
2871 hdlr->initialized = XML_SAX2_MAGIC;
2872 #ifdef LIBXML_SAX1_ENABLED
2873 } else if (version == 1) {
2874 hdlr->startElement = xmlSAX2StartElement;
2875 hdlr->endElement = xmlSAX2EndElement;
2876 hdlr->initialized = 1;
2877 #endif /* LIBXML_SAX1_ENABLED */
2878 } else
2879 return(-1);
2880 hdlr->internalSubset = xmlSAX2InternalSubset;
2881 hdlr->externalSubset = xmlSAX2ExternalSubset;
2882 hdlr->isStandalone = xmlSAX2IsStandalone;
2883 hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
2884 hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
2885 hdlr->resolveEntity = xmlSAX2ResolveEntity;
2886 hdlr->getEntity = xmlSAX2GetEntity;
2887 hdlr->getParameterEntity = xmlSAX2GetParameterEntity;
2888 hdlr->entityDecl = xmlSAX2EntityDecl;
2889 hdlr->attributeDecl = xmlSAX2AttributeDecl;
2890 hdlr->elementDecl = xmlSAX2ElementDecl;
2891 hdlr->notationDecl = xmlSAX2NotationDecl;
2892 hdlr->unparsedEntityDecl = xmlSAX2UnparsedEntityDecl;
2893 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2894 hdlr->startDocument = xmlSAX2StartDocument;
2895 hdlr->endDocument = xmlSAX2EndDocument;
2896 hdlr->reference = xmlSAX2Reference;
2897 hdlr->characters = xmlSAX2Characters;
2898 hdlr->cdataBlock = xmlSAX2CDataBlock;
2899 hdlr->ignorableWhitespace = xmlSAX2Characters;
2900 hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
2901 hdlr->comment = xmlSAX2Comment;
2902 hdlr->warning = xmlParserWarning;
2903 hdlr->error = xmlParserError;
2904 hdlr->fatalError = xmlParserError;
2906 return(0);
2910 * xmlSAX2InitDefaultSAXHandler:
2911 * @hdlr: the SAX handler
2912 * @warning: flag if non-zero sets the handler warning procedure
2914 * Initialize the default XML SAX2 handler
2916 void
2917 xmlSAX2InitDefaultSAXHandler(xmlSAXHandler *hdlr, int warning)
2919 if ((hdlr == NULL) || (hdlr->initialized != 0))
2920 return;
2922 xmlSAXVersion(hdlr, xmlSAX2DefaultVersionValue);
2923 if (warning == 0)
2924 hdlr->warning = NULL;
2925 else
2926 hdlr->warning = xmlParserWarning;
2930 * xmlDefaultSAXHandlerInit:
2932 * DEPRECATED: This function will be made private. Call xmlInitParser to
2933 * initialize the library.
2935 * Initialize the default SAX2 handler
2937 void
2938 xmlDefaultSAXHandlerInit(void)
2940 #ifdef LIBXML_SAX1_ENABLED
2941 xmlSAXVersion((xmlSAXHandlerPtr) &xmlDefaultSAXHandler, 1);
2942 #endif /* LIBXML_SAX1_ENABLED */
2945 #ifdef LIBXML_HTML_ENABLED
2948 * xmlSAX2InitHtmlDefaultSAXHandler:
2949 * @hdlr: the SAX handler
2951 * Initialize the default HTML SAX2 handler
2953 void
2954 xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr)
2956 if ((hdlr == NULL) || (hdlr->initialized != 0))
2957 return;
2959 hdlr->internalSubset = xmlSAX2InternalSubset;
2960 hdlr->externalSubset = NULL;
2961 hdlr->isStandalone = NULL;
2962 hdlr->hasInternalSubset = NULL;
2963 hdlr->hasExternalSubset = NULL;
2964 hdlr->resolveEntity = NULL;
2965 hdlr->getEntity = xmlSAX2GetEntity;
2966 hdlr->getParameterEntity = NULL;
2967 hdlr->entityDecl = NULL;
2968 hdlr->attributeDecl = NULL;
2969 hdlr->elementDecl = NULL;
2970 hdlr->notationDecl = NULL;
2971 hdlr->unparsedEntityDecl = NULL;
2972 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2973 hdlr->startDocument = xmlSAX2StartDocument;
2974 hdlr->endDocument = xmlSAX2EndDocument;
2975 hdlr->startElement = xmlSAX2StartElement;
2976 hdlr->endElement = xmlSAX2EndElement;
2977 hdlr->reference = NULL;
2978 hdlr->characters = xmlSAX2Characters;
2979 hdlr->cdataBlock = xmlSAX2CDataBlock;
2980 hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
2981 hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
2982 hdlr->comment = xmlSAX2Comment;
2983 hdlr->warning = xmlParserWarning;
2984 hdlr->error = xmlParserError;
2985 hdlr->fatalError = xmlParserError;
2987 hdlr->initialized = 1;
2991 * htmlDefaultSAXHandlerInit:
2993 * DEPRECATED: This function will be made private. Call xmlInitParser to
2994 * initialize the library.
2996 * Initialize the default SAX handler
2998 void
2999 htmlDefaultSAXHandlerInit(void)
3001 xmlSAX2InitHtmlDefaultSAXHandler((xmlSAXHandlerPtr) &htmlDefaultSAXHandler);
3004 #endif /* LIBXML_HTML_ENABLED */