blob: 9d6218fa3aeaf9ef9dbf12e819c8368db18d713b [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)
Daniel Veillard25239c12001-03-14 13:56:48 +0000587 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, name,
Owen Taylor3473f882001-02-23 17:55:21 +0000588 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 &&
Daniel Veillarde020c3a2001-03-21 18:06:15 +0000624 ctxt->myDoc && ctxt->myDoc->extSubset)
Owen Taylor3473f882001-02-23 17:55:21 +0000625 ctxt->valid &= xmlValidateNotationUse(&ctxt->vctxt, ctxt->myDoc,
626 notationName);
Daniel Veillarde020c3a2001-03-21 18:06:15 +0000627 if (ctxt->inSubset == 1)
628 xmlAddDocEntity(ctxt->myDoc, name,
629 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
630 publicId, systemId, notationName);
631 else if (ctxt->inSubset == 2)
632 xmlAddDtdEntity(ctxt->myDoc, name,
633 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
634 publicId, systemId, notationName);
635 else {
636 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
637 ctxt->sax->error(ctxt,
638 "SAX.unparsedEntityDecl(%s) called while not in subset\n", name);
639 }
Owen Taylor3473f882001-02-23 17:55:21 +0000640}
641
642/**
643 * setDocumentLocator:
644 * @ctx: the user data (XML parser context)
645 * @loc: A SAX Locator
646 *
647 * Receive the document locator at startup, actually xmlDefaultSAXLocator
648 * Everything is available on the context, so this is useless in our case.
649 */
650void
651setDocumentLocator(void *ctx, xmlSAXLocatorPtr loc)
652{
653 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
654#ifdef DEBUG_SAX
655 xmlGenericError(xmlGenericErrorContext,
656 "SAX.setDocumentLocator()\n");
657#endif
658}
659
660/**
661 * startDocument:
662 * @ctx: the user data (XML parser context)
663 *
664 * called when the document start being processed.
665 */
666void
667startDocument(void *ctx)
668{
669 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
670 xmlDocPtr doc;
671
672#ifdef DEBUG_SAX
673 xmlGenericError(xmlGenericErrorContext,
674 "SAX.startDocument()\n");
675#endif
676 if (ctxt->html) {
677 if (ctxt->myDoc == NULL)
678#ifdef LIBXML_HTML_ENABLED
679 ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
680#else
681 xmlGenericError(xmlGenericErrorContext,
682 "libxml2 built without HTML support\n");
683#endif
684 } else {
685 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
686 if (doc != NULL) {
687 if (ctxt->encoding != NULL)
688 doc->encoding = xmlStrdup(ctxt->encoding);
689 else
690 doc->encoding = NULL;
691 doc->standalone = ctxt->standalone;
692 }
693 }
694 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
695 (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
696 ctxt->myDoc->URL = xmlStrdup((xmlChar *) ctxt->input->filename);
697 }
698}
699
700/**
701 * endDocument:
702 * @ctx: the user data (XML parser context)
703 *
704 * called when the document end has been detected.
705 */
706void
707endDocument(void *ctx)
708{
709 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
710#ifdef DEBUG_SAX
711 xmlGenericError(xmlGenericErrorContext,
712 "SAX.endDocument()\n");
713#endif
714 if (ctxt->validate && ctxt->wellFormed &&
715 ctxt->myDoc && ctxt->myDoc->intSubset)
716 ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
717
718 /*
719 * Grab the encoding if it was added on-the-fly
720 */
721 if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
722 (ctxt->myDoc->encoding == NULL)) {
723 ctxt->myDoc->encoding = ctxt->encoding;
724 ctxt->encoding = NULL;
725 }
726 if ((ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
727 (ctxt->myDoc->encoding == NULL)) {
728 ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
729 }
730 if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
731 (ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
732 ctxt->myDoc->charset = ctxt->charset;
733 }
734}
735
736/**
737 * attribute:
738 * @ctx: the user data (XML parser context)
739 * @fullname: The attribute name, including namespace prefix
740 * @value: The attribute value
741 *
742 * Handle an attribute that has been read by the parser.
743 * The default handling is to convert the attribute into an
744 * DOM subtree and past it in a new xmlAttr element added to
745 * the element.
746 */
747void
748attribute(void *ctx, const xmlChar *fullname, const xmlChar *value)
749{
750 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
751 xmlAttrPtr ret;
752 xmlChar *name;
753 xmlChar *ns;
754 xmlChar *nval;
755 xmlNsPtr namespace;
756
757/****************
758#ifdef DEBUG_SAX
759 xmlGenericError(xmlGenericErrorContext,
760 "SAX.attribute(%s, %s)\n", fullname, value);
761#endif
762 ****************/
763 /*
764 * Split the full name into a namespace prefix and the tag name
765 */
766 name = xmlSplitQName(ctxt, fullname, &ns);
767
768 /*
769 * Do the last stage of the attribute normalization
770 * Needed for HTML too:
771 * http://www.w3.org/TR/html4/types.html#h-6.2
772 */
773 nval = xmlValidNormalizeAttributeValue(ctxt->myDoc, ctxt->node,
774 fullname, value);
775 if (nval != NULL)
776 value = nval;
777
778 /*
779 * Check whether it's a namespace definition
780 */
781 if ((!ctxt->html) && (ns == NULL) &&
782 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
783 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
784 if (value[0] != 0) {
785 xmlURIPtr uri;
786
787 uri = xmlParseURI((const char *)value);
788 if (uri == NULL) {
789 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
790 ctxt->sax->warning(ctxt->userData,
791 "nmlns: %s not a valid URI\n", value);
792 } else {
793 if (uri->scheme == NULL) {
794 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
795 ctxt->sax->warning(ctxt->userData,
796 "nmlns: URI %s is not absolute\n", value);
797 }
798 xmlFreeURI(uri);
799 }
800 }
801
802 /* a default namespace definition */
803 xmlNewNs(ctxt->node, value, NULL);
804 if (name != NULL)
805 xmlFree(name);
806 if (nval != NULL)
807 xmlFree(nval);
808 return;
809 }
810 if ((!ctxt->html) &&
811 (ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
812 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
813 /*
814 * Validate also for namespace decls, they are attributes from
815 * an XML-1.0 perspective
816 TODO ... doesn't map well with current API
817 if (ctxt->validate && ctxt->wellFormed &&
818 ctxt->myDoc && ctxt->myDoc->intSubset)
819 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
820 ctxt->node, ret, value);
821 */
822 /* a standard namespace definition */
823 xmlNewNs(ctxt->node, value, name);
824 xmlFree(ns);
825 if (name != NULL)
826 xmlFree(name);
827 if (nval != NULL)
828 xmlFree(nval);
829 return;
830 }
831
832 if (ns != NULL)
833 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
834 else {
835 namespace = NULL;
836 }
837
838 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
839 ret = xmlNewNsProp(ctxt->node, namespace, name, NULL);
840
841 if (ret != NULL) {
842 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
843 xmlNodePtr tmp;
844
845 ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
846 tmp = ret->children;
847 while (tmp != NULL) {
848 tmp->parent = (xmlNodePtr) ret;
849 if (tmp->next == NULL)
850 ret->last = tmp;
851 tmp = tmp->next;
852 }
853 } else if (value != NULL) {
854 ret->children = xmlNewDocText(ctxt->myDoc, value);
855 ret->last = ret->children;
856 if (ret->children != NULL)
857 ret->children->parent = (xmlNodePtr) ret;
858 }
859 }
860
861 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
862 ctxt->myDoc && ctxt->myDoc->intSubset) {
863
864 /*
865 * If we don't substitute entities, the validation should be
866 * done on a value with replaced entities anyway.
867 */
868 if (!ctxt->replaceEntities) {
869 xmlChar *val;
870
871 ctxt->depth++;
872 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
873 0,0,0);
874 ctxt->depth--;
875 if (val == NULL)
876 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
877 ctxt->myDoc, ctxt->node, ret, value);
878 else {
879 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
880 ctxt->myDoc, ctxt->node, ret, val);
881 xmlFree(val);
882 }
883 } else {
884 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
885 ctxt->node, ret, value);
886 }
887 } else {
888 /*
889 * when validating, the ID registration is done at the attribute
890 * validation level. Otherwise we have to do specific handling here.
891 */
892 if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
893 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
894 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
895 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
896 }
897
898 if (nval != NULL)
899 xmlFree(nval);
900 if (name != NULL)
901 xmlFree(name);
902 if (ns != NULL)
903 xmlFree(ns);
904}
905
906/**
907 * startElement:
908 * @ctx: the user data (XML parser context)
909 * @fullname: The element name, including namespace prefix
910 * @atts: An array of name/value attributes pairs, NULL terminated
911 *
912 * called when an opening tag has been processed.
913 */
914void
915startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
916{
917 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
918 xmlNodePtr ret;
919 xmlNodePtr parent = ctxt->node;
920 xmlNsPtr ns;
921 xmlChar *name;
922 xmlChar *prefix;
923 const xmlChar *att;
924 const xmlChar *value;
925 int i;
926
927#ifdef DEBUG_SAX
928 xmlGenericError(xmlGenericErrorContext,
929 "SAX.startElement(%s)\n", fullname);
930#endif
931
932 /*
933 * First check on validity:
934 */
935 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
936 ((ctxt->myDoc->intSubset == NULL) ||
937 ((ctxt->myDoc->intSubset->notations == NULL) &&
938 (ctxt->myDoc->intSubset->elements == NULL) &&
939 (ctxt->myDoc->intSubset->attributes == NULL) &&
940 (ctxt->myDoc->intSubset->entities == NULL)))) {
941 if (ctxt->vctxt.error != NULL) {
942 ctxt->vctxt.error(ctxt->vctxt.userData,
943 "Validation failed: no DTD found !\n");
944 }
945 ctxt->validate = 0;
946 }
947
948
949 /*
950 * Split the full name into a namespace prefix and the tag name
951 */
952 name = xmlSplitQName(ctxt, fullname, &prefix);
953
954
955 /*
956 * Note : the namespace resolution is deferred until the end of the
957 * attributes parsing, since local namespace can be defined as
958 * an attribute at this level.
959 */
960 ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL);
961 if (ret == NULL) return;
962 if (ctxt->myDoc->children == NULL) {
963#ifdef DEBUG_SAX_TREE
964 xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
965#endif
966 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
967 } else if (parent == NULL) {
968 parent = ctxt->myDoc->children;
969 }
970 ctxt->nodemem = -1;
971
972 /*
973 * We are parsing a new node.
974 */
975#ifdef DEBUG_SAX_TREE
976 xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);
977#endif
978 nodePush(ctxt, ret);
979
980 /*
981 * Link the child element
982 */
983 if (parent != NULL) {
984 if (parent->type == XML_ELEMENT_NODE) {
985#ifdef DEBUG_SAX_TREE
986 xmlGenericError(xmlGenericErrorContext,
987 "adding child %s to %s\n", name, parent->name);
988#endif
989 xmlAddChild(parent, ret);
990 } else {
991#ifdef DEBUG_SAX_TREE
992 xmlGenericError(xmlGenericErrorContext,
993 "adding sibling %s to ", name);
994 xmlDebugDumpOneNode(stderr, parent, 0);
995#endif
996 xmlAddSibling(parent, ret);
997 }
998 }
999
1000 /*
1001 * process all the attributes whose name start with "xml"
1002 */
1003 if (atts != NULL) {
1004 i = 0;
1005 att = atts[i++];
1006 value = atts[i++];
1007 if (!ctxt->html) {
1008 while ((att != NULL) && (value != NULL)) {
1009 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l'))
1010 attribute(ctxt, att, value);
1011
1012 att = atts[i++];
1013 value = atts[i++];
1014 }
1015 }
1016 }
1017
1018 /*
1019 * Search the namespace, note that since the attributes have been
1020 * processed, the local namespaces are available.
1021 */
1022 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
1023 if ((ns == NULL) && (parent != NULL))
1024 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
1025 if ((prefix != NULL) && (ns == NULL)) {
1026 ns = xmlNewNs(ret, NULL, prefix);
1027 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1028 ctxt->sax->warning(ctxt->userData,
1029 "Namespace prefix %s is not defined\n", prefix);
1030 }
1031 xmlSetNs(ret, ns);
1032
1033 /*
1034 * process all the other attributes
1035 */
1036 if (atts != NULL) {
1037 i = 0;
1038 att = atts[i++];
1039 value = atts[i++];
1040 if (ctxt->html) {
1041 while (att != NULL) {
1042 attribute(ctxt, att, value);
1043 att = atts[i++];
1044 value = atts[i++];
1045 }
1046 } else {
1047 while ((att != NULL) && (value != NULL)) {
1048 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l'))
1049 attribute(ctxt, att, value);
1050
1051 /*
1052 * Next ones
1053 */
1054 att = atts[i++];
1055 value = atts[i++];
1056 }
1057 }
1058 }
1059
1060 /*
1061 * If it's the Document root, finish the Dtd validation and
1062 * check the document root element for validity
1063 */
1064 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
1065 ctxt->valid &= xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
1066 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
1067 ctxt->vctxt.finishDtd = 1;
1068 }
1069
1070 if (prefix != NULL)
1071 xmlFree(prefix);
1072 if (name != NULL)
1073 xmlFree(name);
1074
1075}
1076
1077/**
1078 * endElement:
1079 * @ctx: the user data (XML parser context)
1080 * @name: The element name
1081 *
1082 * called when the end of an element has been detected.
1083 */
1084void
1085endElement(void *ctx, const xmlChar *name)
1086{
1087 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1088 xmlParserNodeInfo node_info;
1089 xmlNodePtr cur = ctxt->node;
1090
1091#ifdef DEBUG_SAX
1092 if (name == NULL)
1093 xmlGenericError(xmlGenericErrorContext, "SAX.endElement(NULL)\n");
1094 else
1095 xmlGenericError(xmlGenericErrorContext, "SAX.endElement(%s)\n", name);
1096#endif
1097
1098 /* Capture end position and add node */
1099 if (cur != NULL && ctxt->record_info) {
1100 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
1101 node_info.end_line = ctxt->input->line;
1102 node_info.node = cur;
1103 xmlParserAddNodeInfo(ctxt, &node_info);
1104 }
1105 ctxt->nodemem = -1;
1106
1107 if (ctxt->validate && ctxt->wellFormed &&
1108 ctxt->myDoc && ctxt->myDoc->intSubset)
1109 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
1110 cur);
1111
1112
1113 /*
1114 * end of parsing of this node.
1115 */
1116#ifdef DEBUG_SAX_TREE
1117 xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);
1118#endif
1119 nodePop(ctxt);
1120}
1121
1122/**
1123 * reference:
1124 * @ctx: the user data (XML parser context)
1125 * @name: The entity name
1126 *
1127 * called when an entity reference is detected.
1128 */
1129void
1130reference(void *ctx, const xmlChar *name)
1131{
1132 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1133 xmlNodePtr ret;
1134
1135#ifdef DEBUG_SAX
1136 xmlGenericError(xmlGenericErrorContext,
1137 "SAX.reference(%s)\n", name);
1138#endif
1139 if (name[0] == '#')
1140 ret = xmlNewCharRef(ctxt->myDoc, name);
1141 else
1142 ret = xmlNewReference(ctxt->myDoc, name);
1143#ifdef DEBUG_SAX_TREE
1144 xmlGenericError(xmlGenericErrorContext,
1145 "add reference %s to %s \n", name, ctxt->node->name);
1146#endif
1147 xmlAddChild(ctxt->node, ret);
1148}
1149
1150/**
1151 * characters:
1152 * @ctx: the user data (XML parser context)
1153 * @ch: a xmlChar string
1154 * @len: the number of xmlChar
1155 *
1156 * receiving some chars from the parser.
1157 * Question: how much at a time ???
1158 */
1159void
1160characters(void *ctx, const xmlChar *ch, int len)
1161{
1162 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1163 xmlNodePtr lastChild;
1164
1165#ifdef DEBUG_SAX
1166 xmlGenericError(xmlGenericErrorContext,
1167 "SAX.characters(%.30s, %d)\n", ch, len);
1168#endif
1169 /*
1170 * Handle the data if any. If there is no child
1171 * add it as content, otherwise if the last child is text,
1172 * concatenate it, else create a new node of type text.
1173 */
1174
1175 if (ctxt->node == NULL) {
1176#ifdef DEBUG_SAX_TREE
1177 xmlGenericError(xmlGenericErrorContext,
1178 "add chars: ctxt->node == NULL !\n");
1179#endif
1180 return;
1181 }
1182 lastChild = xmlGetLastChild(ctxt->node);
1183#ifdef DEBUG_SAX_TREE
1184 xmlGenericError(xmlGenericErrorContext,
1185 "add chars to %s \n", ctxt->node->name);
1186#endif
1187
1188 /*
1189 * Here we needed an accelerator mechanism in case of very large
1190 * elements. Use an attribute in the structure !!!
1191 */
1192 if (lastChild == NULL) {
1193 /* first node, first time */
1194 xmlNodeAddContentLen(ctxt->node, ch, len);
1195#ifndef XML_USE_BUFFER_CONTENT
1196 if (ctxt->node->children != NULL) {
1197 ctxt->nodelen = len;
1198 ctxt->nodemem = len + 1;
1199 }
1200#endif
1201 } else {
Daniel Veillard80f32572001-03-07 19:45:40 +00001202 int isText = xmlNodeIsText(lastChild);
1203 if ((isText) && (ctxt->nodemem != 0)) {
Owen Taylor3473f882001-02-23 17:55:21 +00001204#ifndef XML_USE_BUFFER_CONTENT
1205 /*
1206 * The whole point of maintaining nodelen and nodemem,
1207 * xmlTextConcat is too costly, i.e. compute lenght,
1208 * reallocate a new buffer, move data, append ch. Here
1209 * We try to minimaze realloc() uses and avoid copying
1210 * and recomputing lenght over and over.
1211 */
1212 if (ctxt->nodelen + len >= ctxt->nodemem) {
1213 xmlChar *newbuf;
1214 int size;
1215
1216 size = ctxt->nodemem + len;
1217 size *= 2;
1218 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
1219 if (newbuf == NULL) {
1220 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1221 ctxt->sax->error(ctxt->userData,
1222 "SAX.characters(): out of memory\n");
1223 return;
1224 }
1225 ctxt->nodemem = size;
1226 lastChild->content = newbuf;
1227 }
1228 memcpy(&lastChild->content[ctxt->nodelen], ch, len);
1229 ctxt->nodelen += len;
1230 lastChild->content[ctxt->nodelen] = 0;
1231#else
1232 xmlTextConcat(lastChild, ch, len);
1233#endif
Daniel Veillard80f32572001-03-07 19:45:40 +00001234 } else if (isText) {
1235 xmlTextConcat(lastChild, ch, len);
1236 if (ctxt->node->children != NULL) {
1237 ctxt->nodelen = xmlStrlen(lastChild->content);
1238 ctxt->nodemem = ctxt->nodelen + 1;
1239 }
Owen Taylor3473f882001-02-23 17:55:21 +00001240 } else {
1241 /* Mixed content, first time */
1242 lastChild = xmlNewTextLen(ch, len);
1243 xmlAddChild(ctxt->node, lastChild);
1244#ifndef XML_USE_BUFFER_CONTENT
1245 if (ctxt->node->children != NULL) {
1246 ctxt->nodelen = len;
1247 ctxt->nodemem = len + 1;
1248 }
1249#endif
1250 }
1251 }
1252}
1253
1254/**
1255 * ignorableWhitespace:
1256 * @ctx: the user data (XML parser context)
1257 * @ch: a xmlChar string
1258 * @len: the number of xmlChar
1259 *
1260 * receiving some ignorable whitespaces from the parser.
1261 * Question: how much at a time ???
1262 */
1263void
1264ignorableWhitespace(void *ctx, const xmlChar *ch, int len)
1265{
1266 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
1267#ifdef DEBUG_SAX
1268 xmlGenericError(xmlGenericErrorContext,
1269 "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len);
1270#endif
1271}
1272
1273/**
1274 * processingInstruction:
1275 * @ctx: the user data (XML parser context)
1276 * @target: the target name
1277 * @data: the PI data's
1278 *
1279 * A processing instruction has been parsed.
1280 */
1281void
1282processingInstruction(void *ctx, const xmlChar *target,
1283 const xmlChar *data)
1284{
1285 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1286 xmlNodePtr ret;
1287 xmlNodePtr parent = ctxt->node;
1288
1289#ifdef DEBUG_SAX
1290 xmlGenericError(xmlGenericErrorContext,
1291 "SAX.processingInstruction(%s, %s)\n", target, data);
1292#endif
1293
1294 ret = xmlNewPI(target, data);
1295 if (ret == NULL) return;
1296 parent = ctxt->node;
1297
1298 if (ctxt->inSubset == 1) {
1299 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1300 return;
1301 } else if (ctxt->inSubset == 2) {
1302 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1303 return;
1304 }
1305 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
1306#ifdef DEBUG_SAX_TREE
1307 xmlGenericError(xmlGenericErrorContext,
1308 "Setting PI %s as root\n", target);
1309#endif
1310 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1311 return;
1312 }
1313 if (parent->type == XML_ELEMENT_NODE) {
1314#ifdef DEBUG_SAX_TREE
1315 xmlGenericError(xmlGenericErrorContext,
1316 "adding PI %s child to %s\n", target, parent->name);
1317#endif
1318 xmlAddChild(parent, ret);
1319 } else {
1320#ifdef DEBUG_SAX_TREE
1321 xmlGenericError(xmlGenericErrorContext,
1322 "adding PI %s sibling to ", target);
1323 xmlDebugDumpOneNode(stderr, parent, 0);
1324#endif
1325 xmlAddSibling(parent, ret);
1326 }
1327}
1328
1329/**
1330 * globalNamespace:
1331 * @ctx: the user data (XML parser context)
1332 * @href: the namespace associated URN
1333 * @prefix: the namespace prefix
1334 *
1335 * An old global namespace has been parsed.
1336 */
1337void
1338globalNamespace(void *ctx, const xmlChar *href, const xmlChar *prefix)
1339{
1340 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1341#ifdef DEBUG_SAX
1342 xmlGenericError(xmlGenericErrorContext,
1343 "SAX.globalNamespace(%s, %s)\n", href, prefix);
1344#endif
1345 xmlNewGlobalNs(ctxt->myDoc, href, prefix);
1346}
1347
1348/**
1349 * setNamespace:
1350 * @ctx: the user data (XML parser context)
1351 * @name: the namespace prefix
1352 *
1353 * Set the current element namespace.
1354 */
1355
1356void
1357setNamespace(void *ctx, const xmlChar *name)
1358{
1359 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1360 xmlNsPtr ns;
1361 xmlNodePtr parent;
1362
1363#ifdef DEBUG_SAX
1364 xmlGenericError(xmlGenericErrorContext, "SAX.setNamespace(%s)\n", name);
1365#endif
1366 ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name);
1367 if (ns == NULL) { /* ctxt->node may not have a parent yet ! */
1368 if (ctxt->nodeNr >= 2) {
1369 parent = ctxt->nodeTab[ctxt->nodeNr - 2];
1370 if (parent != NULL)
1371 ns = xmlSearchNs(ctxt->myDoc, parent, name);
1372 }
1373 }
1374 xmlSetNs(ctxt->node, ns);
1375}
1376
1377/**
1378 * getNamespace:
1379 * @ctx: the user data (XML parser context)
1380 *
1381 * Get the current element namespace.
1382 *
1383 * Returns the xmlNsPtr or NULL if none
1384 */
1385
1386xmlNsPtr
1387getNamespace(void *ctx)
1388{
1389 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1390 xmlNsPtr ret;
1391
1392#ifdef DEBUG_SAX
1393 xmlGenericError(xmlGenericErrorContext, "SAX.getNamespace()\n");
1394#endif
1395 ret = ctxt->node->ns;
1396 return(ret);
1397}
1398
1399/**
1400 * checkNamespace:
1401 * @ctx: the user data (XML parser context)
1402 * @namespace: the namespace to check against
1403 *
1404 * Check that the current element namespace is the same as the
1405 * one read upon parsing.
1406 *
1407 * Returns 1 if true 0 otherwise
1408 */
1409
1410int
1411checkNamespace(void *ctx, xmlChar *namespace)
1412{
1413 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1414 xmlNodePtr cur = ctxt->node;
1415
1416#ifdef DEBUG_SAX
1417 xmlGenericError(xmlGenericErrorContext,
1418 "SAX.checkNamespace(%s)\n", namespace);
1419#endif
1420
1421 /*
1422 * Check that the Name in the ETag is the same as in the STag.
1423 */
1424 if (namespace == NULL) {
1425 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1426 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1427 ctxt->sax->error(ctxt,
1428 "End tags for %s don't hold the namespace %s\n",
1429 cur->name, cur->ns->prefix);
1430 ctxt->wellFormed = 0;
1431 }
1432 } else {
1433 if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) {
1434 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1435 ctxt->sax->error(ctxt,
1436 "End tags %s holds a prefix %s not used by the open tag\n",
1437 cur->name, namespace);
1438 ctxt->wellFormed = 0;
1439 } else if (!xmlStrEqual(namespace, cur->ns->prefix)) {
1440 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1441 ctxt->sax->error(ctxt,
1442 "Start and End tags for %s don't use the same namespaces: %s and %s\n",
1443 cur->name, cur->ns->prefix, namespace);
1444 ctxt->wellFormed = 0;
1445 } else
1446 return(1);
1447 }
1448 return(0);
1449}
1450
1451/**
1452 * namespaceDecl:
1453 * @ctx: the user data (XML parser context)
1454 * @href: the namespace associated URN
1455 * @prefix: the namespace prefix
1456 *
1457 * A namespace has been parsed.
1458 */
1459void
1460namespaceDecl(void *ctx, const xmlChar *href, const xmlChar *prefix)
1461{
1462 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1463#ifdef DEBUG_SAX
1464 if (prefix == NULL)
1465 xmlGenericError(xmlGenericErrorContext,
1466 "SAX.namespaceDecl(%s, NULL)\n", href);
1467 else
1468 xmlGenericError(xmlGenericErrorContext,
1469 "SAX.namespaceDecl(%s, %s)\n", href, prefix);
1470#endif
1471 xmlNewNs(ctxt->node, href, prefix);
1472}
1473
1474/**
1475 * comment:
1476 * @ctx: the user data (XML parser context)
1477 * @value: the comment content
1478 *
1479 * A comment has been parsed.
1480 */
1481void
1482comment(void *ctx, const xmlChar *value)
1483{
1484 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1485 xmlNodePtr ret;
1486 xmlNodePtr parent = ctxt->node;
1487
1488#ifdef DEBUG_SAX
1489 xmlGenericError(xmlGenericErrorContext, "SAX.comment(%s)\n", value);
1490#endif
1491 ret = xmlNewDocComment(ctxt->myDoc, value);
1492 if (ret == NULL) return;
1493
1494 if (ctxt->inSubset == 1) {
1495 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1496 return;
1497 } else if (ctxt->inSubset == 2) {
1498 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1499 return;
1500 }
1501 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
1502#ifdef DEBUG_SAX_TREE
1503 xmlGenericError(xmlGenericErrorContext,
1504 "Setting comment as root\n");
1505#endif
1506 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1507 return;
1508 }
1509 if (parent->type == XML_ELEMENT_NODE) {
1510#ifdef DEBUG_SAX_TREE
1511 xmlGenericError(xmlGenericErrorContext,
1512 "adding comment child to %s\n", parent->name);
1513#endif
1514 xmlAddChild(parent, ret);
1515 } else {
1516#ifdef DEBUG_SAX_TREE
1517 xmlGenericError(xmlGenericErrorContext,
1518 "adding comment sibling to ");
1519 xmlDebugDumpOneNode(stderr, parent, 0);
1520#endif
1521 xmlAddSibling(parent, ret);
1522 }
1523}
1524
1525/**
1526 * cdataBlock:
1527 * @ctx: the user data (XML parser context)
1528 * @value: The pcdata content
1529 * @len: the block length
1530 *
1531 * called when a pcdata block has been parsed
1532 */
1533void
1534cdataBlock(void *ctx, const xmlChar *value, int len)
1535{
1536 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1537 xmlNodePtr ret, lastChild;
1538
1539#ifdef DEBUG_SAX
1540 xmlGenericError(xmlGenericErrorContext,
1541 "SAX.pcdata(%.10s, %d)\n", value, len);
1542#endif
1543 lastChild = xmlGetLastChild(ctxt->node);
1544#ifdef DEBUG_SAX_TREE
1545 xmlGenericError(xmlGenericErrorContext,
1546 "add chars to %s \n", ctxt->node->name);
1547#endif
1548 if ((lastChild != NULL) &&
1549 (lastChild->type == XML_CDATA_SECTION_NODE)) {
1550 xmlTextConcat(lastChild, value, len);
1551 } else {
1552 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
1553 xmlAddChild(ctxt->node, ret);
1554 }
1555}
1556
1557/*
1558 * Default handler for XML, builds the DOM tree
1559 */
1560xmlSAXHandler xmlDefaultSAXHandler = {
1561 internalSubset,
1562 isStandalone,
1563 hasInternalSubset,
1564 hasExternalSubset,
1565 resolveEntity,
1566 getEntity,
1567 entityDecl,
1568 notationDecl,
1569 attributeDecl,
1570 elementDecl,
1571 unparsedEntityDecl,
1572 setDocumentLocator,
1573 startDocument,
1574 endDocument,
1575 startElement,
1576 endElement,
1577 reference,
1578 characters,
1579 ignorableWhitespace,
1580 processingInstruction,
1581 comment,
1582 xmlParserWarning,
1583 xmlParserError,
1584 xmlParserError,
1585 getParameterEntity,
1586 cdataBlock,
1587 externalSubset,
1588};
1589
1590/**
1591 * xmlDefaultSAXHandlerInit:
1592 *
1593 * Initialize the default SAX handler
1594 */
1595void
1596xmlDefaultSAXHandlerInit(void)
1597{
1598 xmlDefaultSAXHandler.internalSubset = internalSubset;
1599 xmlDefaultSAXHandler.externalSubset = externalSubset;
1600 xmlDefaultSAXHandler.isStandalone = isStandalone;
1601 xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
1602 xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
1603 xmlDefaultSAXHandler.resolveEntity = resolveEntity;
1604 xmlDefaultSAXHandler.getEntity = getEntity;
1605 xmlDefaultSAXHandler.getParameterEntity = getParameterEntity;
1606 xmlDefaultSAXHandler.entityDecl = entityDecl;
1607 xmlDefaultSAXHandler.attributeDecl = attributeDecl;
1608 xmlDefaultSAXHandler.elementDecl = elementDecl;
1609 xmlDefaultSAXHandler.notationDecl = notationDecl;
1610 xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
1611 xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1612 xmlDefaultSAXHandler.startDocument = startDocument;
1613 xmlDefaultSAXHandler.endDocument = endDocument;
1614 xmlDefaultSAXHandler.startElement = startElement;
1615 xmlDefaultSAXHandler.endElement = endElement;
1616 xmlDefaultSAXHandler.reference = reference;
1617 xmlDefaultSAXHandler.characters = characters;
1618 xmlDefaultSAXHandler.cdataBlock = cdataBlock;
1619 xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1620 xmlDefaultSAXHandler.processingInstruction = processingInstruction;
1621 xmlDefaultSAXHandler.comment = comment;
1622 if (xmlGetWarningsDefaultValue == 0)
1623 xmlDefaultSAXHandler.warning = NULL;
1624 else
1625 xmlDefaultSAXHandler.warning = xmlParserWarning;
1626 xmlDefaultSAXHandler.error = xmlParserError;
1627 xmlDefaultSAXHandler.fatalError = xmlParserError;
1628}
1629
1630/*
1631 * Default handler for HTML, builds the DOM tree
1632 */
1633xmlSAXHandler htmlDefaultSAXHandler = {
1634 internalSubset,
1635 NULL,
1636 NULL,
1637 NULL,
1638 NULL,
1639 getEntity,
1640 NULL,
1641 NULL,
1642 NULL,
1643 NULL,
1644 NULL,
1645 setDocumentLocator,
1646 startDocument,
1647 endDocument,
1648 startElement,
1649 endElement,
1650 NULL,
1651 characters,
1652 ignorableWhitespace,
1653 NULL,
1654 comment,
1655 xmlParserWarning,
1656 xmlParserError,
1657 xmlParserError,
1658 getParameterEntity,
1659 cdataBlock,
1660 NULL,
1661};
1662
1663/**
1664 * htmlDefaultSAXHandlerInit:
1665 *
1666 * Initialize the default SAX handler
1667 */
1668void
1669htmlDefaultSAXHandlerInit(void)
1670{
1671 htmlDefaultSAXHandler.internalSubset = internalSubset;
1672 htmlDefaultSAXHandler.externalSubset = NULL;
1673 htmlDefaultSAXHandler.isStandalone = NULL;
1674 htmlDefaultSAXHandler.hasInternalSubset = NULL;
1675 htmlDefaultSAXHandler.hasExternalSubset = NULL;
1676 htmlDefaultSAXHandler.resolveEntity = NULL;
1677 htmlDefaultSAXHandler.getEntity = getEntity;
1678 htmlDefaultSAXHandler.getParameterEntity = NULL;
1679 htmlDefaultSAXHandler.entityDecl = NULL;
1680 htmlDefaultSAXHandler.attributeDecl = NULL;
1681 htmlDefaultSAXHandler.elementDecl = NULL;
1682 htmlDefaultSAXHandler.notationDecl = NULL;
1683 htmlDefaultSAXHandler.unparsedEntityDecl = NULL;
1684 htmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1685 htmlDefaultSAXHandler.startDocument = startDocument;
1686 htmlDefaultSAXHandler.endDocument = endDocument;
1687 htmlDefaultSAXHandler.startElement = startElement;
1688 htmlDefaultSAXHandler.endElement = endElement;
1689 htmlDefaultSAXHandler.reference = NULL;
1690 htmlDefaultSAXHandler.characters = characters;
1691 htmlDefaultSAXHandler.cdataBlock = cdataBlock;
1692 htmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1693 htmlDefaultSAXHandler.processingInstruction = NULL;
1694 htmlDefaultSAXHandler.comment = comment;
1695 htmlDefaultSAXHandler.warning = xmlParserWarning;
1696 htmlDefaultSAXHandler.error = xmlParserError;
1697 htmlDefaultSAXHandler.fatalError = xmlParserError;
1698}
1699
1700/*
1701 * Default handler for HTML, builds the DOM tree
1702 */
1703xmlSAXHandler sgmlDefaultSAXHandler = {
1704 internalSubset,
1705 NULL,
1706 NULL,
1707 NULL,
1708 NULL,
1709 getEntity,
1710 NULL,
1711 NULL,
1712 NULL,
1713 NULL,
1714 NULL,
1715 setDocumentLocator,
1716 startDocument,
1717 endDocument,
1718 startElement,
1719 endElement,
1720 NULL,
1721 characters,
1722 ignorableWhitespace,
1723 NULL,
1724 comment,
1725 xmlParserWarning,
1726 xmlParserError,
1727 xmlParserError,
1728 getParameterEntity,
1729 NULL,
1730 NULL,
1731};
1732
1733/**
1734 * sgmlDefaultSAXHandlerInit:
1735 *
1736 * Initialize the default SAX handler
1737 */
1738void
1739sgmlDefaultSAXHandlerInit(void)
1740{
1741 sgmlDefaultSAXHandler.internalSubset = internalSubset;
1742 sgmlDefaultSAXHandler.externalSubset = NULL;
1743 sgmlDefaultSAXHandler.isStandalone = NULL;
1744 sgmlDefaultSAXHandler.hasInternalSubset = NULL;
1745 sgmlDefaultSAXHandler.hasExternalSubset = NULL;
1746 sgmlDefaultSAXHandler.resolveEntity = NULL;
1747 sgmlDefaultSAXHandler.getEntity = getEntity;
1748 sgmlDefaultSAXHandler.getParameterEntity = NULL;
1749 sgmlDefaultSAXHandler.entityDecl = NULL;
1750 sgmlDefaultSAXHandler.attributeDecl = NULL;
1751 sgmlDefaultSAXHandler.elementDecl = NULL;
1752 sgmlDefaultSAXHandler.notationDecl = NULL;
1753 sgmlDefaultSAXHandler.unparsedEntityDecl = NULL;
1754 sgmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1755 sgmlDefaultSAXHandler.startDocument = startDocument;
1756 sgmlDefaultSAXHandler.endDocument = endDocument;
1757 sgmlDefaultSAXHandler.startElement = startElement;
1758 sgmlDefaultSAXHandler.endElement = endElement;
1759 sgmlDefaultSAXHandler.reference = NULL;
1760 sgmlDefaultSAXHandler.characters = characters;
1761 sgmlDefaultSAXHandler.cdataBlock = NULL;
1762 sgmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1763 sgmlDefaultSAXHandler.processingInstruction = NULL;
1764 sgmlDefaultSAXHandler.comment = comment;
1765 sgmlDefaultSAXHandler.warning = xmlParserWarning;
1766 sgmlDefaultSAXHandler.error = xmlParserError;
1767 sgmlDefaultSAXHandler.fatalError = xmlParserError;
1768}