VirtualBox

source: vbox/trunk/src/libs/libxml2-2.6.31/SAX2.c@ 39954

Last change on this file since 39954 was 39921, checked in by vboxsync, 13 years ago

libxml-2.6.31 upstream fixes

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

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