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