blob: 5466c0173e87ceff263baf68ab54764921659bc3 [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;
Daniel Veillard7a51d6d2001-09-10 14:40:43 +0000974 ctxt->valid = 0;
975 ctxt->errNo = XML_ERR_NO_DTD;
Owen Taylor3473f882001-02-23 17:55:21 +0000976 }
977
978
979 /*
980 * Split the full name into a namespace prefix and the tag name
981 */
982 name = xmlSplitQName(ctxt, fullname, &prefix);
983
984
985 /*
986 * Note : the namespace resolution is deferred until the end of the
987 * attributes parsing, since local namespace can be defined as
988 * an attribute at this level.
989 */
990 ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL);
991 if (ret == NULL) return;
992 if (ctxt->myDoc->children == NULL) {
993#ifdef DEBUG_SAX_TREE
994 xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
995#endif
996 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
997 } else if (parent == NULL) {
998 parent = ctxt->myDoc->children;
999 }
1000 ctxt->nodemem = -1;
Daniel Veillardd9bad132001-07-23 19:39:43 +00001001 if (ctxt->linenumbers) {
1002 if (ctxt->input != NULL)
1003 ret->content = (void *) (long) ctxt->input->line;
1004 }
Owen Taylor3473f882001-02-23 17:55:21 +00001005
1006 /*
1007 * We are parsing a new node.
1008 */
1009#ifdef DEBUG_SAX_TREE
1010 xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);
1011#endif
1012 nodePush(ctxt, ret);
1013
1014 /*
1015 * Link the child element
1016 */
1017 if (parent != NULL) {
1018 if (parent->type == XML_ELEMENT_NODE) {
1019#ifdef DEBUG_SAX_TREE
1020 xmlGenericError(xmlGenericErrorContext,
1021 "adding child %s to %s\n", name, parent->name);
1022#endif
1023 xmlAddChild(parent, ret);
1024 } else {
1025#ifdef DEBUG_SAX_TREE
1026 xmlGenericError(xmlGenericErrorContext,
1027 "adding sibling %s to ", name);
1028 xmlDebugDumpOneNode(stderr, parent, 0);
1029#endif
1030 xmlAddSibling(parent, ret);
1031 }
1032 }
1033
1034 /*
Daniel Veillard48da9102001-08-07 01:10:10 +00001035 * Insert all the defaulted attributes from the DTD especially namespaces
1036 */
1037 if ((!ctxt->html) &&
1038 ((ctxt->myDoc->intSubset != NULL) ||
1039 (ctxt->myDoc->extSubset != NULL))) {
1040 xmlElementPtr elemDecl = NULL;
1041
1042 if (prefix != NULL) {
1043 if (ctxt->myDoc->intSubset != NULL)
1044 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset,
1045 name, prefix);
1046 if ((elemDecl == NULL) && (ctxt->myDoc->extSubset != NULL))
1047 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset,
1048 name, prefix);
1049 } else {
1050 if (ctxt->myDoc->intSubset != NULL)
1051 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset,
1052 name, prefix);
1053 if ((elemDecl == NULL) && (ctxt->myDoc->extSubset != NULL))
1054 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset,
1055 name, prefix);
1056 }
1057 if (elemDecl != NULL) {
1058 xmlAttributePtr attr = elemDecl->attributes;
1059 while (attr != NULL) {
1060 if (attr->defaultValue != NULL) {
1061 /*
1062 * the element should be instanciated in the tree if:
1063 * - this is a namespace prefix
1064 * - the user required for completion in the tree
1065 * like XSLT
1066 */
1067 if (((attr->prefix != NULL) &&
1068 (xmlStrEqual(attr->prefix, BAD_CAST "xmlns"))) ||
1069 ((attr->prefix == NULL) &&
1070 (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) ||
1071 (ctxt->loadsubset & XML_COMPLETE_ATTRS)) {
1072 xmlChar buffer[100];
1073 const xmlChar *fulln = attr->name;
1074
1075 if (attr->prefix != NULL) {
1076 snprintf((char *) buffer, 99, "%s:%s",
1077 attr->prefix, attr->name);
1078 buffer[99] = 0;
1079 fulln = buffer;
1080 }
1081
1082 /*
1083 * Check that the attribute is not declared in the
1084 * serialization
1085 */
1086 att = NULL;
1087 if (atts != NULL) {
1088 i = 0;
1089 att = atts[i];
1090 while (att != NULL) {
1091 if (xmlStrEqual(att, fulln))
1092 break;
1093 i += 2;
1094 att = atts[i];
1095 }
1096 }
1097 if (att == NULL)
1098 attribute(ctxt, fulln, attr->defaultValue);
1099 }
1100 }
1101 attr = attr->nexth;
1102 }
1103 }
1104 }
1105
1106 /*
Owen Taylor3473f882001-02-23 17:55:21 +00001107 * process all the attributes whose name start with "xml"
1108 */
1109 if (atts != NULL) {
1110 i = 0;
1111 att = atts[i++];
1112 value = atts[i++];
1113 if (!ctxt->html) {
1114 while ((att != NULL) && (value != NULL)) {
1115 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l'))
1116 attribute(ctxt, att, value);
1117
1118 att = atts[i++];
1119 value = atts[i++];
1120 }
1121 }
1122 }
1123
1124 /*
1125 * Search the namespace, note that since the attributes have been
1126 * processed, the local namespaces are available.
1127 */
1128 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
1129 if ((ns == NULL) && (parent != NULL))
1130 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
1131 if ((prefix != NULL) && (ns == NULL)) {
1132 ns = xmlNewNs(ret, NULL, prefix);
1133 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1134 ctxt->sax->warning(ctxt->userData,
1135 "Namespace prefix %s is not defined\n", prefix);
1136 }
1137 xmlSetNs(ret, ns);
1138
1139 /*
1140 * process all the other attributes
1141 */
1142 if (atts != NULL) {
1143 i = 0;
1144 att = atts[i++];
1145 value = atts[i++];
1146 if (ctxt->html) {
1147 while (att != NULL) {
1148 attribute(ctxt, att, value);
1149 att = atts[i++];
1150 value = atts[i++];
1151 }
1152 } else {
1153 while ((att != NULL) && (value != NULL)) {
1154 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l'))
1155 attribute(ctxt, att, value);
1156
1157 /*
1158 * Next ones
1159 */
1160 att = atts[i++];
1161 value = atts[i++];
1162 }
1163 }
1164 }
1165
1166 /*
1167 * If it's the Document root, finish the Dtd validation and
1168 * check the document root element for validity
1169 */
1170 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
1171 ctxt->valid &= xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
1172 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
1173 ctxt->vctxt.finishDtd = 1;
1174 }
1175
1176 if (prefix != NULL)
1177 xmlFree(prefix);
1178 if (name != NULL)
1179 xmlFree(name);
1180
1181}
1182
1183/**
1184 * endElement:
1185 * @ctx: the user data (XML parser context)
1186 * @name: The element name
1187 *
1188 * called when the end of an element has been detected.
1189 */
1190void
Daniel Veillardc86a4fa2001-03-26 16:28:29 +00001191endElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
Owen Taylor3473f882001-02-23 17:55:21 +00001192{
1193 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1194 xmlParserNodeInfo node_info;
1195 xmlNodePtr cur = ctxt->node;
1196
1197#ifdef DEBUG_SAX
1198 if (name == NULL)
1199 xmlGenericError(xmlGenericErrorContext, "SAX.endElement(NULL)\n");
1200 else
1201 xmlGenericError(xmlGenericErrorContext, "SAX.endElement(%s)\n", name);
1202#endif
1203
1204 /* Capture end position and add node */
1205 if (cur != NULL && ctxt->record_info) {
1206 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
1207 node_info.end_line = ctxt->input->line;
1208 node_info.node = cur;
1209 xmlParserAddNodeInfo(ctxt, &node_info);
1210 }
1211 ctxt->nodemem = -1;
1212
1213 if (ctxt->validate && ctxt->wellFormed &&
1214 ctxt->myDoc && ctxt->myDoc->intSubset)
1215 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
1216 cur);
1217
1218
1219 /*
1220 * end of parsing of this node.
1221 */
1222#ifdef DEBUG_SAX_TREE
1223 xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);
1224#endif
1225 nodePop(ctxt);
1226}
1227
1228/**
1229 * reference:
1230 * @ctx: the user data (XML parser context)
1231 * @name: The entity name
1232 *
1233 * called when an entity reference is detected.
1234 */
1235void
1236reference(void *ctx, const xmlChar *name)
1237{
1238 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1239 xmlNodePtr ret;
1240
1241#ifdef DEBUG_SAX
1242 xmlGenericError(xmlGenericErrorContext,
1243 "SAX.reference(%s)\n", name);
1244#endif
1245 if (name[0] == '#')
1246 ret = xmlNewCharRef(ctxt->myDoc, name);
1247 else
1248 ret = xmlNewReference(ctxt->myDoc, name);
1249#ifdef DEBUG_SAX_TREE
1250 xmlGenericError(xmlGenericErrorContext,
1251 "add reference %s to %s \n", name, ctxt->node->name);
1252#endif
1253 xmlAddChild(ctxt->node, ret);
1254}
1255
1256/**
1257 * characters:
1258 * @ctx: the user data (XML parser context)
1259 * @ch: a xmlChar string
1260 * @len: the number of xmlChar
1261 *
1262 * receiving some chars from the parser.
Owen Taylor3473f882001-02-23 17:55:21 +00001263 */
1264void
1265characters(void *ctx, const xmlChar *ch, int len)
1266{
1267 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1268 xmlNodePtr lastChild;
1269
1270#ifdef DEBUG_SAX
1271 xmlGenericError(xmlGenericErrorContext,
1272 "SAX.characters(%.30s, %d)\n", ch, len);
1273#endif
1274 /*
1275 * Handle the data if any. If there is no child
1276 * add it as content, otherwise if the last child is text,
1277 * concatenate it, else create a new node of type text.
1278 */
1279
1280 if (ctxt->node == NULL) {
1281#ifdef DEBUG_SAX_TREE
1282 xmlGenericError(xmlGenericErrorContext,
1283 "add chars: ctxt->node == NULL !\n");
1284#endif
1285 return;
1286 }
1287 lastChild = xmlGetLastChild(ctxt->node);
1288#ifdef DEBUG_SAX_TREE
1289 xmlGenericError(xmlGenericErrorContext,
1290 "add chars to %s \n", ctxt->node->name);
1291#endif
1292
1293 /*
1294 * Here we needed an accelerator mechanism in case of very large
1295 * elements. Use an attribute in the structure !!!
1296 */
1297 if (lastChild == NULL) {
1298 /* first node, first time */
1299 xmlNodeAddContentLen(ctxt->node, ch, len);
1300#ifndef XML_USE_BUFFER_CONTENT
1301 if (ctxt->node->children != NULL) {
1302 ctxt->nodelen = len;
1303 ctxt->nodemem = len + 1;
1304 }
1305#endif
1306 } else {
Daniel Veillardf300b7e2001-08-13 10:43:15 +00001307 int coalesceText = (lastChild != NULL) &&
1308 (lastChild->type == XML_TEXT_NODE) &&
1309 (lastChild->name == xmlStringText);
1310 if ((coalesceText) && (ctxt->nodemem != 0)) {
Owen Taylor3473f882001-02-23 17:55:21 +00001311#ifndef XML_USE_BUFFER_CONTENT
1312 /*
1313 * The whole point of maintaining nodelen and nodemem,
1314 * xmlTextConcat is too costly, i.e. compute lenght,
1315 * reallocate a new buffer, move data, append ch. Here
1316 * We try to minimaze realloc() uses and avoid copying
1317 * and recomputing lenght over and over.
1318 */
1319 if (ctxt->nodelen + len >= ctxt->nodemem) {
1320 xmlChar *newbuf;
1321 int size;
1322
1323 size = ctxt->nodemem + len;
1324 size *= 2;
1325 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
1326 if (newbuf == NULL) {
1327 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1328 ctxt->sax->error(ctxt->userData,
1329 "SAX.characters(): out of memory\n");
1330 return;
1331 }
1332 ctxt->nodemem = size;
1333 lastChild->content = newbuf;
1334 }
1335 memcpy(&lastChild->content[ctxt->nodelen], ch, len);
1336 ctxt->nodelen += len;
1337 lastChild->content[ctxt->nodelen] = 0;
1338#else
1339 xmlTextConcat(lastChild, ch, len);
1340#endif
Daniel Veillardf300b7e2001-08-13 10:43:15 +00001341 } else if (coalesceText) {
Daniel Veillard80f32572001-03-07 19:45:40 +00001342 xmlTextConcat(lastChild, ch, len);
1343 if (ctxt->node->children != NULL) {
1344 ctxt->nodelen = xmlStrlen(lastChild->content);
1345 ctxt->nodemem = ctxt->nodelen + 1;
1346 }
Owen Taylor3473f882001-02-23 17:55:21 +00001347 } else {
1348 /* Mixed content, first time */
1349 lastChild = xmlNewTextLen(ch, len);
1350 xmlAddChild(ctxt->node, lastChild);
1351#ifndef XML_USE_BUFFER_CONTENT
1352 if (ctxt->node->children != NULL) {
1353 ctxt->nodelen = len;
1354 ctxt->nodemem = len + 1;
1355 }
1356#endif
1357 }
1358 }
1359}
1360
1361/**
1362 * ignorableWhitespace:
1363 * @ctx: the user data (XML parser context)
1364 * @ch: a xmlChar string
1365 * @len: the number of xmlChar
1366 *
1367 * receiving some ignorable whitespaces from the parser.
Daniel Veillard05c13a22001-09-09 08:38:09 +00001368 * UNUSED: by default the DOM building will use characters
Owen Taylor3473f882001-02-23 17:55:21 +00001369 */
1370void
Daniel Veillardc86a4fa2001-03-26 16:28:29 +00001371ignorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
Owen Taylor3473f882001-02-23 17:55:21 +00001372{
1373 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
1374#ifdef DEBUG_SAX
1375 xmlGenericError(xmlGenericErrorContext,
1376 "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len);
1377#endif
1378}
1379
1380/**
1381 * processingInstruction:
1382 * @ctx: the user data (XML parser context)
1383 * @target: the target name
1384 * @data: the PI data's
1385 *
1386 * A processing instruction has been parsed.
1387 */
1388void
1389processingInstruction(void *ctx, const xmlChar *target,
1390 const xmlChar *data)
1391{
1392 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1393 xmlNodePtr ret;
1394 xmlNodePtr parent = ctxt->node;
1395
1396#ifdef DEBUG_SAX
1397 xmlGenericError(xmlGenericErrorContext,
1398 "SAX.processingInstruction(%s, %s)\n", target, data);
1399#endif
1400
1401 ret = xmlNewPI(target, data);
1402 if (ret == NULL) return;
1403 parent = ctxt->node;
1404
1405 if (ctxt->inSubset == 1) {
1406 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1407 return;
1408 } else if (ctxt->inSubset == 2) {
1409 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1410 return;
1411 }
1412 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
1413#ifdef DEBUG_SAX_TREE
1414 xmlGenericError(xmlGenericErrorContext,
1415 "Setting PI %s as root\n", target);
1416#endif
1417 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1418 return;
1419 }
1420 if (parent->type == XML_ELEMENT_NODE) {
1421#ifdef DEBUG_SAX_TREE
1422 xmlGenericError(xmlGenericErrorContext,
1423 "adding PI %s child to %s\n", target, parent->name);
1424#endif
1425 xmlAddChild(parent, ret);
1426 } else {
1427#ifdef DEBUG_SAX_TREE
1428 xmlGenericError(xmlGenericErrorContext,
1429 "adding PI %s sibling to ", target);
1430 xmlDebugDumpOneNode(stderr, parent, 0);
1431#endif
1432 xmlAddSibling(parent, ret);
1433 }
1434}
1435
1436/**
1437 * globalNamespace:
1438 * @ctx: the user data (XML parser context)
1439 * @href: the namespace associated URN
1440 * @prefix: the namespace prefix
1441 *
1442 * An old global namespace has been parsed.
1443 */
1444void
1445globalNamespace(void *ctx, const xmlChar *href, const xmlChar *prefix)
1446{
1447 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1448#ifdef DEBUG_SAX
1449 xmlGenericError(xmlGenericErrorContext,
1450 "SAX.globalNamespace(%s, %s)\n", href, prefix);
1451#endif
1452 xmlNewGlobalNs(ctxt->myDoc, href, prefix);
1453}
1454
1455/**
1456 * setNamespace:
1457 * @ctx: the user data (XML parser context)
1458 * @name: the namespace prefix
1459 *
1460 * Set the current element namespace.
1461 */
1462
1463void
1464setNamespace(void *ctx, const xmlChar *name)
1465{
1466 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1467 xmlNsPtr ns;
1468 xmlNodePtr parent;
1469
1470#ifdef DEBUG_SAX
1471 xmlGenericError(xmlGenericErrorContext, "SAX.setNamespace(%s)\n", name);
1472#endif
1473 ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name);
1474 if (ns == NULL) { /* ctxt->node may not have a parent yet ! */
1475 if (ctxt->nodeNr >= 2) {
1476 parent = ctxt->nodeTab[ctxt->nodeNr - 2];
1477 if (parent != NULL)
1478 ns = xmlSearchNs(ctxt->myDoc, parent, name);
1479 }
1480 }
1481 xmlSetNs(ctxt->node, ns);
1482}
1483
1484/**
1485 * getNamespace:
1486 * @ctx: the user data (XML parser context)
1487 *
1488 * Get the current element namespace.
1489 *
1490 * Returns the xmlNsPtr or NULL if none
1491 */
1492
1493xmlNsPtr
1494getNamespace(void *ctx)
1495{
1496 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1497 xmlNsPtr ret;
1498
1499#ifdef DEBUG_SAX
1500 xmlGenericError(xmlGenericErrorContext, "SAX.getNamespace()\n");
1501#endif
1502 ret = ctxt->node->ns;
1503 return(ret);
1504}
1505
1506/**
1507 * checkNamespace:
1508 * @ctx: the user data (XML parser context)
1509 * @namespace: the namespace to check against
1510 *
1511 * Check that the current element namespace is the same as the
1512 * one read upon parsing.
1513 *
1514 * Returns 1 if true 0 otherwise
1515 */
1516
1517int
1518checkNamespace(void *ctx, xmlChar *namespace)
1519{
1520 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1521 xmlNodePtr cur = ctxt->node;
1522
1523#ifdef DEBUG_SAX
1524 xmlGenericError(xmlGenericErrorContext,
1525 "SAX.checkNamespace(%s)\n", namespace);
1526#endif
1527
1528 /*
1529 * Check that the Name in the ETag is the same as in the STag.
1530 */
1531 if (namespace == NULL) {
1532 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1533 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1534 ctxt->sax->error(ctxt,
1535 "End tags for %s don't hold the namespace %s\n",
1536 cur->name, cur->ns->prefix);
1537 ctxt->wellFormed = 0;
1538 }
1539 } else {
1540 if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) {
1541 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1542 ctxt->sax->error(ctxt,
1543 "End tags %s holds a prefix %s not used by the open tag\n",
1544 cur->name, namespace);
1545 ctxt->wellFormed = 0;
1546 } else if (!xmlStrEqual(namespace, cur->ns->prefix)) {
1547 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1548 ctxt->sax->error(ctxt,
1549 "Start and End tags for %s don't use the same namespaces: %s and %s\n",
1550 cur->name, cur->ns->prefix, namespace);
1551 ctxt->wellFormed = 0;
1552 } else
1553 return(1);
1554 }
1555 return(0);
1556}
1557
1558/**
1559 * namespaceDecl:
1560 * @ctx: the user data (XML parser context)
1561 * @href: the namespace associated URN
1562 * @prefix: the namespace prefix
1563 *
1564 * A namespace has been parsed.
1565 */
1566void
1567namespaceDecl(void *ctx, const xmlChar *href, const xmlChar *prefix)
1568{
1569 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1570#ifdef DEBUG_SAX
1571 if (prefix == NULL)
1572 xmlGenericError(xmlGenericErrorContext,
1573 "SAX.namespaceDecl(%s, NULL)\n", href);
1574 else
1575 xmlGenericError(xmlGenericErrorContext,
1576 "SAX.namespaceDecl(%s, %s)\n", href, prefix);
1577#endif
1578 xmlNewNs(ctxt->node, href, prefix);
1579}
1580
1581/**
1582 * comment:
1583 * @ctx: the user data (XML parser context)
1584 * @value: the comment content
1585 *
1586 * A comment has been parsed.
1587 */
1588void
1589comment(void *ctx, const xmlChar *value)
1590{
1591 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1592 xmlNodePtr ret;
1593 xmlNodePtr parent = ctxt->node;
1594
1595#ifdef DEBUG_SAX
1596 xmlGenericError(xmlGenericErrorContext, "SAX.comment(%s)\n", value);
1597#endif
1598 ret = xmlNewDocComment(ctxt->myDoc, value);
1599 if (ret == NULL) return;
1600
1601 if (ctxt->inSubset == 1) {
1602 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1603 return;
1604 } else if (ctxt->inSubset == 2) {
1605 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1606 return;
1607 }
1608 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
1609#ifdef DEBUG_SAX_TREE
1610 xmlGenericError(xmlGenericErrorContext,
1611 "Setting comment as root\n");
1612#endif
1613 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1614 return;
1615 }
1616 if (parent->type == XML_ELEMENT_NODE) {
1617#ifdef DEBUG_SAX_TREE
1618 xmlGenericError(xmlGenericErrorContext,
1619 "adding comment child to %s\n", parent->name);
1620#endif
1621 xmlAddChild(parent, ret);
1622 } else {
1623#ifdef DEBUG_SAX_TREE
1624 xmlGenericError(xmlGenericErrorContext,
1625 "adding comment sibling to ");
1626 xmlDebugDumpOneNode(stderr, parent, 0);
1627#endif
1628 xmlAddSibling(parent, ret);
1629 }
1630}
1631
1632/**
1633 * cdataBlock:
1634 * @ctx: the user data (XML parser context)
1635 * @value: The pcdata content
1636 * @len: the block length
1637 *
1638 * called when a pcdata block has been parsed
1639 */
1640void
1641cdataBlock(void *ctx, const xmlChar *value, int len)
1642{
1643 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1644 xmlNodePtr ret, lastChild;
1645
1646#ifdef DEBUG_SAX
1647 xmlGenericError(xmlGenericErrorContext,
1648 "SAX.pcdata(%.10s, %d)\n", value, len);
1649#endif
1650 lastChild = xmlGetLastChild(ctxt->node);
1651#ifdef DEBUG_SAX_TREE
1652 xmlGenericError(xmlGenericErrorContext,
1653 "add chars to %s \n", ctxt->node->name);
1654#endif
1655 if ((lastChild != NULL) &&
1656 (lastChild->type == XML_CDATA_SECTION_NODE)) {
1657 xmlTextConcat(lastChild, value, len);
1658 } else {
1659 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
1660 xmlAddChild(ctxt->node, ret);
1661 }
1662}
1663
1664/*
1665 * Default handler for XML, builds the DOM tree
1666 */
1667xmlSAXHandler xmlDefaultSAXHandler = {
1668 internalSubset,
1669 isStandalone,
1670 hasInternalSubset,
1671 hasExternalSubset,
1672 resolveEntity,
1673 getEntity,
1674 entityDecl,
1675 notationDecl,
1676 attributeDecl,
1677 elementDecl,
1678 unparsedEntityDecl,
1679 setDocumentLocator,
1680 startDocument,
1681 endDocument,
1682 startElement,
1683 endElement,
1684 reference,
1685 characters,
Daniel Veillard05c13a22001-09-09 08:38:09 +00001686 characters,
Owen Taylor3473f882001-02-23 17:55:21 +00001687 processingInstruction,
1688 comment,
1689 xmlParserWarning,
1690 xmlParserError,
1691 xmlParserError,
1692 getParameterEntity,
1693 cdataBlock,
1694 externalSubset,
1695};
1696
1697/**
1698 * xmlDefaultSAXHandlerInit:
1699 *
1700 * Initialize the default SAX handler
1701 */
1702void
1703xmlDefaultSAXHandlerInit(void)
1704{
Daniel Veillard7583a592001-07-08 13:15:55 +00001705 static int xmlSAXInitialized = 0;
1706 if (xmlSAXInitialized)
1707 return;
1708
Owen Taylor3473f882001-02-23 17:55:21 +00001709 xmlDefaultSAXHandler.internalSubset = internalSubset;
1710 xmlDefaultSAXHandler.externalSubset = externalSubset;
1711 xmlDefaultSAXHandler.isStandalone = isStandalone;
1712 xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
1713 xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
1714 xmlDefaultSAXHandler.resolveEntity = resolveEntity;
1715 xmlDefaultSAXHandler.getEntity = getEntity;
1716 xmlDefaultSAXHandler.getParameterEntity = getParameterEntity;
1717 xmlDefaultSAXHandler.entityDecl = entityDecl;
1718 xmlDefaultSAXHandler.attributeDecl = attributeDecl;
1719 xmlDefaultSAXHandler.elementDecl = elementDecl;
1720 xmlDefaultSAXHandler.notationDecl = notationDecl;
1721 xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
1722 xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1723 xmlDefaultSAXHandler.startDocument = startDocument;
1724 xmlDefaultSAXHandler.endDocument = endDocument;
1725 xmlDefaultSAXHandler.startElement = startElement;
1726 xmlDefaultSAXHandler.endElement = endElement;
1727 xmlDefaultSAXHandler.reference = reference;
1728 xmlDefaultSAXHandler.characters = characters;
1729 xmlDefaultSAXHandler.cdataBlock = cdataBlock;
Daniel Veillard05c13a22001-09-09 08:38:09 +00001730 xmlDefaultSAXHandler.ignorableWhitespace = characters;
Owen Taylor3473f882001-02-23 17:55:21 +00001731 xmlDefaultSAXHandler.processingInstruction = processingInstruction;
1732 xmlDefaultSAXHandler.comment = comment;
1733 if (xmlGetWarningsDefaultValue == 0)
1734 xmlDefaultSAXHandler.warning = NULL;
1735 else
1736 xmlDefaultSAXHandler.warning = xmlParserWarning;
1737 xmlDefaultSAXHandler.error = xmlParserError;
1738 xmlDefaultSAXHandler.fatalError = xmlParserError;
Daniel Veillard7583a592001-07-08 13:15:55 +00001739
1740 xmlSAXInitialized = 1;
Owen Taylor3473f882001-02-23 17:55:21 +00001741}
1742
Daniel Veillardeae522a2001-04-23 13:41:34 +00001743#ifdef LIBXML_HTML_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00001744/*
1745 * Default handler for HTML, builds the DOM tree
1746 */
1747xmlSAXHandler htmlDefaultSAXHandler = {
1748 internalSubset,
1749 NULL,
1750 NULL,
1751 NULL,
1752 NULL,
1753 getEntity,
1754 NULL,
1755 NULL,
1756 NULL,
1757 NULL,
1758 NULL,
1759 setDocumentLocator,
1760 startDocument,
1761 endDocument,
1762 startElement,
1763 endElement,
1764 NULL,
1765 characters,
Daniel Veillard05c13a22001-09-09 08:38:09 +00001766 characters,
Owen Taylor3473f882001-02-23 17:55:21 +00001767 NULL,
1768 comment,
1769 xmlParserWarning,
1770 xmlParserError,
1771 xmlParserError,
1772 getParameterEntity,
1773 cdataBlock,
1774 NULL,
1775};
1776
1777/**
1778 * htmlDefaultSAXHandlerInit:
1779 *
1780 * Initialize the default SAX handler
1781 */
1782void
1783htmlDefaultSAXHandlerInit(void)
1784{
Daniel Veillard7583a592001-07-08 13:15:55 +00001785 static int htmlSAXInitialized = 0;
1786 if (htmlSAXInitialized)
1787 return;
1788
Owen Taylor3473f882001-02-23 17:55:21 +00001789 htmlDefaultSAXHandler.internalSubset = internalSubset;
1790 htmlDefaultSAXHandler.externalSubset = NULL;
1791 htmlDefaultSAXHandler.isStandalone = NULL;
1792 htmlDefaultSAXHandler.hasInternalSubset = NULL;
1793 htmlDefaultSAXHandler.hasExternalSubset = NULL;
1794 htmlDefaultSAXHandler.resolveEntity = NULL;
1795 htmlDefaultSAXHandler.getEntity = getEntity;
1796 htmlDefaultSAXHandler.getParameterEntity = NULL;
1797 htmlDefaultSAXHandler.entityDecl = NULL;
1798 htmlDefaultSAXHandler.attributeDecl = NULL;
1799 htmlDefaultSAXHandler.elementDecl = NULL;
1800 htmlDefaultSAXHandler.notationDecl = NULL;
1801 htmlDefaultSAXHandler.unparsedEntityDecl = NULL;
1802 htmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1803 htmlDefaultSAXHandler.startDocument = startDocument;
1804 htmlDefaultSAXHandler.endDocument = endDocument;
1805 htmlDefaultSAXHandler.startElement = startElement;
1806 htmlDefaultSAXHandler.endElement = endElement;
1807 htmlDefaultSAXHandler.reference = NULL;
1808 htmlDefaultSAXHandler.characters = characters;
1809 htmlDefaultSAXHandler.cdataBlock = cdataBlock;
1810 htmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1811 htmlDefaultSAXHandler.processingInstruction = NULL;
1812 htmlDefaultSAXHandler.comment = comment;
1813 htmlDefaultSAXHandler.warning = xmlParserWarning;
1814 htmlDefaultSAXHandler.error = xmlParserError;
1815 htmlDefaultSAXHandler.fatalError = xmlParserError;
Daniel Veillard7583a592001-07-08 13:15:55 +00001816
1817 htmlSAXInitialized = 1;
Owen Taylor3473f882001-02-23 17:55:21 +00001818}
Daniel Veillardeae522a2001-04-23 13:41:34 +00001819#endif /* LIBXML_HTML_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +00001820
Daniel Veillardeae522a2001-04-23 13:41:34 +00001821#ifdef LIBXML_DOCB_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00001822/*
Daniel Veillardeae522a2001-04-23 13:41:34 +00001823 * Default handler for SGML DocBook, builds the DOM tree
Owen Taylor3473f882001-02-23 17:55:21 +00001824 */
Daniel Veillardeae522a2001-04-23 13:41:34 +00001825xmlSAXHandler docbDefaultSAXHandler = {
Owen Taylor3473f882001-02-23 17:55:21 +00001826 internalSubset,
Daniel Veillard61b33d52001-04-24 13:55:12 +00001827 isStandalone,
1828 hasInternalSubset,
1829 hasExternalSubset,
1830 resolveEntity,
Owen Taylor3473f882001-02-23 17:55:21 +00001831 getEntity,
Daniel Veillard61b33d52001-04-24 13:55:12 +00001832 entityDecl,
Owen Taylor3473f882001-02-23 17:55:21 +00001833 NULL,
1834 NULL,
1835 NULL,
1836 NULL,
1837 setDocumentLocator,
1838 startDocument,
1839 endDocument,
1840 startElement,
1841 endElement,
Daniel Veillard1034da22001-04-25 19:06:28 +00001842 reference,
Owen Taylor3473f882001-02-23 17:55:21 +00001843 characters,
1844 ignorableWhitespace,
1845 NULL,
1846 comment,
1847 xmlParserWarning,
1848 xmlParserError,
1849 xmlParserError,
1850 getParameterEntity,
1851 NULL,
1852 NULL,
1853};
1854
1855/**
Daniel Veillardeae522a2001-04-23 13:41:34 +00001856 * docbDefaultSAXHandlerInit:
Owen Taylor3473f882001-02-23 17:55:21 +00001857 *
1858 * Initialize the default SAX handler
1859 */
1860void
Daniel Veillardeae522a2001-04-23 13:41:34 +00001861docbDefaultSAXHandlerInit(void)
Owen Taylor3473f882001-02-23 17:55:21 +00001862{
Daniel Veillard7583a592001-07-08 13:15:55 +00001863 static int docbSAXInitialized = 0;
1864 if (docbSAXInitialized)
1865 return;
1866
Daniel Veillardeae522a2001-04-23 13:41:34 +00001867 docbDefaultSAXHandler.internalSubset = internalSubset;
1868 docbDefaultSAXHandler.externalSubset = NULL;
Daniel Veillard61b33d52001-04-24 13:55:12 +00001869 docbDefaultSAXHandler.isStandalone = isStandalone;
1870 docbDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
1871 docbDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
1872 docbDefaultSAXHandler.resolveEntity = resolveEntity;
Daniel Veillardeae522a2001-04-23 13:41:34 +00001873 docbDefaultSAXHandler.getEntity = getEntity;
1874 docbDefaultSAXHandler.getParameterEntity = NULL;
Daniel Veillard61b33d52001-04-24 13:55:12 +00001875 docbDefaultSAXHandler.entityDecl = entityDecl;
Daniel Veillardeae522a2001-04-23 13:41:34 +00001876 docbDefaultSAXHandler.attributeDecl = NULL;
1877 docbDefaultSAXHandler.elementDecl = NULL;
1878 docbDefaultSAXHandler.notationDecl = NULL;
1879 docbDefaultSAXHandler.unparsedEntityDecl = NULL;
1880 docbDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1881 docbDefaultSAXHandler.startDocument = startDocument;
1882 docbDefaultSAXHandler.endDocument = endDocument;
1883 docbDefaultSAXHandler.startElement = startElement;
1884 docbDefaultSAXHandler.endElement = endElement;
Daniel Veillard1034da22001-04-25 19:06:28 +00001885 docbDefaultSAXHandler.reference = reference;
Daniel Veillardeae522a2001-04-23 13:41:34 +00001886 docbDefaultSAXHandler.characters = characters;
1887 docbDefaultSAXHandler.cdataBlock = NULL;
1888 docbDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1889 docbDefaultSAXHandler.processingInstruction = NULL;
1890 docbDefaultSAXHandler.comment = comment;
1891 docbDefaultSAXHandler.warning = xmlParserWarning;
1892 docbDefaultSAXHandler.error = xmlParserError;
1893 docbDefaultSAXHandler.fatalError = xmlParserError;
Daniel Veillard7583a592001-07-08 13:15:55 +00001894
1895 docbSAXInitialized = 1;
Owen Taylor3473f882001-02-23 17:55:21 +00001896}
Daniel Veillardeae522a2001-04-23 13:41:34 +00001897
1898#endif /* LIBXML_DOCB_ENABLED */