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