blob: be5c760840181cb741c765d8055f9f379c21b96f [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 }
Daniel Veillard143b04f2001-09-10 18:14:14 +00001137
1138 /*
1139 * set the namespace node, making sure that if the default namspace
1140 * is unbound on a parent we simply kee it NULL
1141 */
Daniel Veillard651f9472001-10-04 14:51:06 +00001142 if ((ns != NULL) && (ns->href != NULL) && (ns->href[0] != 0))
Daniel Veillard143b04f2001-09-10 18:14:14 +00001143 xmlSetNs(ret, ns);
Owen Taylor3473f882001-02-23 17:55:21 +00001144
1145 /*
1146 * process all the other attributes
1147 */
1148 if (atts != NULL) {
1149 i = 0;
1150 att = atts[i++];
1151 value = atts[i++];
1152 if (ctxt->html) {
1153 while (att != NULL) {
1154 attribute(ctxt, att, value);
1155 att = atts[i++];
1156 value = atts[i++];
1157 }
1158 } else {
1159 while ((att != NULL) && (value != NULL)) {
1160 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l'))
1161 attribute(ctxt, att, value);
1162
1163 /*
1164 * Next ones
1165 */
1166 att = atts[i++];
1167 value = atts[i++];
1168 }
1169 }
1170 }
1171
1172 /*
1173 * If it's the Document root, finish the Dtd validation and
1174 * check the document root element for validity
1175 */
1176 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
1177 ctxt->valid &= xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
1178 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
1179 ctxt->vctxt.finishDtd = 1;
1180 }
1181
1182 if (prefix != NULL)
1183 xmlFree(prefix);
1184 if (name != NULL)
1185 xmlFree(name);
1186
1187}
1188
1189/**
1190 * endElement:
1191 * @ctx: the user data (XML parser context)
1192 * @name: The element name
1193 *
1194 * called when the end of an element has been detected.
1195 */
1196void
Daniel Veillardc86a4fa2001-03-26 16:28:29 +00001197endElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
Owen Taylor3473f882001-02-23 17:55:21 +00001198{
1199 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1200 xmlParserNodeInfo node_info;
1201 xmlNodePtr cur = ctxt->node;
1202
1203#ifdef DEBUG_SAX
1204 if (name == NULL)
1205 xmlGenericError(xmlGenericErrorContext, "SAX.endElement(NULL)\n");
1206 else
1207 xmlGenericError(xmlGenericErrorContext, "SAX.endElement(%s)\n", name);
1208#endif
1209
1210 /* Capture end position and add node */
1211 if (cur != NULL && ctxt->record_info) {
1212 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
1213 node_info.end_line = ctxt->input->line;
1214 node_info.node = cur;
1215 xmlParserAddNodeInfo(ctxt, &node_info);
1216 }
1217 ctxt->nodemem = -1;
1218
1219 if (ctxt->validate && ctxt->wellFormed &&
1220 ctxt->myDoc && ctxt->myDoc->intSubset)
1221 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
1222 cur);
1223
1224
1225 /*
1226 * end of parsing of this node.
1227 */
1228#ifdef DEBUG_SAX_TREE
1229 xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);
1230#endif
1231 nodePop(ctxt);
1232}
1233
1234/**
1235 * reference:
1236 * @ctx: the user data (XML parser context)
1237 * @name: The entity name
1238 *
1239 * called when an entity reference is detected.
1240 */
1241void
1242reference(void *ctx, const xmlChar *name)
1243{
1244 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1245 xmlNodePtr ret;
1246
1247#ifdef DEBUG_SAX
1248 xmlGenericError(xmlGenericErrorContext,
1249 "SAX.reference(%s)\n", name);
1250#endif
1251 if (name[0] == '#')
1252 ret = xmlNewCharRef(ctxt->myDoc, name);
1253 else
1254 ret = xmlNewReference(ctxt->myDoc, name);
1255#ifdef DEBUG_SAX_TREE
1256 xmlGenericError(xmlGenericErrorContext,
1257 "add reference %s to %s \n", name, ctxt->node->name);
1258#endif
1259 xmlAddChild(ctxt->node, ret);
1260}
1261
1262/**
1263 * characters:
1264 * @ctx: the user data (XML parser context)
1265 * @ch: a xmlChar string
1266 * @len: the number of xmlChar
1267 *
1268 * receiving some chars from the parser.
Owen Taylor3473f882001-02-23 17:55:21 +00001269 */
1270void
1271characters(void *ctx, const xmlChar *ch, int len)
1272{
1273 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1274 xmlNodePtr lastChild;
1275
1276#ifdef DEBUG_SAX
1277 xmlGenericError(xmlGenericErrorContext,
1278 "SAX.characters(%.30s, %d)\n", ch, len);
1279#endif
1280 /*
1281 * Handle the data if any. If there is no child
1282 * add it as content, otherwise if the last child is text,
1283 * concatenate it, else create a new node of type text.
1284 */
1285
1286 if (ctxt->node == NULL) {
1287#ifdef DEBUG_SAX_TREE
1288 xmlGenericError(xmlGenericErrorContext,
1289 "add chars: ctxt->node == NULL !\n");
1290#endif
1291 return;
1292 }
1293 lastChild = xmlGetLastChild(ctxt->node);
1294#ifdef DEBUG_SAX_TREE
1295 xmlGenericError(xmlGenericErrorContext,
1296 "add chars to %s \n", ctxt->node->name);
1297#endif
1298
1299 /*
1300 * Here we needed an accelerator mechanism in case of very large
1301 * elements. Use an attribute in the structure !!!
1302 */
1303 if (lastChild == NULL) {
1304 /* first node, first time */
1305 xmlNodeAddContentLen(ctxt->node, ch, len);
1306#ifndef XML_USE_BUFFER_CONTENT
1307 if (ctxt->node->children != NULL) {
1308 ctxt->nodelen = len;
1309 ctxt->nodemem = len + 1;
1310 }
1311#endif
1312 } else {
Daniel Veillardf300b7e2001-08-13 10:43:15 +00001313 int coalesceText = (lastChild != NULL) &&
1314 (lastChild->type == XML_TEXT_NODE) &&
1315 (lastChild->name == xmlStringText);
1316 if ((coalesceText) && (ctxt->nodemem != 0)) {
Owen Taylor3473f882001-02-23 17:55:21 +00001317#ifndef XML_USE_BUFFER_CONTENT
1318 /*
1319 * The whole point of maintaining nodelen and nodemem,
Daniel Veillard60087f32001-10-10 09:45:09 +00001320 * xmlTextConcat is too costly, i.e. compute length,
Owen Taylor3473f882001-02-23 17:55:21 +00001321 * reallocate a new buffer, move data, append ch. Here
1322 * We try to minimaze realloc() uses and avoid copying
Daniel Veillard60087f32001-10-10 09:45:09 +00001323 * and recomputing length over and over.
Owen Taylor3473f882001-02-23 17:55:21 +00001324 */
1325 if (ctxt->nodelen + len >= ctxt->nodemem) {
1326 xmlChar *newbuf;
1327 int size;
1328
1329 size = ctxt->nodemem + len;
1330 size *= 2;
1331 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
1332 if (newbuf == NULL) {
1333 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1334 ctxt->sax->error(ctxt->userData,
1335 "SAX.characters(): out of memory\n");
1336 return;
1337 }
1338 ctxt->nodemem = size;
1339 lastChild->content = newbuf;
1340 }
1341 memcpy(&lastChild->content[ctxt->nodelen], ch, len);
1342 ctxt->nodelen += len;
1343 lastChild->content[ctxt->nodelen] = 0;
1344#else
1345 xmlTextConcat(lastChild, ch, len);
1346#endif
Daniel Veillardf300b7e2001-08-13 10:43:15 +00001347 } else if (coalesceText) {
Daniel Veillard80f32572001-03-07 19:45:40 +00001348 xmlTextConcat(lastChild, ch, len);
1349 if (ctxt->node->children != NULL) {
1350 ctxt->nodelen = xmlStrlen(lastChild->content);
1351 ctxt->nodemem = ctxt->nodelen + 1;
1352 }
Owen Taylor3473f882001-02-23 17:55:21 +00001353 } else {
1354 /* Mixed content, first time */
1355 lastChild = xmlNewTextLen(ch, len);
1356 xmlAddChild(ctxt->node, lastChild);
1357#ifndef XML_USE_BUFFER_CONTENT
1358 if (ctxt->node->children != NULL) {
1359 ctxt->nodelen = len;
1360 ctxt->nodemem = len + 1;
1361 }
1362#endif
1363 }
1364 }
1365}
1366
1367/**
1368 * ignorableWhitespace:
1369 * @ctx: the user data (XML parser context)
1370 * @ch: a xmlChar string
1371 * @len: the number of xmlChar
1372 *
1373 * receiving some ignorable whitespaces from the parser.
Daniel Veillard05c13a22001-09-09 08:38:09 +00001374 * UNUSED: by default the DOM building will use characters
Owen Taylor3473f882001-02-23 17:55:21 +00001375 */
1376void
Daniel Veillardc86a4fa2001-03-26 16:28:29 +00001377ignorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
Owen Taylor3473f882001-02-23 17:55:21 +00001378{
1379 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
1380#ifdef DEBUG_SAX
1381 xmlGenericError(xmlGenericErrorContext,
1382 "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len);
1383#endif
1384}
1385
1386/**
1387 * processingInstruction:
1388 * @ctx: the user data (XML parser context)
1389 * @target: the target name
1390 * @data: the PI data's
1391 *
1392 * A processing instruction has been parsed.
1393 */
1394void
1395processingInstruction(void *ctx, const xmlChar *target,
1396 const xmlChar *data)
1397{
1398 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1399 xmlNodePtr ret;
1400 xmlNodePtr parent = ctxt->node;
1401
1402#ifdef DEBUG_SAX
1403 xmlGenericError(xmlGenericErrorContext,
1404 "SAX.processingInstruction(%s, %s)\n", target, data);
1405#endif
1406
1407 ret = xmlNewPI(target, data);
1408 if (ret == NULL) return;
1409 parent = ctxt->node;
1410
1411 if (ctxt->inSubset == 1) {
1412 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1413 return;
1414 } else if (ctxt->inSubset == 2) {
1415 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1416 return;
1417 }
1418 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
1419#ifdef DEBUG_SAX_TREE
1420 xmlGenericError(xmlGenericErrorContext,
1421 "Setting PI %s as root\n", target);
1422#endif
1423 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1424 return;
1425 }
1426 if (parent->type == XML_ELEMENT_NODE) {
1427#ifdef DEBUG_SAX_TREE
1428 xmlGenericError(xmlGenericErrorContext,
1429 "adding PI %s child to %s\n", target, parent->name);
1430#endif
1431 xmlAddChild(parent, ret);
1432 } else {
1433#ifdef DEBUG_SAX_TREE
1434 xmlGenericError(xmlGenericErrorContext,
1435 "adding PI %s sibling to ", target);
1436 xmlDebugDumpOneNode(stderr, parent, 0);
1437#endif
1438 xmlAddSibling(parent, ret);
1439 }
1440}
1441
1442/**
1443 * globalNamespace:
1444 * @ctx: the user data (XML parser context)
1445 * @href: the namespace associated URN
1446 * @prefix: the namespace prefix
1447 *
1448 * An old global namespace has been parsed.
1449 */
1450void
1451globalNamespace(void *ctx, const xmlChar *href, const xmlChar *prefix)
1452{
1453 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1454#ifdef DEBUG_SAX
1455 xmlGenericError(xmlGenericErrorContext,
1456 "SAX.globalNamespace(%s, %s)\n", href, prefix);
1457#endif
1458 xmlNewGlobalNs(ctxt->myDoc, href, prefix);
1459}
1460
1461/**
1462 * setNamespace:
1463 * @ctx: the user data (XML parser context)
1464 * @name: the namespace prefix
1465 *
1466 * Set the current element namespace.
1467 */
1468
1469void
1470setNamespace(void *ctx, const xmlChar *name)
1471{
1472 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1473 xmlNsPtr ns;
1474 xmlNodePtr parent;
1475
1476#ifdef DEBUG_SAX
1477 xmlGenericError(xmlGenericErrorContext, "SAX.setNamespace(%s)\n", name);
1478#endif
1479 ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name);
1480 if (ns == NULL) { /* ctxt->node may not have a parent yet ! */
1481 if (ctxt->nodeNr >= 2) {
1482 parent = ctxt->nodeTab[ctxt->nodeNr - 2];
1483 if (parent != NULL)
1484 ns = xmlSearchNs(ctxt->myDoc, parent, name);
1485 }
1486 }
1487 xmlSetNs(ctxt->node, ns);
1488}
1489
1490/**
1491 * getNamespace:
1492 * @ctx: the user data (XML parser context)
1493 *
1494 * Get the current element namespace.
1495 *
1496 * Returns the xmlNsPtr or NULL if none
1497 */
1498
1499xmlNsPtr
1500getNamespace(void *ctx)
1501{
1502 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1503 xmlNsPtr ret;
1504
1505#ifdef DEBUG_SAX
1506 xmlGenericError(xmlGenericErrorContext, "SAX.getNamespace()\n");
1507#endif
1508 ret = ctxt->node->ns;
1509 return(ret);
1510}
1511
1512/**
1513 * checkNamespace:
1514 * @ctx: the user data (XML parser context)
1515 * @namespace: the namespace to check against
1516 *
1517 * Check that the current element namespace is the same as the
1518 * one read upon parsing.
1519 *
1520 * Returns 1 if true 0 otherwise
1521 */
1522
1523int
1524checkNamespace(void *ctx, xmlChar *namespace)
1525{
1526 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1527 xmlNodePtr cur = ctxt->node;
1528
1529#ifdef DEBUG_SAX
1530 xmlGenericError(xmlGenericErrorContext,
1531 "SAX.checkNamespace(%s)\n", namespace);
1532#endif
1533
1534 /*
1535 * Check that the Name in the ETag is the same as in the STag.
1536 */
1537 if (namespace == NULL) {
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 for %s don't hold the namespace %s\n",
1542 cur->name, cur->ns->prefix);
1543 ctxt->wellFormed = 0;
1544 }
1545 } else {
1546 if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) {
1547 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1548 ctxt->sax->error(ctxt,
1549 "End tags %s holds a prefix %s not used by the open tag\n",
1550 cur->name, namespace);
1551 ctxt->wellFormed = 0;
1552 } else if (!xmlStrEqual(namespace, cur->ns->prefix)) {
1553 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1554 ctxt->sax->error(ctxt,
1555 "Start and End tags for %s don't use the same namespaces: %s and %s\n",
1556 cur->name, cur->ns->prefix, namespace);
1557 ctxt->wellFormed = 0;
1558 } else
1559 return(1);
1560 }
1561 return(0);
1562}
1563
1564/**
1565 * namespaceDecl:
1566 * @ctx: the user data (XML parser context)
1567 * @href: the namespace associated URN
1568 * @prefix: the namespace prefix
1569 *
1570 * A namespace has been parsed.
1571 */
1572void
1573namespaceDecl(void *ctx, const xmlChar *href, const xmlChar *prefix)
1574{
1575 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1576#ifdef DEBUG_SAX
1577 if (prefix == NULL)
1578 xmlGenericError(xmlGenericErrorContext,
1579 "SAX.namespaceDecl(%s, NULL)\n", href);
1580 else
1581 xmlGenericError(xmlGenericErrorContext,
1582 "SAX.namespaceDecl(%s, %s)\n", href, prefix);
1583#endif
1584 xmlNewNs(ctxt->node, href, prefix);
1585}
1586
1587/**
1588 * comment:
1589 * @ctx: the user data (XML parser context)
1590 * @value: the comment content
1591 *
1592 * A comment has been parsed.
1593 */
1594void
1595comment(void *ctx, const xmlChar *value)
1596{
1597 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1598 xmlNodePtr ret;
1599 xmlNodePtr parent = ctxt->node;
1600
1601#ifdef DEBUG_SAX
1602 xmlGenericError(xmlGenericErrorContext, "SAX.comment(%s)\n", value);
1603#endif
1604 ret = xmlNewDocComment(ctxt->myDoc, value);
1605 if (ret == NULL) return;
1606
1607 if (ctxt->inSubset == 1) {
1608 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1609 return;
1610 } else if (ctxt->inSubset == 2) {
1611 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1612 return;
1613 }
1614 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
1615#ifdef DEBUG_SAX_TREE
1616 xmlGenericError(xmlGenericErrorContext,
1617 "Setting comment as root\n");
1618#endif
1619 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1620 return;
1621 }
1622 if (parent->type == XML_ELEMENT_NODE) {
1623#ifdef DEBUG_SAX_TREE
1624 xmlGenericError(xmlGenericErrorContext,
1625 "adding comment child to %s\n", parent->name);
1626#endif
1627 xmlAddChild(parent, ret);
1628 } else {
1629#ifdef DEBUG_SAX_TREE
1630 xmlGenericError(xmlGenericErrorContext,
1631 "adding comment sibling to ");
1632 xmlDebugDumpOneNode(stderr, parent, 0);
1633#endif
1634 xmlAddSibling(parent, ret);
1635 }
1636}
1637
1638/**
1639 * cdataBlock:
1640 * @ctx: the user data (XML parser context)
1641 * @value: The pcdata content
1642 * @len: the block length
1643 *
1644 * called when a pcdata block has been parsed
1645 */
1646void
1647cdataBlock(void *ctx, const xmlChar *value, int len)
1648{
1649 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1650 xmlNodePtr ret, lastChild;
1651
1652#ifdef DEBUG_SAX
1653 xmlGenericError(xmlGenericErrorContext,
1654 "SAX.pcdata(%.10s, %d)\n", value, len);
1655#endif
1656 lastChild = xmlGetLastChild(ctxt->node);
1657#ifdef DEBUG_SAX_TREE
1658 xmlGenericError(xmlGenericErrorContext,
1659 "add chars to %s \n", ctxt->node->name);
1660#endif
1661 if ((lastChild != NULL) &&
1662 (lastChild->type == XML_CDATA_SECTION_NODE)) {
1663 xmlTextConcat(lastChild, value, len);
1664 } else {
1665 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
1666 xmlAddChild(ctxt->node, ret);
1667 }
1668}
1669
1670/*
1671 * Default handler for XML, builds the DOM tree
1672 */
1673xmlSAXHandler xmlDefaultSAXHandler = {
1674 internalSubset,
1675 isStandalone,
1676 hasInternalSubset,
1677 hasExternalSubset,
1678 resolveEntity,
1679 getEntity,
1680 entityDecl,
1681 notationDecl,
1682 attributeDecl,
1683 elementDecl,
1684 unparsedEntityDecl,
1685 setDocumentLocator,
1686 startDocument,
1687 endDocument,
1688 startElement,
1689 endElement,
1690 reference,
1691 characters,
Daniel Veillard05c13a22001-09-09 08:38:09 +00001692 characters,
Owen Taylor3473f882001-02-23 17:55:21 +00001693 processingInstruction,
1694 comment,
1695 xmlParserWarning,
1696 xmlParserError,
1697 xmlParserError,
1698 getParameterEntity,
1699 cdataBlock,
1700 externalSubset,
1701};
1702
1703/**
1704 * xmlDefaultSAXHandlerInit:
1705 *
1706 * Initialize the default SAX handler
1707 */
1708void
1709xmlDefaultSAXHandlerInit(void)
1710{
Daniel Veillard7583a592001-07-08 13:15:55 +00001711 static int xmlSAXInitialized = 0;
1712 if (xmlSAXInitialized)
1713 return;
1714
Owen Taylor3473f882001-02-23 17:55:21 +00001715 xmlDefaultSAXHandler.internalSubset = internalSubset;
1716 xmlDefaultSAXHandler.externalSubset = externalSubset;
1717 xmlDefaultSAXHandler.isStandalone = isStandalone;
1718 xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
1719 xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
1720 xmlDefaultSAXHandler.resolveEntity = resolveEntity;
1721 xmlDefaultSAXHandler.getEntity = getEntity;
1722 xmlDefaultSAXHandler.getParameterEntity = getParameterEntity;
1723 xmlDefaultSAXHandler.entityDecl = entityDecl;
1724 xmlDefaultSAXHandler.attributeDecl = attributeDecl;
1725 xmlDefaultSAXHandler.elementDecl = elementDecl;
1726 xmlDefaultSAXHandler.notationDecl = notationDecl;
1727 xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
1728 xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1729 xmlDefaultSAXHandler.startDocument = startDocument;
1730 xmlDefaultSAXHandler.endDocument = endDocument;
1731 xmlDefaultSAXHandler.startElement = startElement;
1732 xmlDefaultSAXHandler.endElement = endElement;
1733 xmlDefaultSAXHandler.reference = reference;
1734 xmlDefaultSAXHandler.characters = characters;
1735 xmlDefaultSAXHandler.cdataBlock = cdataBlock;
Daniel Veillard05c13a22001-09-09 08:38:09 +00001736 xmlDefaultSAXHandler.ignorableWhitespace = characters;
Owen Taylor3473f882001-02-23 17:55:21 +00001737 xmlDefaultSAXHandler.processingInstruction = processingInstruction;
1738 xmlDefaultSAXHandler.comment = comment;
1739 if (xmlGetWarningsDefaultValue == 0)
1740 xmlDefaultSAXHandler.warning = NULL;
1741 else
1742 xmlDefaultSAXHandler.warning = xmlParserWarning;
1743 xmlDefaultSAXHandler.error = xmlParserError;
1744 xmlDefaultSAXHandler.fatalError = xmlParserError;
Daniel Veillard7583a592001-07-08 13:15:55 +00001745
1746 xmlSAXInitialized = 1;
Owen Taylor3473f882001-02-23 17:55:21 +00001747}
1748
Daniel Veillardeae522a2001-04-23 13:41:34 +00001749#ifdef LIBXML_HTML_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00001750/*
1751 * Default handler for HTML, builds the DOM tree
1752 */
1753xmlSAXHandler htmlDefaultSAXHandler = {
1754 internalSubset,
1755 NULL,
1756 NULL,
1757 NULL,
1758 NULL,
1759 getEntity,
1760 NULL,
1761 NULL,
1762 NULL,
1763 NULL,
1764 NULL,
1765 setDocumentLocator,
1766 startDocument,
1767 endDocument,
1768 startElement,
1769 endElement,
1770 NULL,
1771 characters,
Daniel Veillardbce62332001-09-10 18:46:55 +00001772 ignorableWhitespace,
Owen Taylor3473f882001-02-23 17:55:21 +00001773 NULL,
1774 comment,
1775 xmlParserWarning,
1776 xmlParserError,
1777 xmlParserError,
1778 getParameterEntity,
1779 cdataBlock,
1780 NULL,
1781};
1782
1783/**
1784 * htmlDefaultSAXHandlerInit:
1785 *
1786 * Initialize the default SAX handler
1787 */
1788void
1789htmlDefaultSAXHandlerInit(void)
1790{
Daniel Veillard7583a592001-07-08 13:15:55 +00001791 static int htmlSAXInitialized = 0;
1792 if (htmlSAXInitialized)
1793 return;
1794
Owen Taylor3473f882001-02-23 17:55:21 +00001795 htmlDefaultSAXHandler.internalSubset = internalSubset;
1796 htmlDefaultSAXHandler.externalSubset = NULL;
1797 htmlDefaultSAXHandler.isStandalone = NULL;
1798 htmlDefaultSAXHandler.hasInternalSubset = NULL;
1799 htmlDefaultSAXHandler.hasExternalSubset = NULL;
1800 htmlDefaultSAXHandler.resolveEntity = NULL;
1801 htmlDefaultSAXHandler.getEntity = getEntity;
1802 htmlDefaultSAXHandler.getParameterEntity = NULL;
1803 htmlDefaultSAXHandler.entityDecl = NULL;
1804 htmlDefaultSAXHandler.attributeDecl = NULL;
1805 htmlDefaultSAXHandler.elementDecl = NULL;
1806 htmlDefaultSAXHandler.notationDecl = NULL;
1807 htmlDefaultSAXHandler.unparsedEntityDecl = NULL;
1808 htmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1809 htmlDefaultSAXHandler.startDocument = startDocument;
1810 htmlDefaultSAXHandler.endDocument = endDocument;
1811 htmlDefaultSAXHandler.startElement = startElement;
1812 htmlDefaultSAXHandler.endElement = endElement;
1813 htmlDefaultSAXHandler.reference = NULL;
1814 htmlDefaultSAXHandler.characters = characters;
1815 htmlDefaultSAXHandler.cdataBlock = cdataBlock;
1816 htmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1817 htmlDefaultSAXHandler.processingInstruction = NULL;
1818 htmlDefaultSAXHandler.comment = comment;
1819 htmlDefaultSAXHandler.warning = xmlParserWarning;
1820 htmlDefaultSAXHandler.error = xmlParserError;
1821 htmlDefaultSAXHandler.fatalError = xmlParserError;
Daniel Veillard7583a592001-07-08 13:15:55 +00001822
1823 htmlSAXInitialized = 1;
Owen Taylor3473f882001-02-23 17:55:21 +00001824}
Daniel Veillardeae522a2001-04-23 13:41:34 +00001825#endif /* LIBXML_HTML_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +00001826
Daniel Veillardeae522a2001-04-23 13:41:34 +00001827#ifdef LIBXML_DOCB_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00001828/*
Daniel Veillardeae522a2001-04-23 13:41:34 +00001829 * Default handler for SGML DocBook, builds the DOM tree
Owen Taylor3473f882001-02-23 17:55:21 +00001830 */
Daniel Veillardeae522a2001-04-23 13:41:34 +00001831xmlSAXHandler docbDefaultSAXHandler = {
Owen Taylor3473f882001-02-23 17:55:21 +00001832 internalSubset,
Daniel Veillard61b33d52001-04-24 13:55:12 +00001833 isStandalone,
1834 hasInternalSubset,
1835 hasExternalSubset,
1836 resolveEntity,
Owen Taylor3473f882001-02-23 17:55:21 +00001837 getEntity,
Daniel Veillard61b33d52001-04-24 13:55:12 +00001838 entityDecl,
Owen Taylor3473f882001-02-23 17:55:21 +00001839 NULL,
1840 NULL,
1841 NULL,
1842 NULL,
1843 setDocumentLocator,
1844 startDocument,
1845 endDocument,
1846 startElement,
1847 endElement,
Daniel Veillard1034da22001-04-25 19:06:28 +00001848 reference,
Owen Taylor3473f882001-02-23 17:55:21 +00001849 characters,
1850 ignorableWhitespace,
1851 NULL,
1852 comment,
1853 xmlParserWarning,
1854 xmlParserError,
1855 xmlParserError,
1856 getParameterEntity,
1857 NULL,
1858 NULL,
1859};
1860
1861/**
Daniel Veillardeae522a2001-04-23 13:41:34 +00001862 * docbDefaultSAXHandlerInit:
Owen Taylor3473f882001-02-23 17:55:21 +00001863 *
1864 * Initialize the default SAX handler
1865 */
1866void
Daniel Veillardeae522a2001-04-23 13:41:34 +00001867docbDefaultSAXHandlerInit(void)
Owen Taylor3473f882001-02-23 17:55:21 +00001868{
Daniel Veillard7583a592001-07-08 13:15:55 +00001869 static int docbSAXInitialized = 0;
1870 if (docbSAXInitialized)
1871 return;
1872
Daniel Veillardeae522a2001-04-23 13:41:34 +00001873 docbDefaultSAXHandler.internalSubset = internalSubset;
1874 docbDefaultSAXHandler.externalSubset = NULL;
Daniel Veillard61b33d52001-04-24 13:55:12 +00001875 docbDefaultSAXHandler.isStandalone = isStandalone;
1876 docbDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
1877 docbDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
1878 docbDefaultSAXHandler.resolveEntity = resolveEntity;
Daniel Veillardeae522a2001-04-23 13:41:34 +00001879 docbDefaultSAXHandler.getEntity = getEntity;
1880 docbDefaultSAXHandler.getParameterEntity = NULL;
Daniel Veillard61b33d52001-04-24 13:55:12 +00001881 docbDefaultSAXHandler.entityDecl = entityDecl;
Daniel Veillardeae522a2001-04-23 13:41:34 +00001882 docbDefaultSAXHandler.attributeDecl = NULL;
1883 docbDefaultSAXHandler.elementDecl = NULL;
1884 docbDefaultSAXHandler.notationDecl = NULL;
1885 docbDefaultSAXHandler.unparsedEntityDecl = NULL;
1886 docbDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1887 docbDefaultSAXHandler.startDocument = startDocument;
1888 docbDefaultSAXHandler.endDocument = endDocument;
1889 docbDefaultSAXHandler.startElement = startElement;
1890 docbDefaultSAXHandler.endElement = endElement;
Daniel Veillard1034da22001-04-25 19:06:28 +00001891 docbDefaultSAXHandler.reference = reference;
Daniel Veillardeae522a2001-04-23 13:41:34 +00001892 docbDefaultSAXHandler.characters = characters;
1893 docbDefaultSAXHandler.cdataBlock = NULL;
1894 docbDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1895 docbDefaultSAXHandler.processingInstruction = NULL;
1896 docbDefaultSAXHandler.comment = comment;
1897 docbDefaultSAXHandler.warning = xmlParserWarning;
1898 docbDefaultSAXHandler.error = xmlParserError;
1899 docbDefaultSAXHandler.fatalError = xmlParserError;
Daniel Veillard7583a592001-07-08 13:15:55 +00001900
1901 docbSAXInitialized = 1;
Owen Taylor3473f882001-02-23 17:55:21 +00001902}
Daniel Veillardeae522a2001-04-23 13:41:34 +00001903
1904#endif /* LIBXML_DOCB_ENABLED */