blob: 399eed439ee4b0fb500005291976c2cffc07e19b [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>
Daniel Veillard3c01b1d2001-10-17 15:58:35 +000026#include <libxml/globals.h>
Owen Taylor3473f882001-02-23 17:55:21 +000027
28/* #define DEBUG_SAX */
29/* #define DEBUG_SAX_TREE */
30
31/**
32 * getPublicId:
33 * @ctx: the user data (XML parser context)
34 *
35 * Return the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
36 *
37 * Returns a xmlChar *
38 */
39const xmlChar *
Daniel Veillardc86a4fa2001-03-26 16:28:29 +000040getPublicId(void *ctx ATTRIBUTE_UNUSED)
Owen Taylor3473f882001-02-23 17:55:21 +000041{
42 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
43 return(NULL);
44}
45
46/**
47 * getSystemId:
48 * @ctx: the user data (XML parser context)
49 *
50 * Return the system ID, basically URL or filename e.g.
51 * http://www.sgmlsource.com/dtds/memo.dtd
52 *
53 * Returns a xmlChar *
54 */
55const xmlChar *
56getSystemId(void *ctx)
57{
58 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard56a4cb82001-03-24 17:00:36 +000059 return((const xmlChar *) ctxt->input->filename);
Owen Taylor3473f882001-02-23 17:55:21 +000060}
61
62/**
63 * getLineNumber:
64 * @ctx: the user data (XML parser context)
65 *
66 * Return the line number of the current parsing point.
67 *
68 * Returns an int
69 */
70int
71getLineNumber(void *ctx)
72{
73 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
74 return(ctxt->input->line);
75}
76
77/**
78 * getColumnNumber:
79 * @ctx: the user data (XML parser context)
80 *
81 * Return the column number of the current parsing point.
82 *
83 * Returns an int
84 */
85int
86getColumnNumber(void *ctx)
87{
88 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
89 return(ctxt->input->col);
90}
91
Owen Taylor3473f882001-02-23 17:55:21 +000092/**
93 * isStandalone:
94 * @ctx: the user data (XML parser context)
95 *
96 * Is this document tagged standalone ?
97 *
98 * Returns 1 if true
99 */
100int
101isStandalone(void *ctx)
102{
103 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
104 return(ctxt->myDoc->standalone == 1);
105}
106
107/**
108 * hasInternalSubset:
109 * @ctx: the user data (XML parser context)
110 *
111 * Does this document has an internal subset
112 *
113 * Returns 1 if true
114 */
115int
116hasInternalSubset(void *ctx)
117{
118 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
119 return(ctxt->myDoc->intSubset != NULL);
120}
121
122/**
123 * hasExternalSubset:
124 * @ctx: the user data (XML parser context)
125 *
126 * Does this document has an external subset
127 *
128 * Returns 1 if true
129 */
130int
131hasExternalSubset(void *ctx)
132{
133 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
134 return(ctxt->myDoc->extSubset != NULL);
135}
136
137/**
138 * internalSubset:
139 * @ctx: the user data (XML parser context)
140 * @name: the root element name
141 * @ExternalID: the external ID
142 * @SystemID: the SYSTEM ID (e.g. filename or URL)
143 *
144 * Callback on internal subset declaration.
145 */
146void
147internalSubset(void *ctx, const xmlChar *name,
148 const xmlChar *ExternalID, const xmlChar *SystemID)
149{
150 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
151 xmlDtdPtr dtd;
152#ifdef DEBUG_SAX
153 xmlGenericError(xmlGenericErrorContext,
154 "SAX.internalSubset(%s, %s, %s)\n",
155 name, ExternalID, SystemID);
156#endif
157
158 if (ctxt->myDoc == NULL)
159 return;
160 dtd = xmlGetIntSubset(ctxt->myDoc);
161 if (dtd != NULL) {
162 if (ctxt->html)
163 return;
164 xmlUnlinkNode((xmlNodePtr) dtd);
165 xmlFreeDtd(dtd);
166 ctxt->myDoc->intSubset = NULL;
167 }
168 ctxt->myDoc->intSubset =
169 xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
170}
171
172/**
173 * externalSubset:
174 * @ctx: the user data (XML parser context)
175 * @name: the root element name
176 * @ExternalID: the external ID
177 * @SystemID: the SYSTEM ID (e.g. filename or URL)
178 *
179 * Callback on external subset declaration.
180 */
181void
182externalSubset(void *ctx, const xmlChar *name,
183 const xmlChar *ExternalID, const xmlChar *SystemID)
184{
185 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
186#ifdef DEBUG_SAX
187 xmlGenericError(xmlGenericErrorContext,
188 "SAX.externalSubset(%s, %s, %s)\n",
189 name, ExternalID, SystemID);
190#endif
191 if (((ExternalID != NULL) || (SystemID != NULL)) &&
Daniel Veillard9403a042001-05-28 11:00:53 +0000192 (((ctxt->validate) || (ctxt->loadsubset != 0)) &&
Owen Taylor3473f882001-02-23 17:55:21 +0000193 (ctxt->wellFormed && ctxt->myDoc))) {
194 /*
195 * Try to fetch and parse the external subset.
196 */
197 xmlParserInputPtr oldinput;
198 int oldinputNr;
199 int oldinputMax;
200 xmlParserInputPtr *oldinputTab;
Owen Taylor3473f882001-02-23 17:55:21 +0000201 xmlParserInputPtr input = NULL;
202 xmlCharEncoding enc;
203 int oldcharset;
204
205 /*
206 * Ask the Entity resolver to load the damn thing
207 */
208 if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
209 input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
210 SystemID);
211 if (input == NULL) {
212 return;
213 }
214
215 xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
216
217 /*
218 * make sure we won't destroy the main document context
219 */
220 oldinput = ctxt->input;
221 oldinputNr = ctxt->inputNr;
222 oldinputMax = ctxt->inputMax;
223 oldinputTab = ctxt->inputTab;
Owen Taylor3473f882001-02-23 17:55:21 +0000224 oldcharset = ctxt->charset;
225
226 ctxt->inputTab = (xmlParserInputPtr *)
227 xmlMalloc(5 * sizeof(xmlParserInputPtr));
228 if (ctxt->inputTab == NULL) {
229 ctxt->errNo = XML_ERR_NO_MEMORY;
230 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
231 ctxt->sax->error(ctxt->userData,
232 "externalSubset: out of memory\n");
233 ctxt->errNo = XML_ERR_NO_MEMORY;
234 ctxt->input = oldinput;
235 ctxt->inputNr = oldinputNr;
236 ctxt->inputMax = oldinputMax;
237 ctxt->inputTab = oldinputTab;
238 ctxt->charset = oldcharset;
239 return;
240 }
241 ctxt->inputNr = 0;
242 ctxt->inputMax = 5;
243 ctxt->input = NULL;
244 xmlPushInput(ctxt, input);
245
246 /*
247 * On the fly encoding conversion if needed
248 */
249 enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
250 xmlSwitchEncoding(ctxt, enc);
251
252 if (input->filename == NULL)
253 input->filename = (char *) xmlStrdup(SystemID);
254 input->line = 1;
255 input->col = 1;
256 input->base = ctxt->input->cur;
257 input->cur = ctxt->input->cur;
258 input->free = NULL;
259
260 /*
261 * let's parse that entity knowing it's an external subset.
262 */
263 xmlParseExternalSubset(ctxt, ExternalID, SystemID);
264
265 /*
266 * Free up the external entities
267 */
268
269 while (ctxt->inputNr > 1)
270 xmlPopInput(ctxt);
271 xmlFreeInputStream(ctxt->input);
272 xmlFree(ctxt->inputTab);
273
274 /*
275 * Restore the parsing context of the main entity
276 */
277 ctxt->input = oldinput;
278 ctxt->inputNr = oldinputNr;
279 ctxt->inputMax = oldinputMax;
280 ctxt->inputTab = oldinputTab;
281 ctxt->charset = oldcharset;
282 /* ctxt->wellFormed = oldwellFormed; */
283 }
284}
285
286/**
287 * resolveEntity:
288 * @ctx: the user data (XML parser context)
289 * @publicId: The public ID of the entity
290 * @systemId: The system ID of the entity
291 *
292 * The entity loader, to control the loading of external entities,
293 * the application can either:
294 * - override this resolveEntity() callback in the SAX block
295 * - or better use the xmlSetExternalEntityLoader() function to
296 * set up it's own entity resolution routine
297 *
298 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
299 */
300xmlParserInputPtr
301resolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
302{
303 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
304 xmlParserInputPtr ret;
305 xmlChar *URI;
306 const char *base = NULL;
307
308 if (ctxt->input != NULL)
309 base = ctxt->input->filename;
310 if (base == NULL)
311 base = ctxt->directory;
312
313 URI = xmlBuildURI(systemId, (const xmlChar *) base);
314
315#ifdef DEBUG_SAX
316 xmlGenericError(xmlGenericErrorContext,
317 "SAX.resolveEntity(%s, %s)\n", publicId, systemId);
318#endif
319
320 ret = xmlLoadExternalEntity((const char *) URI,
321 (const char *) publicId, ctxt);
322 if (URI != NULL)
323 xmlFree(URI);
324 return(ret);
325}
326
327/**
328 * getEntity:
329 * @ctx: the user data (XML parser context)
330 * @name: The entity name
331 *
332 * Get an entity by name
333 *
334 * Returns the xmlEntityPtr if found.
335 */
336xmlEntityPtr
337getEntity(void *ctx, const xmlChar *name)
338{
339 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
340 xmlEntityPtr ret;
341
342#ifdef DEBUG_SAX
343 xmlGenericError(xmlGenericErrorContext,
344 "SAX.getEntity(%s)\n", name);
345#endif
346
347 ret = xmlGetDocEntity(ctxt->myDoc, name);
348 if ((ret != NULL) && (ctxt->validate) && (ret->children == NULL) &&
349 (ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
350 /*
351 * for validation purposes we really need to fetch and
352 * parse the external entity
353 */
Owen Taylor3473f882001-02-23 17:55:21 +0000354 xmlNodePtr children;
355
Daniel Veillard5015b712001-08-17 09:37:52 +0000356 xmlParseCtxtExternalEntity(ctxt, ret->URI, ret->ExternalID, &children);
Owen Taylor3473f882001-02-23 17:55:21 +0000357 xmlAddChildList((xmlNodePtr) ret, children);
358 }
359 return(ret);
360}
361
362/**
363 * getParameterEntity:
364 * @ctx: the user data (XML parser context)
365 * @name: The entity name
366 *
367 * Get a parameter entity by name
368 *
369 * Returns the xmlEntityPtr if found.
370 */
371xmlEntityPtr
372getParameterEntity(void *ctx, const xmlChar *name)
373{
374 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
375 xmlEntityPtr ret;
376
377#ifdef DEBUG_SAX
378 xmlGenericError(xmlGenericErrorContext,
379 "SAX.getParameterEntity(%s)\n", name);
380#endif
381
382 ret = xmlGetParameterEntity(ctxt->myDoc, name);
383 return(ret);
384}
385
386
387/**
388 * entityDecl:
389 * @ctx: the user data (XML parser context)
390 * @name: the entity name
391 * @type: the entity type
392 * @publicId: The public ID of the entity
393 * @systemId: The system ID of the entity
394 * @content: the entity value (without processing).
395 *
396 * An entity definition has been parsed
397 */
398void
399entityDecl(void *ctx, const xmlChar *name, int type,
400 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
401{
402 xmlEntityPtr ent;
403 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
404
405#ifdef DEBUG_SAX
406 xmlGenericError(xmlGenericErrorContext,
407 "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
408 name, type, publicId, systemId, content);
409#endif
410 if (ctxt->inSubset == 1) {
411 ent = xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
412 systemId, content);
413 if ((ent == NULL) && (ctxt->pedantic) &&
414 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
415 ctxt->sax->warning(ctxt,
416 "Entity(%s) already defined in the internal subset\n", name);
417 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
418 xmlChar *URI;
419 const char *base = NULL;
420
421 if (ctxt->input != NULL)
422 base = ctxt->input->filename;
423 if (base == NULL)
424 base = ctxt->directory;
425
426 URI = xmlBuildURI(systemId, (const xmlChar *) base);
427 ent->URI = URI;
428 }
429 } else if (ctxt->inSubset == 2) {
430 ent = xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
431 systemId, content);
432 if ((ent == NULL) && (ctxt->pedantic) &&
433 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
434 ctxt->sax->warning(ctxt,
435 "Entity(%s) already defined in the external subset\n", name);
436 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
437 xmlChar *URI;
438 const char *base = NULL;
439
440 if (ctxt->input != NULL)
441 base = ctxt->input->filename;
442 if (base == NULL)
443 base = ctxt->directory;
444
445 URI = xmlBuildURI(systemId, (const xmlChar *) base);
446 ent->URI = URI;
447 }
448 } else {
449 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
450 ctxt->sax->error(ctxt,
451 "SAX.entityDecl(%s) called while not in subset\n", name);
452 }
453}
454
455/**
456 * attributeDecl:
457 * @ctx: the user data (XML parser context)
458 * @elem: the name of the element
459 * @fullname: the attribute name
460 * @type: the attribute type
461 * @def: the type of default value
462 * @defaultValue: the attribute default value
463 * @tree: the tree of enumerated value set
464 *
465 * An attribute definition has been parsed
466 */
467void
468attributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
469 int type, int def, const xmlChar *defaultValue,
470 xmlEnumerationPtr tree)
471{
472 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
473 xmlAttributePtr attr;
474 xmlChar *name = NULL, *prefix = NULL;
475
476#ifdef DEBUG_SAX
477 xmlGenericError(xmlGenericErrorContext,
478 "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
479 elem, fullname, type, def, defaultValue);
480#endif
481 name = xmlSplitQName(ctxt, fullname, &prefix);
482 if (ctxt->inSubset == 1)
483 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
484 name, prefix, (xmlAttributeType) type,
485 (xmlAttributeDefault) def, defaultValue, tree);
486 else if (ctxt->inSubset == 2)
487 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
488 name, prefix, (xmlAttributeType) type,
489 (xmlAttributeDefault) def, defaultValue, tree);
490 else {
491 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
492 ctxt->sax->error(ctxt,
493 "SAX.attributeDecl(%s) called while not in subset\n", name);
494 return;
495 }
496 if (attr == 0) ctxt->valid = 0;
497 if (ctxt->validate && ctxt->wellFormed &&
498 ctxt->myDoc && ctxt->myDoc->intSubset)
499 ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
500 attr);
501 if (prefix != NULL)
502 xmlFree(prefix);
503 if (name != NULL)
504 xmlFree(name);
505}
506
507/**
508 * elementDecl:
509 * @ctx: the user data (XML parser context)
510 * @name: the element name
511 * @type: the element type
512 * @content: the element value tree
513 *
514 * An element definition has been parsed
515 */
516void
Daniel Veillard1fd36d22001-07-04 22:54:28 +0000517elementDecl(void *ctx, const xmlChar * name, int type,
518 xmlElementContentPtr content)
Owen Taylor3473f882001-02-23 17:55:21 +0000519{
520 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
521 xmlElementPtr elem = NULL;
522
523#ifdef DEBUG_SAX
524 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard1fd36d22001-07-04 22:54:28 +0000525 "SAX.elementDecl(%s, %d, ...)\n", name, type);
Owen Taylor3473f882001-02-23 17:55:21 +0000526#endif
Daniel Veillard1fd36d22001-07-04 22:54:28 +0000527
Owen Taylor3473f882001-02-23 17:55:21 +0000528 if (ctxt->inSubset == 1)
Daniel Veillard1fd36d22001-07-04 22:54:28 +0000529 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
530 name, (xmlElementTypeVal) type, content);
Owen Taylor3473f882001-02-23 17:55:21 +0000531 else if (ctxt->inSubset == 2)
Daniel Veillard1fd36d22001-07-04 22:54:28 +0000532 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
533 name, (xmlElementTypeVal) type, content);
Owen Taylor3473f882001-02-23 17:55:21 +0000534 else {
Daniel Veillard1fd36d22001-07-04 22:54:28 +0000535 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
536 ctxt->sax->error(ctxt,
537 "SAX.elementDecl(%s) called while not in subset\n",
538 name);
539 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000540 }
Daniel Veillard1fd36d22001-07-04 22:54:28 +0000541 if (elem == NULL)
542 ctxt->valid = 0;
Owen Taylor3473f882001-02-23 17:55:21 +0000543 if (ctxt->validate && ctxt->wellFormed &&
544 ctxt->myDoc && ctxt->myDoc->intSubset)
Daniel Veillard1fd36d22001-07-04 22:54:28 +0000545 ctxt->valid &=
546 xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
Owen Taylor3473f882001-02-23 17:55:21 +0000547}
548
549/**
550 * notationDecl:
551 * @ctx: the user data (XML parser context)
552 * @name: The name of the notation
553 * @publicId: The public ID of the entity
554 * @systemId: The system ID of the entity
555 *
556 * What to do when a notation declaration has been parsed.
557 */
558void
559notationDecl(void *ctx, const xmlChar *name,
560 const xmlChar *publicId, const xmlChar *systemId)
561{
562 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
563 xmlNotationPtr nota = NULL;
564
565#ifdef DEBUG_SAX
566 xmlGenericError(xmlGenericErrorContext,
567 "SAX.notationDecl(%s, %s, %s)\n", name, publicId, systemId);
568#endif
569
570 if (ctxt->inSubset == 1)
571 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
572 publicId, systemId);
573 else if (ctxt->inSubset == 2)
Daniel Veillard25239c12001-03-14 13:56:48 +0000574 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, name,
Owen Taylor3473f882001-02-23 17:55:21 +0000575 publicId, systemId);
576 else {
577 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
578 ctxt->sax->error(ctxt,
579 "SAX.notationDecl(%s) called while not in subset\n", name);
580 return;
581 }
582 if (nota == NULL) ctxt->valid = 0;
583 if (ctxt->validate && ctxt->wellFormed &&
584 ctxt->myDoc && ctxt->myDoc->intSubset)
585 ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
586 nota);
587}
588
589/**
590 * unparsedEntityDecl:
591 * @ctx: the user data (XML parser context)
592 * @name: The name of the entity
593 * @publicId: The public ID of the entity
594 * @systemId: The system ID of the entity
595 * @notationName: the name of the notation
596 *
597 * What to do when an unparsed entity declaration is parsed
598 */
599void
600unparsedEntityDecl(void *ctx, const xmlChar *name,
601 const xmlChar *publicId, const xmlChar *systemId,
602 const xmlChar *notationName)
603{
Daniel Veillard9f4eb912001-08-01 21:22:27 +0000604 xmlEntityPtr ent;
Owen Taylor3473f882001-02-23 17:55:21 +0000605 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
606#ifdef DEBUG_SAX
607 xmlGenericError(xmlGenericErrorContext,
608 "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
609 name, publicId, systemId, notationName);
610#endif
611 if (ctxt->validate && ctxt->wellFormed &&
Daniel Veillarde020c3a2001-03-21 18:06:15 +0000612 ctxt->myDoc && ctxt->myDoc->extSubset)
Owen Taylor3473f882001-02-23 17:55:21 +0000613 ctxt->valid &= xmlValidateNotationUse(&ctxt->vctxt, ctxt->myDoc,
614 notationName);
Daniel Veillard9f4eb912001-08-01 21:22:27 +0000615 if (ctxt->inSubset == 1) {
616 ent = xmlAddDocEntity(ctxt->myDoc, name,
Daniel Veillarde020c3a2001-03-21 18:06:15 +0000617 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
618 publicId, systemId, notationName);
Daniel Veillard9f4eb912001-08-01 21:22:27 +0000619 if ((ent == NULL) && (ctxt->pedantic) &&
620 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
621 ctxt->sax->warning(ctxt,
622 "Entity(%s) already defined in the internal subset\n", name);
623 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
624 xmlChar *URI;
625 const char *base = NULL;
626
627 if (ctxt->input != NULL)
628 base = ctxt->input->filename;
629 if (base == NULL)
630 base = ctxt->directory;
631
632 URI = xmlBuildURI(systemId, (const xmlChar *) base);
633 ent->URI = URI;
634 }
635 } else if (ctxt->inSubset == 2) {
636 ent = xmlAddDtdEntity(ctxt->myDoc, name,
Daniel Veillarde020c3a2001-03-21 18:06:15 +0000637 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
638 publicId, systemId, notationName);
Daniel Veillard9f4eb912001-08-01 21:22:27 +0000639 if ((ent == NULL) && (ctxt->pedantic) &&
640 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
641 ctxt->sax->warning(ctxt,
642 "Entity(%s) already defined in the external subset\n", name);
643 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
644 xmlChar *URI;
645 const char *base = NULL;
646
647 if (ctxt->input != NULL)
648 base = ctxt->input->filename;
649 if (base == NULL)
650 base = ctxt->directory;
651
652 URI = xmlBuildURI(systemId, (const xmlChar *) base);
653 ent->URI = URI;
654 }
655 } else {
Daniel Veillarde020c3a2001-03-21 18:06:15 +0000656 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
657 ctxt->sax->error(ctxt,
658 "SAX.unparsedEntityDecl(%s) called while not in subset\n", name);
659 }
Owen Taylor3473f882001-02-23 17:55:21 +0000660}
661
662/**
663 * setDocumentLocator:
664 * @ctx: the user data (XML parser context)
665 * @loc: A SAX Locator
666 *
667 * Receive the document locator at startup, actually xmlDefaultSAXLocator
668 * Everything is available on the context, so this is useless in our case.
669 */
670void
Daniel Veillardc86a4fa2001-03-26 16:28:29 +0000671setDocumentLocator(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
Owen Taylor3473f882001-02-23 17:55:21 +0000672{
673 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
674#ifdef DEBUG_SAX
675 xmlGenericError(xmlGenericErrorContext,
676 "SAX.setDocumentLocator()\n");
677#endif
678}
679
680/**
681 * startDocument:
682 * @ctx: the user data (XML parser context)
683 *
684 * called when the document start being processed.
685 */
686void
687startDocument(void *ctx)
688{
689 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
690 xmlDocPtr doc;
691
692#ifdef DEBUG_SAX
693 xmlGenericError(xmlGenericErrorContext,
694 "SAX.startDocument()\n");
695#endif
696 if (ctxt->html) {
697 if (ctxt->myDoc == NULL)
698#ifdef LIBXML_HTML_ENABLED
699 ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
700#else
701 xmlGenericError(xmlGenericErrorContext,
702 "libxml2 built without HTML support\n");
703#endif
704 } else {
705 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
706 if (doc != NULL) {
707 if (ctxt->encoding != NULL)
708 doc->encoding = xmlStrdup(ctxt->encoding);
709 else
710 doc->encoding = NULL;
711 doc->standalone = ctxt->standalone;
712 }
713 }
714 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
715 (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000716 ctxt->myDoc->URL = xmlStrdup((const xmlChar *) ctxt->input->filename);
Owen Taylor3473f882001-02-23 17:55:21 +0000717 }
718}
719
720/**
721 * endDocument:
722 * @ctx: the user data (XML parser context)
723 *
724 * called when the document end has been detected.
725 */
726void
727endDocument(void *ctx)
728{
729 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
730#ifdef DEBUG_SAX
731 xmlGenericError(xmlGenericErrorContext,
732 "SAX.endDocument()\n");
733#endif
734 if (ctxt->validate && ctxt->wellFormed &&
735 ctxt->myDoc && ctxt->myDoc->intSubset)
736 ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
737
738 /*
739 * Grab the encoding if it was added on-the-fly
740 */
741 if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
742 (ctxt->myDoc->encoding == NULL)) {
743 ctxt->myDoc->encoding = ctxt->encoding;
744 ctxt->encoding = NULL;
745 }
746 if ((ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
747 (ctxt->myDoc->encoding == NULL)) {
748 ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
749 }
750 if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
751 (ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
752 ctxt->myDoc->charset = ctxt->charset;
753 }
754}
755
756/**
757 * attribute:
758 * @ctx: the user data (XML parser context)
759 * @fullname: The attribute name, including namespace prefix
760 * @value: The attribute value
761 *
762 * Handle an attribute that has been read by the parser.
763 * The default handling is to convert the attribute into an
764 * DOM subtree and past it in a new xmlAttr element added to
765 * the element.
766 */
767void
768attribute(void *ctx, const xmlChar *fullname, const xmlChar *value)
769{
770 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
771 xmlAttrPtr ret;
772 xmlChar *name;
773 xmlChar *ns;
774 xmlChar *nval;
775 xmlNsPtr namespace;
776
777/****************
778#ifdef DEBUG_SAX
779 xmlGenericError(xmlGenericErrorContext,
780 "SAX.attribute(%s, %s)\n", fullname, value);
781#endif
782 ****************/
783 /*
784 * Split the full name into a namespace prefix and the tag name
785 */
786 name = xmlSplitQName(ctxt, fullname, &ns);
787
788 /*
789 * Do the last stage of the attribute normalization
790 * Needed for HTML too:
791 * http://www.w3.org/TR/html4/types.html#h-6.2
792 */
793 nval = xmlValidNormalizeAttributeValue(ctxt->myDoc, ctxt->node,
794 fullname, value);
795 if (nval != NULL)
796 value = nval;
797
798 /*
799 * Check whether it's a namespace definition
800 */
801 if ((!ctxt->html) && (ns == NULL) &&
802 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
803 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
804 if (value[0] != 0) {
805 xmlURIPtr uri;
806
807 uri = xmlParseURI((const char *)value);
808 if (uri == NULL) {
809 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
810 ctxt->sax->warning(ctxt->userData,
811 "nmlns: %s not a valid URI\n", value);
812 } else {
813 if (uri->scheme == NULL) {
814 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
815 ctxt->sax->warning(ctxt->userData,
816 "nmlns: URI %s is not absolute\n", value);
817 }
818 xmlFreeURI(uri);
819 }
820 }
821
822 /* a default namespace definition */
823 xmlNewNs(ctxt->node, value, NULL);
824 if (name != NULL)
825 xmlFree(name);
826 if (nval != NULL)
827 xmlFree(nval);
828 return;
829 }
830 if ((!ctxt->html) &&
831 (ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
832 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
833 /*
834 * Validate also for namespace decls, they are attributes from
835 * an XML-1.0 perspective
836 TODO ... doesn't map well with current API
837 if (ctxt->validate && ctxt->wellFormed &&
838 ctxt->myDoc && ctxt->myDoc->intSubset)
839 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
840 ctxt->node, ret, value);
841 */
842 /* a standard namespace definition */
843 xmlNewNs(ctxt->node, value, name);
844 xmlFree(ns);
845 if (name != NULL)
846 xmlFree(name);
847 if (nval != NULL)
848 xmlFree(nval);
849 return;
850 }
851
852 if (ns != NULL)
853 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
854 else {
855 namespace = NULL;
856 }
857
858 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
859 ret = xmlNewNsProp(ctxt->node, namespace, name, NULL);
860
861 if (ret != NULL) {
862 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
863 xmlNodePtr tmp;
864
865 ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
866 tmp = ret->children;
867 while (tmp != NULL) {
868 tmp->parent = (xmlNodePtr) ret;
869 if (tmp->next == NULL)
870 ret->last = tmp;
871 tmp = tmp->next;
872 }
873 } else if (value != NULL) {
874 ret->children = xmlNewDocText(ctxt->myDoc, value);
875 ret->last = ret->children;
876 if (ret->children != NULL)
877 ret->children->parent = (xmlNodePtr) ret;
878 }
879 }
880
881 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
882 ctxt->myDoc && ctxt->myDoc->intSubset) {
883
884 /*
885 * If we don't substitute entities, the validation should be
886 * done on a value with replaced entities anyway.
887 */
888 if (!ctxt->replaceEntities) {
889 xmlChar *val;
890
891 ctxt->depth++;
892 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
893 0,0,0);
894 ctxt->depth--;
895 if (val == NULL)
896 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
897 ctxt->myDoc, ctxt->node, ret, value);
898 else {
899 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
900 ctxt->myDoc, ctxt->node, ret, val);
901 xmlFree(val);
902 }
903 } else {
904 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
905 ctxt->node, ret, value);
906 }
Daniel Veillard62f313b2001-07-04 19:49:14 +0000907 } else if (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
908 ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0))) {
Owen Taylor3473f882001-02-23 17:55:21 +0000909 /*
910 * when validating, the ID registration is done at the attribute
911 * validation level. Otherwise we have to do specific handling here.
912 */
913 if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
914 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
915 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
916 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
917 }
918
919 if (nval != NULL)
920 xmlFree(nval);
921 if (name != NULL)
922 xmlFree(name);
923 if (ns != NULL)
924 xmlFree(ns);
925}
926
927/**
928 * startElement:
929 * @ctx: the user data (XML parser context)
930 * @fullname: The element name, including namespace prefix
931 * @atts: An array of name/value attributes pairs, NULL terminated
932 *
933 * called when an opening tag has been processed.
934 */
935void
936startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
937{
938 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
939 xmlNodePtr ret;
940 xmlNodePtr parent = ctxt->node;
941 xmlNsPtr ns;
942 xmlChar *name;
943 xmlChar *prefix;
944 const xmlChar *att;
945 const xmlChar *value;
946 int i;
947
948#ifdef DEBUG_SAX
949 xmlGenericError(xmlGenericErrorContext,
950 "SAX.startElement(%s)\n", fullname);
951#endif
952
953 /*
954 * First check on validity:
955 */
956 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
957 ((ctxt->myDoc->intSubset == NULL) ||
958 ((ctxt->myDoc->intSubset->notations == NULL) &&
959 (ctxt->myDoc->intSubset->elements == NULL) &&
960 (ctxt->myDoc->intSubset->attributes == NULL) &&
961 (ctxt->myDoc->intSubset->entities == NULL)))) {
962 if (ctxt->vctxt.error != NULL) {
963 ctxt->vctxt.error(ctxt->vctxt.userData,
964 "Validation failed: no DTD found !\n");
965 }
966 ctxt->validate = 0;
Daniel Veillard7a51d6d2001-09-10 14:40:43 +0000967 ctxt->valid = 0;
968 ctxt->errNo = XML_ERR_NO_DTD;
Owen Taylor3473f882001-02-23 17:55:21 +0000969 }
970
971
972 /*
973 * Split the full name into a namespace prefix and the tag name
974 */
975 name = xmlSplitQName(ctxt, fullname, &prefix);
976
977
978 /*
979 * Note : the namespace resolution is deferred until the end of the
980 * attributes parsing, since local namespace can be defined as
981 * an attribute at this level.
982 */
983 ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL);
984 if (ret == NULL) return;
985 if (ctxt->myDoc->children == NULL) {
986#ifdef DEBUG_SAX_TREE
987 xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
988#endif
989 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
990 } else if (parent == NULL) {
991 parent = ctxt->myDoc->children;
992 }
993 ctxt->nodemem = -1;
Daniel Veillardd9bad132001-07-23 19:39:43 +0000994 if (ctxt->linenumbers) {
995 if (ctxt->input != NULL)
996 ret->content = (void *) (long) ctxt->input->line;
997 }
Owen Taylor3473f882001-02-23 17:55:21 +0000998
999 /*
1000 * We are parsing a new node.
1001 */
1002#ifdef DEBUG_SAX_TREE
1003 xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);
1004#endif
1005 nodePush(ctxt, ret);
1006
1007 /*
1008 * Link the child element
1009 */
1010 if (parent != NULL) {
1011 if (parent->type == XML_ELEMENT_NODE) {
1012#ifdef DEBUG_SAX_TREE
1013 xmlGenericError(xmlGenericErrorContext,
1014 "adding child %s to %s\n", name, parent->name);
1015#endif
1016 xmlAddChild(parent, ret);
1017 } else {
1018#ifdef DEBUG_SAX_TREE
1019 xmlGenericError(xmlGenericErrorContext,
1020 "adding sibling %s to ", name);
1021 xmlDebugDumpOneNode(stderr, parent, 0);
1022#endif
1023 xmlAddSibling(parent, ret);
1024 }
1025 }
1026
1027 /*
Daniel Veillard48da9102001-08-07 01:10:10 +00001028 * Insert all the defaulted attributes from the DTD especially namespaces
1029 */
1030 if ((!ctxt->html) &&
1031 ((ctxt->myDoc->intSubset != NULL) ||
1032 (ctxt->myDoc->extSubset != NULL))) {
1033 xmlElementPtr elemDecl = NULL;
1034
1035 if (prefix != NULL) {
1036 if (ctxt->myDoc->intSubset != NULL)
1037 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset,
1038 name, prefix);
1039 if ((elemDecl == NULL) && (ctxt->myDoc->extSubset != NULL))
1040 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset,
1041 name, prefix);
1042 } else {
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 }
1050 if (elemDecl != NULL) {
1051 xmlAttributePtr attr = elemDecl->attributes;
1052 while (attr != NULL) {
1053 if (attr->defaultValue != NULL) {
1054 /*
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001055 * the element should be instantiated in the tree if:
Daniel Veillard48da9102001-08-07 01:10:10 +00001056 * - this is a namespace prefix
1057 * - the user required for completion in the tree
1058 * like XSLT
1059 */
1060 if (((attr->prefix != NULL) &&
1061 (xmlStrEqual(attr->prefix, BAD_CAST "xmlns"))) ||
1062 ((attr->prefix == NULL) &&
1063 (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) ||
1064 (ctxt->loadsubset & XML_COMPLETE_ATTRS)) {
Daniel Veillard963d2ae2002-01-20 22:08:18 +00001065 xmlChar *fulln;
Daniel Veillard48da9102001-08-07 01:10:10 +00001066
1067 if (attr->prefix != NULL) {
Daniel Veillard963d2ae2002-01-20 22:08:18 +00001068 fulln = xmlStrdup(attr->prefix);
1069 fulln = xmlStrcat(fulln, BAD_CAST ":");
1070 fulln = xmlStrcat(fulln, attr->name);
1071 } else {
1072 fulln = xmlStrdup(attr->name);
Daniel Veillard48da9102001-08-07 01:10:10 +00001073 }
1074
1075 /*
1076 * Check that the attribute is not declared in the
1077 * serialization
1078 */
1079 att = NULL;
1080 if (atts != NULL) {
1081 i = 0;
1082 att = atts[i];
1083 while (att != NULL) {
1084 if (xmlStrEqual(att, fulln))
1085 break;
1086 i += 2;
1087 att = atts[i];
1088 }
1089 }
1090 if (att == NULL)
1091 attribute(ctxt, fulln, attr->defaultValue);
Daniel Veillard963d2ae2002-01-20 22:08:18 +00001092 xmlFree(fulln);
Daniel Veillard48da9102001-08-07 01:10:10 +00001093 }
1094 }
1095 attr = attr->nexth;
1096 }
1097 }
1098 }
1099
1100 /*
Owen Taylor3473f882001-02-23 17:55:21 +00001101 * process all the attributes whose name start with "xml"
1102 */
1103 if (atts != NULL) {
1104 i = 0;
1105 att = atts[i++];
1106 value = atts[i++];
1107 if (!ctxt->html) {
1108 while ((att != NULL) && (value != NULL)) {
1109 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l'))
1110 attribute(ctxt, att, value);
1111
1112 att = atts[i++];
1113 value = atts[i++];
1114 }
1115 }
1116 }
1117
1118 /*
1119 * Search the namespace, note that since the attributes have been
1120 * processed, the local namespaces are available.
1121 */
1122 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
1123 if ((ns == NULL) && (parent != NULL))
1124 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
1125 if ((prefix != NULL) && (ns == NULL)) {
1126 ns = xmlNewNs(ret, NULL, prefix);
1127 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1128 ctxt->sax->warning(ctxt->userData,
1129 "Namespace prefix %s is not defined\n", prefix);
1130 }
Daniel Veillard143b04f2001-09-10 18:14:14 +00001131
1132 /*
1133 * set the namespace node, making sure that if the default namspace
1134 * is unbound on a parent we simply kee it NULL
1135 */
Daniel Veillard651f9472001-10-04 14:51:06 +00001136 if ((ns != NULL) && (ns->href != NULL) && (ns->href[0] != 0))
Daniel Veillard143b04f2001-09-10 18:14:14 +00001137 xmlSetNs(ret, ns);
Owen Taylor3473f882001-02-23 17:55:21 +00001138
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 /*
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001167 * If it's the Document root, finish the DTD validation and
Owen Taylor3473f882001-02-23 17:55:21 +00001168 * 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,
Daniel Veillard60087f32001-10-10 09:45:09 +00001314 * xmlTextConcat is too costly, i.e. compute length,
Owen Taylor3473f882001-02-23 17:55:21 +00001315 * reallocate a new buffer, move data, append ch. Here
1316 * We try to minimaze realloc() uses and avoid copying
Daniel Veillard60087f32001-10-10 09:45:09 +00001317 * and recomputing length over and over.
Owen Taylor3473f882001-02-23 17:55:21 +00001318 */
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
Daniel Veillardd0463562001-10-13 09:15:48 +00001664/**
Daniel Veillard9d06d302002-01-22 18:15:52 +00001665 * initxmlDefaultSAXHandler:
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001666 * @hdlr: the SAX handler
1667 * @warning: flag if non-zero sets the handler warning procedure
Daniel Veillardd0463562001-10-13 09:15:48 +00001668 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001669 * Initialize the default XML SAX handler
Owen Taylor3473f882001-02-23 17:55:21 +00001670 */
Daniel Veillardd0463562001-10-13 09:15:48 +00001671void
1672initxmlDefaultSAXHandler(xmlSAXHandler *hdlr, int warning)
1673{
1674 if(hdlr->initialized == 1)
1675 return;
1676
1677 hdlr->internalSubset = internalSubset;
1678 hdlr->externalSubset = externalSubset;
1679 hdlr->isStandalone = isStandalone;
1680 hdlr->hasInternalSubset = hasInternalSubset;
1681 hdlr->hasExternalSubset = hasExternalSubset;
1682 hdlr->resolveEntity = resolveEntity;
1683 hdlr->getEntity = getEntity;
1684 hdlr->getParameterEntity = getParameterEntity;
1685 hdlr->entityDecl = entityDecl;
1686 hdlr->attributeDecl = attributeDecl;
1687 hdlr->elementDecl = elementDecl;
1688 hdlr->notationDecl = notationDecl;
1689 hdlr->unparsedEntityDecl = unparsedEntityDecl;
1690 hdlr->setDocumentLocator = setDocumentLocator;
1691 hdlr->startDocument = startDocument;
1692 hdlr->endDocument = endDocument;
1693 hdlr->startElement = startElement;
1694 hdlr->endElement = endElement;
1695 hdlr->reference = reference;
1696 hdlr->characters = characters;
1697 hdlr->cdataBlock = cdataBlock;
1698 hdlr->ignorableWhitespace = characters;
1699 hdlr->processingInstruction = processingInstruction;
1700 hdlr->comment = comment;
1701 /* if (xmlGetWarningsDefaultValue == 0) */
1702 if (warning == 0)
1703 hdlr->warning = NULL;
1704 else
1705 hdlr->warning = xmlParserWarning;
1706 hdlr->error = xmlParserError;
1707 hdlr->fatalError = xmlParserError;
1708
1709 hdlr->initialized = 1;
1710}
Owen Taylor3473f882001-02-23 17:55:21 +00001711
1712/**
1713 * xmlDefaultSAXHandlerInit:
1714 *
1715 * Initialize the default SAX handler
1716 */
1717void
1718xmlDefaultSAXHandlerInit(void)
1719{
Daniel Veillard3c01b1d2001-10-17 15:58:35 +00001720 initxmlDefaultSAXHandler(&xmlDefaultSAXHandler, xmlGetWarningsDefaultValue);
Owen Taylor3473f882001-02-23 17:55:21 +00001721}
1722
Daniel Veillardeae522a2001-04-23 13:41:34 +00001723#ifdef LIBXML_HTML_ENABLED
Daniel Veillardd0463562001-10-13 09:15:48 +00001724
1725/**
Daniel Veillard9d06d302002-01-22 18:15:52 +00001726 * inithtmlDefaultSAXHandler:
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001727 * @hdlr: the SAX handler
Daniel Veillardd0463562001-10-13 09:15:48 +00001728 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001729 * Initialize the default HTML SAX handler
Owen Taylor3473f882001-02-23 17:55:21 +00001730 */
Daniel Veillardd0463562001-10-13 09:15:48 +00001731void
1732inithtmlDefaultSAXHandler(xmlSAXHandler *hdlr)
1733{
1734 if(hdlr->initialized == 1)
1735 return;
1736
1737 hdlr->internalSubset = internalSubset;
1738 hdlr->externalSubset = NULL;
1739 hdlr->isStandalone = NULL;
1740 hdlr->hasInternalSubset = NULL;
1741 hdlr->hasExternalSubset = NULL;
1742 hdlr->resolveEntity = NULL;
1743 hdlr->getEntity = getEntity;
1744 hdlr->getParameterEntity = NULL;
1745 hdlr->entityDecl = NULL;
1746 hdlr->attributeDecl = NULL;
1747 hdlr->elementDecl = NULL;
1748 hdlr->notationDecl = NULL;
1749 hdlr->unparsedEntityDecl = NULL;
1750 hdlr->setDocumentLocator = setDocumentLocator;
1751 hdlr->startDocument = startDocument;
1752 hdlr->endDocument = endDocument;
1753 hdlr->startElement = startElement;
1754 hdlr->endElement = endElement;
1755 hdlr->reference = NULL;
1756 hdlr->characters = characters;
1757 hdlr->cdataBlock = cdataBlock;
1758 hdlr->ignorableWhitespace = ignorableWhitespace;
1759 hdlr->processingInstruction = NULL;
1760 hdlr->comment = comment;
1761 hdlr->warning = xmlParserWarning;
1762 hdlr->error = xmlParserError;
1763 hdlr->fatalError = xmlParserError;
1764
1765 hdlr->initialized = 1;
1766}
Owen Taylor3473f882001-02-23 17:55:21 +00001767
1768/**
1769 * htmlDefaultSAXHandlerInit:
1770 *
1771 * Initialize the default SAX handler
1772 */
1773void
1774htmlDefaultSAXHandlerInit(void)
1775{
Daniel Veillardd0463562001-10-13 09:15:48 +00001776 inithtmlDefaultSAXHandler(&htmlDefaultSAXHandler);
Owen Taylor3473f882001-02-23 17:55:21 +00001777}
Daniel Veillardd0463562001-10-13 09:15:48 +00001778
Daniel Veillardeae522a2001-04-23 13:41:34 +00001779#endif /* LIBXML_HTML_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +00001780
Daniel Veillardeae522a2001-04-23 13:41:34 +00001781#ifdef LIBXML_DOCB_ENABLED
Daniel Veillardd0463562001-10-13 09:15:48 +00001782
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001783/**
Daniel Veillard9d06d302002-01-22 18:15:52 +00001784 * initdocbDefaultSAXHandler:
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001785 * @hdlr: the SAX handler
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001786 *
1787 * Initialize the default DocBook SAX handler
1788 */
Daniel Veillardd0463562001-10-13 09:15:48 +00001789void
1790initdocbDefaultSAXHandler(xmlSAXHandler *hdlr)
1791{
1792 if(hdlr->initialized == 1)
1793 return;
1794
1795 hdlr->internalSubset = internalSubset;
1796 hdlr->externalSubset = NULL;
1797 hdlr->isStandalone = isStandalone;
1798 hdlr->hasInternalSubset = hasInternalSubset;
1799 hdlr->hasExternalSubset = hasExternalSubset;
1800 hdlr->resolveEntity = resolveEntity;
1801 hdlr->getEntity = getEntity;
1802 hdlr->getParameterEntity = NULL;
1803 hdlr->entityDecl = entityDecl;
1804 hdlr->attributeDecl = NULL;
1805 hdlr->elementDecl = NULL;
1806 hdlr->notationDecl = NULL;
1807 hdlr->unparsedEntityDecl = NULL;
1808 hdlr->setDocumentLocator = setDocumentLocator;
1809 hdlr->startDocument = startDocument;
1810 hdlr->endDocument = endDocument;
1811 hdlr->startElement = startElement;
1812 hdlr->endElement = endElement;
1813 hdlr->reference = reference;
1814 hdlr->characters = characters;
1815 hdlr->cdataBlock = NULL;
1816 hdlr->ignorableWhitespace = ignorableWhitespace;
1817 hdlr->processingInstruction = NULL;
1818 hdlr->comment = comment;
1819 hdlr->warning = xmlParserWarning;
1820 hdlr->error = xmlParserError;
1821 hdlr->fatalError = xmlParserError;
1822
1823 hdlr->initialized = 1;
1824}
Owen Taylor3473f882001-02-23 17:55:21 +00001825
1826/**
Daniel Veillardeae522a2001-04-23 13:41:34 +00001827 * docbDefaultSAXHandlerInit:
Owen Taylor3473f882001-02-23 17:55:21 +00001828 *
1829 * Initialize the default SAX handler
1830 */
1831void
Daniel Veillardeae522a2001-04-23 13:41:34 +00001832docbDefaultSAXHandlerInit(void)
Owen Taylor3473f882001-02-23 17:55:21 +00001833{
Daniel Veillard3c01b1d2001-10-17 15:58:35 +00001834 initdocbDefaultSAXHandler(&docbDefaultSAXHandler);
Owen Taylor3473f882001-02-23 17:55:21 +00001835}
Daniel Veillardeae522a2001-04-23 13:41:34 +00001836
1837#endif /* LIBXML_DOCB_ENABLED */