blob: d7e256b1815f7c1d450199185cec236966683592 [file] [log] [blame]
Owen Taylor3473f882001-02-23 17:55:21 +00001/*
2 * SAX.c : Default SAX handler to build a tree.
3 *
4 * See Copyright for the status of this software.
5 *
6 * Daniel Veillard <Daniel.Veillard@w3.org>
7 */
8
9
10#ifdef WIN32
11#include "win32config.h"
12#else
13#include "config.h"
14#endif
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18#include <libxml/xmlmemory.h>
19#include <libxml/tree.h>
20#include <libxml/parser.h>
21#include <libxml/parserInternals.h>
22#include <libxml/valid.h>
23#include <libxml/entities.h>
24#include <libxml/xmlerror.h>
25#include <libxml/debugXML.h>
26#include <libxml/xmlIO.h>
27#include <libxml/SAX.h>
28#include <libxml/uri.h>
29#include <libxml/HTMLtree.h>
30
31/* #define DEBUG_SAX */
32/* #define DEBUG_SAX_TREE */
33
34/**
35 * getPublicId:
36 * @ctx: the user data (XML parser context)
37 *
38 * Return the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
39 *
40 * Returns a xmlChar *
41 */
42const xmlChar *
43getPublicId(void *ctx)
44{
45 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
46 return(NULL);
47}
48
49/**
50 * getSystemId:
51 * @ctx: the user data (XML parser context)
52 *
53 * Return the system ID, basically URL or filename e.g.
54 * http://www.sgmlsource.com/dtds/memo.dtd
55 *
56 * Returns a xmlChar *
57 */
58const xmlChar *
59getSystemId(void *ctx)
60{
61 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
62 return(BAD_CAST ctxt->input->filename);
63}
64
65/**
66 * getLineNumber:
67 * @ctx: the user data (XML parser context)
68 *
69 * Return the line number of the current parsing point.
70 *
71 * Returns an int
72 */
73int
74getLineNumber(void *ctx)
75{
76 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
77 return(ctxt->input->line);
78}
79
80/**
81 * getColumnNumber:
82 * @ctx: the user data (XML parser context)
83 *
84 * Return the column number of the current parsing point.
85 *
86 * Returns an int
87 */
88int
89getColumnNumber(void *ctx)
90{
91 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
92 return(ctxt->input->col);
93}
94
95/*
96 * The default SAX Locator.
97 */
98
99xmlSAXLocator xmlDefaultSAXLocator = {
100 getPublicId, getSystemId, getLineNumber, getColumnNumber
101};
102
103/**
104 * isStandalone:
105 * @ctx: the user data (XML parser context)
106 *
107 * Is this document tagged standalone ?
108 *
109 * Returns 1 if true
110 */
111int
112isStandalone(void *ctx)
113{
114 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
115 return(ctxt->myDoc->standalone == 1);
116}
117
118/**
119 * hasInternalSubset:
120 * @ctx: the user data (XML parser context)
121 *
122 * Does this document has an internal subset
123 *
124 * Returns 1 if true
125 */
126int
127hasInternalSubset(void *ctx)
128{
129 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
130 return(ctxt->myDoc->intSubset != NULL);
131}
132
133/**
134 * hasExternalSubset:
135 * @ctx: the user data (XML parser context)
136 *
137 * Does this document has an external subset
138 *
139 * Returns 1 if true
140 */
141int
142hasExternalSubset(void *ctx)
143{
144 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
145 return(ctxt->myDoc->extSubset != NULL);
146}
147
148/**
149 * internalSubset:
150 * @ctx: the user data (XML parser context)
151 * @name: the root element name
152 * @ExternalID: the external ID
153 * @SystemID: the SYSTEM ID (e.g. filename or URL)
154 *
155 * Callback on internal subset declaration.
156 */
157void
158internalSubset(void *ctx, const xmlChar *name,
159 const xmlChar *ExternalID, const xmlChar *SystemID)
160{
161 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
162 xmlDtdPtr dtd;
163#ifdef DEBUG_SAX
164 xmlGenericError(xmlGenericErrorContext,
165 "SAX.internalSubset(%s, %s, %s)\n",
166 name, ExternalID, SystemID);
167#endif
168
169 if (ctxt->myDoc == NULL)
170 return;
171 dtd = xmlGetIntSubset(ctxt->myDoc);
172 if (dtd != NULL) {
173 if (ctxt->html)
174 return;
175 xmlUnlinkNode((xmlNodePtr) dtd);
176 xmlFreeDtd(dtd);
177 ctxt->myDoc->intSubset = NULL;
178 }
179 ctxt->myDoc->intSubset =
180 xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
181}
182
183/**
184 * externalSubset:
185 * @ctx: the user data (XML parser context)
186 * @name: the root element name
187 * @ExternalID: the external ID
188 * @SystemID: the SYSTEM ID (e.g. filename or URL)
189 *
190 * Callback on external subset declaration.
191 */
192void
193externalSubset(void *ctx, const xmlChar *name,
194 const xmlChar *ExternalID, const xmlChar *SystemID)
195{
196 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
197#ifdef DEBUG_SAX
198 xmlGenericError(xmlGenericErrorContext,
199 "SAX.externalSubset(%s, %s, %s)\n",
200 name, ExternalID, SystemID);
201#endif
202 if (((ExternalID != NULL) || (SystemID != NULL)) &&
203 (((ctxt->validate) || (ctxt->loadsubset)) &&
204 (ctxt->wellFormed && ctxt->myDoc))) {
205 /*
206 * Try to fetch and parse the external subset.
207 */
208 xmlParserInputPtr oldinput;
209 int oldinputNr;
210 int oldinputMax;
211 xmlParserInputPtr *oldinputTab;
212 int oldwellFormed;
213 xmlParserInputPtr input = NULL;
214 xmlCharEncoding enc;
215 int oldcharset;
216
217 /*
218 * Ask the Entity resolver to load the damn thing
219 */
220 if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
221 input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
222 SystemID);
223 if (input == NULL) {
224 return;
225 }
226
227 xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
228
229 /*
230 * make sure we won't destroy the main document context
231 */
232 oldinput = ctxt->input;
233 oldinputNr = ctxt->inputNr;
234 oldinputMax = ctxt->inputMax;
235 oldinputTab = ctxt->inputTab;
236 oldwellFormed = ctxt->wellFormed;
237 oldcharset = ctxt->charset;
238
239 ctxt->inputTab = (xmlParserInputPtr *)
240 xmlMalloc(5 * sizeof(xmlParserInputPtr));
241 if (ctxt->inputTab == NULL) {
242 ctxt->errNo = XML_ERR_NO_MEMORY;
243 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
244 ctxt->sax->error(ctxt->userData,
245 "externalSubset: out of memory\n");
246 ctxt->errNo = XML_ERR_NO_MEMORY;
247 ctxt->input = oldinput;
248 ctxt->inputNr = oldinputNr;
249 ctxt->inputMax = oldinputMax;
250 ctxt->inputTab = oldinputTab;
251 ctxt->charset = oldcharset;
252 return;
253 }
254 ctxt->inputNr = 0;
255 ctxt->inputMax = 5;
256 ctxt->input = NULL;
257 xmlPushInput(ctxt, input);
258
259 /*
260 * On the fly encoding conversion if needed
261 */
262 enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
263 xmlSwitchEncoding(ctxt, enc);
264
265 if (input->filename == NULL)
266 input->filename = (char *) xmlStrdup(SystemID);
267 input->line = 1;
268 input->col = 1;
269 input->base = ctxt->input->cur;
270 input->cur = ctxt->input->cur;
271 input->free = NULL;
272
273 /*
274 * let's parse that entity knowing it's an external subset.
275 */
276 xmlParseExternalSubset(ctxt, ExternalID, SystemID);
277
278 /*
279 * Free up the external entities
280 */
281
282 while (ctxt->inputNr > 1)
283 xmlPopInput(ctxt);
284 xmlFreeInputStream(ctxt->input);
285 xmlFree(ctxt->inputTab);
286
287 /*
288 * Restore the parsing context of the main entity
289 */
290 ctxt->input = oldinput;
291 ctxt->inputNr = oldinputNr;
292 ctxt->inputMax = oldinputMax;
293 ctxt->inputTab = oldinputTab;
294 ctxt->charset = oldcharset;
295 /* ctxt->wellFormed = oldwellFormed; */
296 }
297}
298
299/**
300 * resolveEntity:
301 * @ctx: the user data (XML parser context)
302 * @publicId: The public ID of the entity
303 * @systemId: The system ID of the entity
304 *
305 * The entity loader, to control the loading of external entities,
306 * the application can either:
307 * - override this resolveEntity() callback in the SAX block
308 * - or better use the xmlSetExternalEntityLoader() function to
309 * set up it's own entity resolution routine
310 *
311 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
312 */
313xmlParserInputPtr
314resolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
315{
316 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
317 xmlParserInputPtr ret;
318 xmlChar *URI;
319 const char *base = NULL;
320
321 if (ctxt->input != NULL)
322 base = ctxt->input->filename;
323 if (base == NULL)
324 base = ctxt->directory;
325
326 URI = xmlBuildURI(systemId, (const xmlChar *) base);
327
328#ifdef DEBUG_SAX
329 xmlGenericError(xmlGenericErrorContext,
330 "SAX.resolveEntity(%s, %s)\n", publicId, systemId);
331#endif
332
333 ret = xmlLoadExternalEntity((const char *) URI,
334 (const char *) publicId, ctxt);
335 if (URI != NULL)
336 xmlFree(URI);
337 return(ret);
338}
339
340/**
341 * getEntity:
342 * @ctx: the user data (XML parser context)
343 * @name: The entity name
344 *
345 * Get an entity by name
346 *
347 * Returns the xmlEntityPtr if found.
348 */
349xmlEntityPtr
350getEntity(void *ctx, const xmlChar *name)
351{
352 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
353 xmlEntityPtr ret;
354
355#ifdef DEBUG_SAX
356 xmlGenericError(xmlGenericErrorContext,
357 "SAX.getEntity(%s)\n", name);
358#endif
359
360 ret = xmlGetDocEntity(ctxt->myDoc, name);
361 if ((ret != NULL) && (ctxt->validate) && (ret->children == NULL) &&
362 (ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
363 /*
364 * for validation purposes we really need to fetch and
365 * parse the external entity
366 */
367 int parse;
368 xmlNodePtr children;
369
370 parse = xmlParseCtxtExternalEntity(ctxt,
371 ret->SystemID, ret->ExternalID, &children);
372 xmlAddChildList((xmlNodePtr) ret, children);
373 }
374 return(ret);
375}
376
377/**
378 * getParameterEntity:
379 * @ctx: the user data (XML parser context)
380 * @name: The entity name
381 *
382 * Get a parameter entity by name
383 *
384 * Returns the xmlEntityPtr if found.
385 */
386xmlEntityPtr
387getParameterEntity(void *ctx, const xmlChar *name)
388{
389 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
390 xmlEntityPtr ret;
391
392#ifdef DEBUG_SAX
393 xmlGenericError(xmlGenericErrorContext,
394 "SAX.getParameterEntity(%s)\n", name);
395#endif
396
397 ret = xmlGetParameterEntity(ctxt->myDoc, name);
398 return(ret);
399}
400
401
402/**
403 * entityDecl:
404 * @ctx: the user data (XML parser context)
405 * @name: the entity name
406 * @type: the entity type
407 * @publicId: The public ID of the entity
408 * @systemId: The system ID of the entity
409 * @content: the entity value (without processing).
410 *
411 * An entity definition has been parsed
412 */
413void
414entityDecl(void *ctx, const xmlChar *name, int type,
415 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
416{
417 xmlEntityPtr ent;
418 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
419
420#ifdef DEBUG_SAX
421 xmlGenericError(xmlGenericErrorContext,
422 "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
423 name, type, publicId, systemId, content);
424#endif
425 if (ctxt->inSubset == 1) {
426 ent = xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
427 systemId, content);
428 if ((ent == NULL) && (ctxt->pedantic) &&
429 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
430 ctxt->sax->warning(ctxt,
431 "Entity(%s) already defined in the internal subset\n", name);
432 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
433 xmlChar *URI;
434 const char *base = NULL;
435
436 if (ctxt->input != NULL)
437 base = ctxt->input->filename;
438 if (base == NULL)
439 base = ctxt->directory;
440
441 URI = xmlBuildURI(systemId, (const xmlChar *) base);
442 ent->URI = URI;
443 }
444 } else if (ctxt->inSubset == 2) {
445 ent = xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
446 systemId, content);
447 if ((ent == NULL) && (ctxt->pedantic) &&
448 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
449 ctxt->sax->warning(ctxt,
450 "Entity(%s) already defined in the external subset\n", name);
451 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
452 xmlChar *URI;
453 const char *base = NULL;
454
455 if (ctxt->input != NULL)
456 base = ctxt->input->filename;
457 if (base == NULL)
458 base = ctxt->directory;
459
460 URI = xmlBuildURI(systemId, (const xmlChar *) base);
461 ent->URI = URI;
462 }
463 } else {
464 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
465 ctxt->sax->error(ctxt,
466 "SAX.entityDecl(%s) called while not in subset\n", name);
467 }
468}
469
470/**
471 * attributeDecl:
472 * @ctx: the user data (XML parser context)
473 * @elem: the name of the element
474 * @fullname: the attribute name
475 * @type: the attribute type
476 * @def: the type of default value
477 * @defaultValue: the attribute default value
478 * @tree: the tree of enumerated value set
479 *
480 * An attribute definition has been parsed
481 */
482void
483attributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
484 int type, int def, const xmlChar *defaultValue,
485 xmlEnumerationPtr tree)
486{
487 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
488 xmlAttributePtr attr;
489 xmlChar *name = NULL, *prefix = NULL;
490
491#ifdef DEBUG_SAX
492 xmlGenericError(xmlGenericErrorContext,
493 "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
494 elem, fullname, type, def, defaultValue);
495#endif
496 name = xmlSplitQName(ctxt, fullname, &prefix);
497 if (ctxt->inSubset == 1)
498 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
499 name, prefix, (xmlAttributeType) type,
500 (xmlAttributeDefault) def, defaultValue, tree);
501 else if (ctxt->inSubset == 2)
502 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
503 name, prefix, (xmlAttributeType) type,
504 (xmlAttributeDefault) def, defaultValue, tree);
505 else {
506 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
507 ctxt->sax->error(ctxt,
508 "SAX.attributeDecl(%s) called while not in subset\n", name);
509 return;
510 }
511 if (attr == 0) ctxt->valid = 0;
512 if (ctxt->validate && ctxt->wellFormed &&
513 ctxt->myDoc && ctxt->myDoc->intSubset)
514 ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
515 attr);
516 if (prefix != NULL)
517 xmlFree(prefix);
518 if (name != NULL)
519 xmlFree(name);
520}
521
522/**
523 * elementDecl:
524 * @ctx: the user data (XML parser context)
525 * @name: the element name
526 * @type: the element type
527 * @content: the element value tree
528 *
529 * An element definition has been parsed
530 */
531void
532elementDecl(void *ctx, const xmlChar *name, int type,
533 xmlElementContentPtr content)
534{
535 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
536 xmlElementPtr elem = NULL;
537
538#ifdef DEBUG_SAX
539 xmlGenericError(xmlGenericErrorContext,
540 "SAX.elementDecl(%s, %d, ...)\n",
541 fullname, type);
542#endif
543
544 if (ctxt->inSubset == 1)
545 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
546 name, (xmlElementTypeVal) type, content);
547 else if (ctxt->inSubset == 2)
548 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
549 name, (xmlElementTypeVal) type, content);
550 else {
551 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
552 ctxt->sax->error(ctxt,
553 "SAX.elementDecl(%s) called while not in subset\n", name);
554 return;
555 }
556 if (elem == NULL) ctxt->valid = 0;
557 if (ctxt->validate && ctxt->wellFormed &&
558 ctxt->myDoc && ctxt->myDoc->intSubset)
559 ctxt->valid &= xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
560}
561
562/**
563 * notationDecl:
564 * @ctx: the user data (XML parser context)
565 * @name: The name of the notation
566 * @publicId: The public ID of the entity
567 * @systemId: The system ID of the entity
568 *
569 * What to do when a notation declaration has been parsed.
570 */
571void
572notationDecl(void *ctx, const xmlChar *name,
573 const xmlChar *publicId, const xmlChar *systemId)
574{
575 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
576 xmlNotationPtr nota = NULL;
577
578#ifdef DEBUG_SAX
579 xmlGenericError(xmlGenericErrorContext,
580 "SAX.notationDecl(%s, %s, %s)\n", name, publicId, systemId);
581#endif
582
583 if (ctxt->inSubset == 1)
584 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
585 publicId, systemId);
586 else if (ctxt->inSubset == 2)
587 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
588 publicId, systemId);
589 else {
590 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
591 ctxt->sax->error(ctxt,
592 "SAX.notationDecl(%s) called while not in subset\n", name);
593 return;
594 }
595 if (nota == NULL) ctxt->valid = 0;
596 if (ctxt->validate && ctxt->wellFormed &&
597 ctxt->myDoc && ctxt->myDoc->intSubset)
598 ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
599 nota);
600}
601
602/**
603 * unparsedEntityDecl:
604 * @ctx: the user data (XML parser context)
605 * @name: The name of the entity
606 * @publicId: The public ID of the entity
607 * @systemId: The system ID of the entity
608 * @notationName: the name of the notation
609 *
610 * What to do when an unparsed entity declaration is parsed
611 */
612void
613unparsedEntityDecl(void *ctx, const xmlChar *name,
614 const xmlChar *publicId, const xmlChar *systemId,
615 const xmlChar *notationName)
616{
617 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
618#ifdef DEBUG_SAX
619 xmlGenericError(xmlGenericErrorContext,
620 "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
621 name, publicId, systemId, notationName);
622#endif
623 if (ctxt->validate && ctxt->wellFormed &&
624 ctxt->myDoc && ctxt->myDoc->intSubset)
625 ctxt->valid &= xmlValidateNotationUse(&ctxt->vctxt, ctxt->myDoc,
626 notationName);
627 xmlAddDocEntity(ctxt->myDoc, name,
628 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
629 publicId, systemId, notationName);
630}
631
632/**
633 * setDocumentLocator:
634 * @ctx: the user data (XML parser context)
635 * @loc: A SAX Locator
636 *
637 * Receive the document locator at startup, actually xmlDefaultSAXLocator
638 * Everything is available on the context, so this is useless in our case.
639 */
640void
641setDocumentLocator(void *ctx, xmlSAXLocatorPtr loc)
642{
643 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
644#ifdef DEBUG_SAX
645 xmlGenericError(xmlGenericErrorContext,
646 "SAX.setDocumentLocator()\n");
647#endif
648}
649
650/**
651 * startDocument:
652 * @ctx: the user data (XML parser context)
653 *
654 * called when the document start being processed.
655 */
656void
657startDocument(void *ctx)
658{
659 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
660 xmlDocPtr doc;
661
662#ifdef DEBUG_SAX
663 xmlGenericError(xmlGenericErrorContext,
664 "SAX.startDocument()\n");
665#endif
666 if (ctxt->html) {
667 if (ctxt->myDoc == NULL)
668#ifdef LIBXML_HTML_ENABLED
669 ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
670#else
671 xmlGenericError(xmlGenericErrorContext,
672 "libxml2 built without HTML support\n");
673#endif
674 } else {
675 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
676 if (doc != NULL) {
677 if (ctxt->encoding != NULL)
678 doc->encoding = xmlStrdup(ctxt->encoding);
679 else
680 doc->encoding = NULL;
681 doc->standalone = ctxt->standalone;
682 }
683 }
684 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
685 (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
686 ctxt->myDoc->URL = xmlStrdup((xmlChar *) ctxt->input->filename);
687 }
688}
689
690/**
691 * endDocument:
692 * @ctx: the user data (XML parser context)
693 *
694 * called when the document end has been detected.
695 */
696void
697endDocument(void *ctx)
698{
699 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
700#ifdef DEBUG_SAX
701 xmlGenericError(xmlGenericErrorContext,
702 "SAX.endDocument()\n");
703#endif
704 if (ctxt->validate && ctxt->wellFormed &&
705 ctxt->myDoc && ctxt->myDoc->intSubset)
706 ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
707
708 /*
709 * Grab the encoding if it was added on-the-fly
710 */
711 if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
712 (ctxt->myDoc->encoding == NULL)) {
713 ctxt->myDoc->encoding = ctxt->encoding;
714 ctxt->encoding = NULL;
715 }
716 if ((ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
717 (ctxt->myDoc->encoding == NULL)) {
718 ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
719 }
720 if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
721 (ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
722 ctxt->myDoc->charset = ctxt->charset;
723 }
724}
725
726/**
727 * attribute:
728 * @ctx: the user data (XML parser context)
729 * @fullname: The attribute name, including namespace prefix
730 * @value: The attribute value
731 *
732 * Handle an attribute that has been read by the parser.
733 * The default handling is to convert the attribute into an
734 * DOM subtree and past it in a new xmlAttr element added to
735 * the element.
736 */
737void
738attribute(void *ctx, const xmlChar *fullname, const xmlChar *value)
739{
740 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
741 xmlAttrPtr ret;
742 xmlChar *name;
743 xmlChar *ns;
744 xmlChar *nval;
745 xmlNsPtr namespace;
746
747/****************
748#ifdef DEBUG_SAX
749 xmlGenericError(xmlGenericErrorContext,
750 "SAX.attribute(%s, %s)\n", fullname, value);
751#endif
752 ****************/
753 /*
754 * Split the full name into a namespace prefix and the tag name
755 */
756 name = xmlSplitQName(ctxt, fullname, &ns);
757
758 /*
759 * Do the last stage of the attribute normalization
760 * Needed for HTML too:
761 * http://www.w3.org/TR/html4/types.html#h-6.2
762 */
763 nval = xmlValidNormalizeAttributeValue(ctxt->myDoc, ctxt->node,
764 fullname, value);
765 if (nval != NULL)
766 value = nval;
767
768 /*
769 * Check whether it's a namespace definition
770 */
771 if ((!ctxt->html) && (ns == NULL) &&
772 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
773 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
774 if (value[0] != 0) {
775 xmlURIPtr uri;
776
777 uri = xmlParseURI((const char *)value);
778 if (uri == NULL) {
779 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
780 ctxt->sax->warning(ctxt->userData,
781 "nmlns: %s not a valid URI\n", value);
782 } else {
783 if (uri->scheme == NULL) {
784 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
785 ctxt->sax->warning(ctxt->userData,
786 "nmlns: URI %s is not absolute\n", value);
787 }
788 xmlFreeURI(uri);
789 }
790 }
791
792 /* a default namespace definition */
793 xmlNewNs(ctxt->node, value, NULL);
794 if (name != NULL)
795 xmlFree(name);
796 if (nval != NULL)
797 xmlFree(nval);
798 return;
799 }
800 if ((!ctxt->html) &&
801 (ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
802 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
803 /*
804 * Validate also for namespace decls, they are attributes from
805 * an XML-1.0 perspective
806 TODO ... doesn't map well with current API
807 if (ctxt->validate && ctxt->wellFormed &&
808 ctxt->myDoc && ctxt->myDoc->intSubset)
809 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
810 ctxt->node, ret, value);
811 */
812 /* a standard namespace definition */
813 xmlNewNs(ctxt->node, value, name);
814 xmlFree(ns);
815 if (name != NULL)
816 xmlFree(name);
817 if (nval != NULL)
818 xmlFree(nval);
819 return;
820 }
821
822 if (ns != NULL)
823 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
824 else {
825 namespace = NULL;
826 }
827
828 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
829 ret = xmlNewNsProp(ctxt->node, namespace, name, NULL);
830
831 if (ret != NULL) {
832 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
833 xmlNodePtr tmp;
834
835 ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
836 tmp = ret->children;
837 while (tmp != NULL) {
838 tmp->parent = (xmlNodePtr) ret;
839 if (tmp->next == NULL)
840 ret->last = tmp;
841 tmp = tmp->next;
842 }
843 } else if (value != NULL) {
844 ret->children = xmlNewDocText(ctxt->myDoc, value);
845 ret->last = ret->children;
846 if (ret->children != NULL)
847 ret->children->parent = (xmlNodePtr) ret;
848 }
849 }
850
851 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
852 ctxt->myDoc && ctxt->myDoc->intSubset) {
853
854 /*
855 * If we don't substitute entities, the validation should be
856 * done on a value with replaced entities anyway.
857 */
858 if (!ctxt->replaceEntities) {
859 xmlChar *val;
860
861 ctxt->depth++;
862 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
863 0,0,0);
864 ctxt->depth--;
865 if (val == NULL)
866 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
867 ctxt->myDoc, ctxt->node, ret, value);
868 else {
869 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
870 ctxt->myDoc, ctxt->node, ret, val);
871 xmlFree(val);
872 }
873 } else {
874 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
875 ctxt->node, ret, value);
876 }
877 } else {
878 /*
879 * when validating, the ID registration is done at the attribute
880 * validation level. Otherwise we have to do specific handling here.
881 */
882 if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
883 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
884 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
885 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
886 }
887
888 if (nval != NULL)
889 xmlFree(nval);
890 if (name != NULL)
891 xmlFree(name);
892 if (ns != NULL)
893 xmlFree(ns);
894}
895
896/**
897 * startElement:
898 * @ctx: the user data (XML parser context)
899 * @fullname: The element name, including namespace prefix
900 * @atts: An array of name/value attributes pairs, NULL terminated
901 *
902 * called when an opening tag has been processed.
903 */
904void
905startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
906{
907 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
908 xmlNodePtr ret;
909 xmlNodePtr parent = ctxt->node;
910 xmlNsPtr ns;
911 xmlChar *name;
912 xmlChar *prefix;
913 const xmlChar *att;
914 const xmlChar *value;
915 int i;
916
917#ifdef DEBUG_SAX
918 xmlGenericError(xmlGenericErrorContext,
919 "SAX.startElement(%s)\n", fullname);
920#endif
921
922 /*
923 * First check on validity:
924 */
925 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
926 ((ctxt->myDoc->intSubset == NULL) ||
927 ((ctxt->myDoc->intSubset->notations == NULL) &&
928 (ctxt->myDoc->intSubset->elements == NULL) &&
929 (ctxt->myDoc->intSubset->attributes == NULL) &&
930 (ctxt->myDoc->intSubset->entities == NULL)))) {
931 if (ctxt->vctxt.error != NULL) {
932 ctxt->vctxt.error(ctxt->vctxt.userData,
933 "Validation failed: no DTD found !\n");
934 }
935 ctxt->validate = 0;
936 }
937
938
939 /*
940 * Split the full name into a namespace prefix and the tag name
941 */
942 name = xmlSplitQName(ctxt, fullname, &prefix);
943
944
945 /*
946 * Note : the namespace resolution is deferred until the end of the
947 * attributes parsing, since local namespace can be defined as
948 * an attribute at this level.
949 */
950 ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL);
951 if (ret == NULL) return;
952 if (ctxt->myDoc->children == NULL) {
953#ifdef DEBUG_SAX_TREE
954 xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
955#endif
956 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
957 } else if (parent == NULL) {
958 parent = ctxt->myDoc->children;
959 }
960 ctxt->nodemem = -1;
961
962 /*
963 * We are parsing a new node.
964 */
965#ifdef DEBUG_SAX_TREE
966 xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);
967#endif
968 nodePush(ctxt, ret);
969
970 /*
971 * Link the child element
972 */
973 if (parent != NULL) {
974 if (parent->type == XML_ELEMENT_NODE) {
975#ifdef DEBUG_SAX_TREE
976 xmlGenericError(xmlGenericErrorContext,
977 "adding child %s to %s\n", name, parent->name);
978#endif
979 xmlAddChild(parent, ret);
980 } else {
981#ifdef DEBUG_SAX_TREE
982 xmlGenericError(xmlGenericErrorContext,
983 "adding sibling %s to ", name);
984 xmlDebugDumpOneNode(stderr, parent, 0);
985#endif
986 xmlAddSibling(parent, ret);
987 }
988 }
989
990 /*
991 * process all the attributes whose name start with "xml"
992 */
993 if (atts != NULL) {
994 i = 0;
995 att = atts[i++];
996 value = atts[i++];
997 if (!ctxt->html) {
998 while ((att != NULL) && (value != NULL)) {
999 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l'))
1000 attribute(ctxt, att, value);
1001
1002 att = atts[i++];
1003 value = atts[i++];
1004 }
1005 }
1006 }
1007
1008 /*
1009 * Search the namespace, note that since the attributes have been
1010 * processed, the local namespaces are available.
1011 */
1012 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
1013 if ((ns == NULL) && (parent != NULL))
1014 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
1015 if ((prefix != NULL) && (ns == NULL)) {
1016 ns = xmlNewNs(ret, NULL, prefix);
1017 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1018 ctxt->sax->warning(ctxt->userData,
1019 "Namespace prefix %s is not defined\n", prefix);
1020 }
1021 xmlSetNs(ret, ns);
1022
1023 /*
1024 * process all the other attributes
1025 */
1026 if (atts != NULL) {
1027 i = 0;
1028 att = atts[i++];
1029 value = atts[i++];
1030 if (ctxt->html) {
1031 while (att != NULL) {
1032 attribute(ctxt, att, value);
1033 att = atts[i++];
1034 value = atts[i++];
1035 }
1036 } else {
1037 while ((att != NULL) && (value != NULL)) {
1038 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l'))
1039 attribute(ctxt, att, value);
1040
1041 /*
1042 * Next ones
1043 */
1044 att = atts[i++];
1045 value = atts[i++];
1046 }
1047 }
1048 }
1049
1050 /*
1051 * If it's the Document root, finish the Dtd validation and
1052 * check the document root element for validity
1053 */
1054 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
1055 ctxt->valid &= xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
1056 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
1057 ctxt->vctxt.finishDtd = 1;
1058 }
1059
1060 if (prefix != NULL)
1061 xmlFree(prefix);
1062 if (name != NULL)
1063 xmlFree(name);
1064
1065}
1066
1067/**
1068 * endElement:
1069 * @ctx: the user data (XML parser context)
1070 * @name: The element name
1071 *
1072 * called when the end of an element has been detected.
1073 */
1074void
1075endElement(void *ctx, const xmlChar *name)
1076{
1077 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1078 xmlParserNodeInfo node_info;
1079 xmlNodePtr cur = ctxt->node;
1080
1081#ifdef DEBUG_SAX
1082 if (name == NULL)
1083 xmlGenericError(xmlGenericErrorContext, "SAX.endElement(NULL)\n");
1084 else
1085 xmlGenericError(xmlGenericErrorContext, "SAX.endElement(%s)\n", name);
1086#endif
1087
1088 /* Capture end position and add node */
1089 if (cur != NULL && ctxt->record_info) {
1090 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
1091 node_info.end_line = ctxt->input->line;
1092 node_info.node = cur;
1093 xmlParserAddNodeInfo(ctxt, &node_info);
1094 }
1095 ctxt->nodemem = -1;
1096
1097 if (ctxt->validate && ctxt->wellFormed &&
1098 ctxt->myDoc && ctxt->myDoc->intSubset)
1099 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
1100 cur);
1101
1102
1103 /*
1104 * end of parsing of this node.
1105 */
1106#ifdef DEBUG_SAX_TREE
1107 xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);
1108#endif
1109 nodePop(ctxt);
1110}
1111
1112/**
1113 * reference:
1114 * @ctx: the user data (XML parser context)
1115 * @name: The entity name
1116 *
1117 * called when an entity reference is detected.
1118 */
1119void
1120reference(void *ctx, const xmlChar *name)
1121{
1122 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1123 xmlNodePtr ret;
1124
1125#ifdef DEBUG_SAX
1126 xmlGenericError(xmlGenericErrorContext,
1127 "SAX.reference(%s)\n", name);
1128#endif
1129 if (name[0] == '#')
1130 ret = xmlNewCharRef(ctxt->myDoc, name);
1131 else
1132 ret = xmlNewReference(ctxt->myDoc, name);
1133#ifdef DEBUG_SAX_TREE
1134 xmlGenericError(xmlGenericErrorContext,
1135 "add reference %s to %s \n", name, ctxt->node->name);
1136#endif
1137 xmlAddChild(ctxt->node, ret);
1138}
1139
1140/**
1141 * characters:
1142 * @ctx: the user data (XML parser context)
1143 * @ch: a xmlChar string
1144 * @len: the number of xmlChar
1145 *
1146 * receiving some chars from the parser.
1147 * Question: how much at a time ???
1148 */
1149void
1150characters(void *ctx, const xmlChar *ch, int len)
1151{
1152 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1153 xmlNodePtr lastChild;
1154
1155#ifdef DEBUG_SAX
1156 xmlGenericError(xmlGenericErrorContext,
1157 "SAX.characters(%.30s, %d)\n", ch, len);
1158#endif
1159 /*
1160 * Handle the data if any. If there is no child
1161 * add it as content, otherwise if the last child is text,
1162 * concatenate it, else create a new node of type text.
1163 */
1164
1165 if (ctxt->node == NULL) {
1166#ifdef DEBUG_SAX_TREE
1167 xmlGenericError(xmlGenericErrorContext,
1168 "add chars: ctxt->node == NULL !\n");
1169#endif
1170 return;
1171 }
1172 lastChild = xmlGetLastChild(ctxt->node);
1173#ifdef DEBUG_SAX_TREE
1174 xmlGenericError(xmlGenericErrorContext,
1175 "add chars to %s \n", ctxt->node->name);
1176#endif
1177
1178 /*
1179 * Here we needed an accelerator mechanism in case of very large
1180 * elements. Use an attribute in the structure !!!
1181 */
1182 if (lastChild == NULL) {
1183 /* first node, first time */
1184 xmlNodeAddContentLen(ctxt->node, ch, len);
1185#ifndef XML_USE_BUFFER_CONTENT
1186 if (ctxt->node->children != NULL) {
1187 ctxt->nodelen = len;
1188 ctxt->nodemem = len + 1;
1189 }
1190#endif
1191 } else {
1192 if ((xmlNodeIsText(lastChild)) && (ctxt->nodemem != 0)) {
1193#ifndef XML_USE_BUFFER_CONTENT
1194 /*
1195 * The whole point of maintaining nodelen and nodemem,
1196 * xmlTextConcat is too costly, i.e. compute lenght,
1197 * reallocate a new buffer, move data, append ch. Here
1198 * We try to minimaze realloc() uses and avoid copying
1199 * and recomputing lenght over and over.
1200 */
1201 if (ctxt->nodelen + len >= ctxt->nodemem) {
1202 xmlChar *newbuf;
1203 int size;
1204
1205 size = ctxt->nodemem + len;
1206 size *= 2;
1207 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
1208 if (newbuf == NULL) {
1209 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1210 ctxt->sax->error(ctxt->userData,
1211 "SAX.characters(): out of memory\n");
1212 return;
1213 }
1214 ctxt->nodemem = size;
1215 lastChild->content = newbuf;
1216 }
1217 memcpy(&lastChild->content[ctxt->nodelen], ch, len);
1218 ctxt->nodelen += len;
1219 lastChild->content[ctxt->nodelen] = 0;
1220#else
1221 xmlTextConcat(lastChild, ch, len);
1222#endif
1223 } else {
1224 /* Mixed content, first time */
1225 lastChild = xmlNewTextLen(ch, len);
1226 xmlAddChild(ctxt->node, lastChild);
1227#ifndef XML_USE_BUFFER_CONTENT
1228 if (ctxt->node->children != NULL) {
1229 ctxt->nodelen = len;
1230 ctxt->nodemem = len + 1;
1231 }
1232#endif
1233 }
1234 }
1235}
1236
1237/**
1238 * ignorableWhitespace:
1239 * @ctx: the user data (XML parser context)
1240 * @ch: a xmlChar string
1241 * @len: the number of xmlChar
1242 *
1243 * receiving some ignorable whitespaces from the parser.
1244 * Question: how much at a time ???
1245 */
1246void
1247ignorableWhitespace(void *ctx, const xmlChar *ch, int len)
1248{
1249 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
1250#ifdef DEBUG_SAX
1251 xmlGenericError(xmlGenericErrorContext,
1252 "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len);
1253#endif
1254}
1255
1256/**
1257 * processingInstruction:
1258 * @ctx: the user data (XML parser context)
1259 * @target: the target name
1260 * @data: the PI data's
1261 *
1262 * A processing instruction has been parsed.
1263 */
1264void
1265processingInstruction(void *ctx, const xmlChar *target,
1266 const xmlChar *data)
1267{
1268 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1269 xmlNodePtr ret;
1270 xmlNodePtr parent = ctxt->node;
1271
1272#ifdef DEBUG_SAX
1273 xmlGenericError(xmlGenericErrorContext,
1274 "SAX.processingInstruction(%s, %s)\n", target, data);
1275#endif
1276
1277 ret = xmlNewPI(target, data);
1278 if (ret == NULL) return;
1279 parent = ctxt->node;
1280
1281 if (ctxt->inSubset == 1) {
1282 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1283 return;
1284 } else if (ctxt->inSubset == 2) {
1285 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1286 return;
1287 }
1288 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
1289#ifdef DEBUG_SAX_TREE
1290 xmlGenericError(xmlGenericErrorContext,
1291 "Setting PI %s as root\n", target);
1292#endif
1293 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1294 return;
1295 }
1296 if (parent->type == XML_ELEMENT_NODE) {
1297#ifdef DEBUG_SAX_TREE
1298 xmlGenericError(xmlGenericErrorContext,
1299 "adding PI %s child to %s\n", target, parent->name);
1300#endif
1301 xmlAddChild(parent, ret);
1302 } else {
1303#ifdef DEBUG_SAX_TREE
1304 xmlGenericError(xmlGenericErrorContext,
1305 "adding PI %s sibling to ", target);
1306 xmlDebugDumpOneNode(stderr, parent, 0);
1307#endif
1308 xmlAddSibling(parent, ret);
1309 }
1310}
1311
1312/**
1313 * globalNamespace:
1314 * @ctx: the user data (XML parser context)
1315 * @href: the namespace associated URN
1316 * @prefix: the namespace prefix
1317 *
1318 * An old global namespace has been parsed.
1319 */
1320void
1321globalNamespace(void *ctx, const xmlChar *href, const xmlChar *prefix)
1322{
1323 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1324#ifdef DEBUG_SAX
1325 xmlGenericError(xmlGenericErrorContext,
1326 "SAX.globalNamespace(%s, %s)\n", href, prefix);
1327#endif
1328 xmlNewGlobalNs(ctxt->myDoc, href, prefix);
1329}
1330
1331/**
1332 * setNamespace:
1333 * @ctx: the user data (XML parser context)
1334 * @name: the namespace prefix
1335 *
1336 * Set the current element namespace.
1337 */
1338
1339void
1340setNamespace(void *ctx, const xmlChar *name)
1341{
1342 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1343 xmlNsPtr ns;
1344 xmlNodePtr parent;
1345
1346#ifdef DEBUG_SAX
1347 xmlGenericError(xmlGenericErrorContext, "SAX.setNamespace(%s)\n", name);
1348#endif
1349 ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name);
1350 if (ns == NULL) { /* ctxt->node may not have a parent yet ! */
1351 if (ctxt->nodeNr >= 2) {
1352 parent = ctxt->nodeTab[ctxt->nodeNr - 2];
1353 if (parent != NULL)
1354 ns = xmlSearchNs(ctxt->myDoc, parent, name);
1355 }
1356 }
1357 xmlSetNs(ctxt->node, ns);
1358}
1359
1360/**
1361 * getNamespace:
1362 * @ctx: the user data (XML parser context)
1363 *
1364 * Get the current element namespace.
1365 *
1366 * Returns the xmlNsPtr or NULL if none
1367 */
1368
1369xmlNsPtr
1370getNamespace(void *ctx)
1371{
1372 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1373 xmlNsPtr ret;
1374
1375#ifdef DEBUG_SAX
1376 xmlGenericError(xmlGenericErrorContext, "SAX.getNamespace()\n");
1377#endif
1378 ret = ctxt->node->ns;
1379 return(ret);
1380}
1381
1382/**
1383 * checkNamespace:
1384 * @ctx: the user data (XML parser context)
1385 * @namespace: the namespace to check against
1386 *
1387 * Check that the current element namespace is the same as the
1388 * one read upon parsing.
1389 *
1390 * Returns 1 if true 0 otherwise
1391 */
1392
1393int
1394checkNamespace(void *ctx, xmlChar *namespace)
1395{
1396 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1397 xmlNodePtr cur = ctxt->node;
1398
1399#ifdef DEBUG_SAX
1400 xmlGenericError(xmlGenericErrorContext,
1401 "SAX.checkNamespace(%s)\n", namespace);
1402#endif
1403
1404 /*
1405 * Check that the Name in the ETag is the same as in the STag.
1406 */
1407 if (namespace == NULL) {
1408 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1409 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1410 ctxt->sax->error(ctxt,
1411 "End tags for %s don't hold the namespace %s\n",
1412 cur->name, cur->ns->prefix);
1413 ctxt->wellFormed = 0;
1414 }
1415 } else {
1416 if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) {
1417 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1418 ctxt->sax->error(ctxt,
1419 "End tags %s holds a prefix %s not used by the open tag\n",
1420 cur->name, namespace);
1421 ctxt->wellFormed = 0;
1422 } else if (!xmlStrEqual(namespace, cur->ns->prefix)) {
1423 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1424 ctxt->sax->error(ctxt,
1425 "Start and End tags for %s don't use the same namespaces: %s and %s\n",
1426 cur->name, cur->ns->prefix, namespace);
1427 ctxt->wellFormed = 0;
1428 } else
1429 return(1);
1430 }
1431 return(0);
1432}
1433
1434/**
1435 * namespaceDecl:
1436 * @ctx: the user data (XML parser context)
1437 * @href: the namespace associated URN
1438 * @prefix: the namespace prefix
1439 *
1440 * A namespace has been parsed.
1441 */
1442void
1443namespaceDecl(void *ctx, const xmlChar *href, const xmlChar *prefix)
1444{
1445 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1446#ifdef DEBUG_SAX
1447 if (prefix == NULL)
1448 xmlGenericError(xmlGenericErrorContext,
1449 "SAX.namespaceDecl(%s, NULL)\n", href);
1450 else
1451 xmlGenericError(xmlGenericErrorContext,
1452 "SAX.namespaceDecl(%s, %s)\n", href, prefix);
1453#endif
1454 xmlNewNs(ctxt->node, href, prefix);
1455}
1456
1457/**
1458 * comment:
1459 * @ctx: the user data (XML parser context)
1460 * @value: the comment content
1461 *
1462 * A comment has been parsed.
1463 */
1464void
1465comment(void *ctx, const xmlChar *value)
1466{
1467 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1468 xmlNodePtr ret;
1469 xmlNodePtr parent = ctxt->node;
1470
1471#ifdef DEBUG_SAX
1472 xmlGenericError(xmlGenericErrorContext, "SAX.comment(%s)\n", value);
1473#endif
1474 ret = xmlNewDocComment(ctxt->myDoc, value);
1475 if (ret == NULL) return;
1476
1477 if (ctxt->inSubset == 1) {
1478 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1479 return;
1480 } else if (ctxt->inSubset == 2) {
1481 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1482 return;
1483 }
1484 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
1485#ifdef DEBUG_SAX_TREE
1486 xmlGenericError(xmlGenericErrorContext,
1487 "Setting comment as root\n");
1488#endif
1489 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1490 return;
1491 }
1492 if (parent->type == XML_ELEMENT_NODE) {
1493#ifdef DEBUG_SAX_TREE
1494 xmlGenericError(xmlGenericErrorContext,
1495 "adding comment child to %s\n", parent->name);
1496#endif
1497 xmlAddChild(parent, ret);
1498 } else {
1499#ifdef DEBUG_SAX_TREE
1500 xmlGenericError(xmlGenericErrorContext,
1501 "adding comment sibling to ");
1502 xmlDebugDumpOneNode(stderr, parent, 0);
1503#endif
1504 xmlAddSibling(parent, ret);
1505 }
1506}
1507
1508/**
1509 * cdataBlock:
1510 * @ctx: the user data (XML parser context)
1511 * @value: The pcdata content
1512 * @len: the block length
1513 *
1514 * called when a pcdata block has been parsed
1515 */
1516void
1517cdataBlock(void *ctx, const xmlChar *value, int len)
1518{
1519 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1520 xmlNodePtr ret, lastChild;
1521
1522#ifdef DEBUG_SAX
1523 xmlGenericError(xmlGenericErrorContext,
1524 "SAX.pcdata(%.10s, %d)\n", value, len);
1525#endif
1526 lastChild = xmlGetLastChild(ctxt->node);
1527#ifdef DEBUG_SAX_TREE
1528 xmlGenericError(xmlGenericErrorContext,
1529 "add chars to %s \n", ctxt->node->name);
1530#endif
1531 if ((lastChild != NULL) &&
1532 (lastChild->type == XML_CDATA_SECTION_NODE)) {
1533 xmlTextConcat(lastChild, value, len);
1534 } else {
1535 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
1536 xmlAddChild(ctxt->node, ret);
1537 }
1538}
1539
1540/*
1541 * Default handler for XML, builds the DOM tree
1542 */
1543xmlSAXHandler xmlDefaultSAXHandler = {
1544 internalSubset,
1545 isStandalone,
1546 hasInternalSubset,
1547 hasExternalSubset,
1548 resolveEntity,
1549 getEntity,
1550 entityDecl,
1551 notationDecl,
1552 attributeDecl,
1553 elementDecl,
1554 unparsedEntityDecl,
1555 setDocumentLocator,
1556 startDocument,
1557 endDocument,
1558 startElement,
1559 endElement,
1560 reference,
1561 characters,
1562 ignorableWhitespace,
1563 processingInstruction,
1564 comment,
1565 xmlParserWarning,
1566 xmlParserError,
1567 xmlParserError,
1568 getParameterEntity,
1569 cdataBlock,
1570 externalSubset,
1571};
1572
1573/**
1574 * xmlDefaultSAXHandlerInit:
1575 *
1576 * Initialize the default SAX handler
1577 */
1578void
1579xmlDefaultSAXHandlerInit(void)
1580{
1581 xmlDefaultSAXHandler.internalSubset = internalSubset;
1582 xmlDefaultSAXHandler.externalSubset = externalSubset;
1583 xmlDefaultSAXHandler.isStandalone = isStandalone;
1584 xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
1585 xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
1586 xmlDefaultSAXHandler.resolveEntity = resolveEntity;
1587 xmlDefaultSAXHandler.getEntity = getEntity;
1588 xmlDefaultSAXHandler.getParameterEntity = getParameterEntity;
1589 xmlDefaultSAXHandler.entityDecl = entityDecl;
1590 xmlDefaultSAXHandler.attributeDecl = attributeDecl;
1591 xmlDefaultSAXHandler.elementDecl = elementDecl;
1592 xmlDefaultSAXHandler.notationDecl = notationDecl;
1593 xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
1594 xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1595 xmlDefaultSAXHandler.startDocument = startDocument;
1596 xmlDefaultSAXHandler.endDocument = endDocument;
1597 xmlDefaultSAXHandler.startElement = startElement;
1598 xmlDefaultSAXHandler.endElement = endElement;
1599 xmlDefaultSAXHandler.reference = reference;
1600 xmlDefaultSAXHandler.characters = characters;
1601 xmlDefaultSAXHandler.cdataBlock = cdataBlock;
1602 xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1603 xmlDefaultSAXHandler.processingInstruction = processingInstruction;
1604 xmlDefaultSAXHandler.comment = comment;
1605 if (xmlGetWarningsDefaultValue == 0)
1606 xmlDefaultSAXHandler.warning = NULL;
1607 else
1608 xmlDefaultSAXHandler.warning = xmlParserWarning;
1609 xmlDefaultSAXHandler.error = xmlParserError;
1610 xmlDefaultSAXHandler.fatalError = xmlParserError;
1611}
1612
1613/*
1614 * Default handler for HTML, builds the DOM tree
1615 */
1616xmlSAXHandler htmlDefaultSAXHandler = {
1617 internalSubset,
1618 NULL,
1619 NULL,
1620 NULL,
1621 NULL,
1622 getEntity,
1623 NULL,
1624 NULL,
1625 NULL,
1626 NULL,
1627 NULL,
1628 setDocumentLocator,
1629 startDocument,
1630 endDocument,
1631 startElement,
1632 endElement,
1633 NULL,
1634 characters,
1635 ignorableWhitespace,
1636 NULL,
1637 comment,
1638 xmlParserWarning,
1639 xmlParserError,
1640 xmlParserError,
1641 getParameterEntity,
1642 cdataBlock,
1643 NULL,
1644};
1645
1646/**
1647 * htmlDefaultSAXHandlerInit:
1648 *
1649 * Initialize the default SAX handler
1650 */
1651void
1652htmlDefaultSAXHandlerInit(void)
1653{
1654 htmlDefaultSAXHandler.internalSubset = internalSubset;
1655 htmlDefaultSAXHandler.externalSubset = NULL;
1656 htmlDefaultSAXHandler.isStandalone = NULL;
1657 htmlDefaultSAXHandler.hasInternalSubset = NULL;
1658 htmlDefaultSAXHandler.hasExternalSubset = NULL;
1659 htmlDefaultSAXHandler.resolveEntity = NULL;
1660 htmlDefaultSAXHandler.getEntity = getEntity;
1661 htmlDefaultSAXHandler.getParameterEntity = NULL;
1662 htmlDefaultSAXHandler.entityDecl = NULL;
1663 htmlDefaultSAXHandler.attributeDecl = NULL;
1664 htmlDefaultSAXHandler.elementDecl = NULL;
1665 htmlDefaultSAXHandler.notationDecl = NULL;
1666 htmlDefaultSAXHandler.unparsedEntityDecl = NULL;
1667 htmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1668 htmlDefaultSAXHandler.startDocument = startDocument;
1669 htmlDefaultSAXHandler.endDocument = endDocument;
1670 htmlDefaultSAXHandler.startElement = startElement;
1671 htmlDefaultSAXHandler.endElement = endElement;
1672 htmlDefaultSAXHandler.reference = NULL;
1673 htmlDefaultSAXHandler.characters = characters;
1674 htmlDefaultSAXHandler.cdataBlock = cdataBlock;
1675 htmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1676 htmlDefaultSAXHandler.processingInstruction = NULL;
1677 htmlDefaultSAXHandler.comment = comment;
1678 htmlDefaultSAXHandler.warning = xmlParserWarning;
1679 htmlDefaultSAXHandler.error = xmlParserError;
1680 htmlDefaultSAXHandler.fatalError = xmlParserError;
1681}
1682
1683/*
1684 * Default handler for HTML, builds the DOM tree
1685 */
1686xmlSAXHandler sgmlDefaultSAXHandler = {
1687 internalSubset,
1688 NULL,
1689 NULL,
1690 NULL,
1691 NULL,
1692 getEntity,
1693 NULL,
1694 NULL,
1695 NULL,
1696 NULL,
1697 NULL,
1698 setDocumentLocator,
1699 startDocument,
1700 endDocument,
1701 startElement,
1702 endElement,
1703 NULL,
1704 characters,
1705 ignorableWhitespace,
1706 NULL,
1707 comment,
1708 xmlParserWarning,
1709 xmlParserError,
1710 xmlParserError,
1711 getParameterEntity,
1712 NULL,
1713 NULL,
1714};
1715
1716/**
1717 * sgmlDefaultSAXHandlerInit:
1718 *
1719 * Initialize the default SAX handler
1720 */
1721void
1722sgmlDefaultSAXHandlerInit(void)
1723{
1724 sgmlDefaultSAXHandler.internalSubset = internalSubset;
1725 sgmlDefaultSAXHandler.externalSubset = NULL;
1726 sgmlDefaultSAXHandler.isStandalone = NULL;
1727 sgmlDefaultSAXHandler.hasInternalSubset = NULL;
1728 sgmlDefaultSAXHandler.hasExternalSubset = NULL;
1729 sgmlDefaultSAXHandler.resolveEntity = NULL;
1730 sgmlDefaultSAXHandler.getEntity = getEntity;
1731 sgmlDefaultSAXHandler.getParameterEntity = NULL;
1732 sgmlDefaultSAXHandler.entityDecl = NULL;
1733 sgmlDefaultSAXHandler.attributeDecl = NULL;
1734 sgmlDefaultSAXHandler.elementDecl = NULL;
1735 sgmlDefaultSAXHandler.notationDecl = NULL;
1736 sgmlDefaultSAXHandler.unparsedEntityDecl = NULL;
1737 sgmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1738 sgmlDefaultSAXHandler.startDocument = startDocument;
1739 sgmlDefaultSAXHandler.endDocument = endDocument;
1740 sgmlDefaultSAXHandler.startElement = startElement;
1741 sgmlDefaultSAXHandler.endElement = endElement;
1742 sgmlDefaultSAXHandler.reference = NULL;
1743 sgmlDefaultSAXHandler.characters = characters;
1744 sgmlDefaultSAXHandler.cdataBlock = NULL;
1745 sgmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1746 sgmlDefaultSAXHandler.processingInstruction = NULL;
1747 sgmlDefaultSAXHandler.comment = comment;
1748 sgmlDefaultSAXHandler.warning = xmlParserWarning;
1749 sgmlDefaultSAXHandler.error = xmlParserError;
1750 sgmlDefaultSAXHandler.fatalError = xmlParserError;
1751}