VirtualBox

source: vbox/trunk/src/libs/libxml2-2.13.2/SAX2.c

最後變更 在這個檔案是 105420,由 vboxsync 提交於 4 月 前

libxml2-2.12.6: Applied and adjusted our libxml2 changes to 2.12.6. bugref:10730

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette