blob: ddb13e927a4ca2074ecca11856213918a47834e2 [file] [log] [blame]
Daniel Veillard1af9a412003-08-20 22:54:39 +00001/*
2 * SAX2.c : Default SAX2 handler to build a tree.
3 *
4 * See Copyright for the status of this software.
5 *
6 * Daniel Veillard <daniel@veillard.com>
7 */
8
9
10#define IN_LIBXML
11#include "libxml.h"
12#include <stdlib.h>
13#include <string.h>
14#include <libxml/xmlmemory.h>
15#include <libxml/tree.h>
16#include <libxml/parser.h>
17#include <libxml/parserInternals.h>
18#include <libxml/valid.h>
19#include <libxml/entities.h>
20#include <libxml/xmlerror.h>
21#include <libxml/debugXML.h>
22#include <libxml/xmlIO.h>
23#include <libxml/SAX.h>
24#include <libxml/uri.h>
25#include <libxml/valid.h>
26#include <libxml/HTMLtree.h>
27#include <libxml/globals.h>
28
29/* #define DEBUG_SAX2 */
30/* #define DEBUG_SAX2_TREE */
31
32/**
Daniel Veillarde57ec792003-09-10 10:50:59 +000033 * TODO:
34 *
35 * macro to flag unimplemented blocks
36 * XML_CATALOG_PREFER user env to select between system/public prefered
37 * option. C.f. Richard Tobin <richard@cogsci.ed.ac.uk>
38 *> Just FYI, I am using an environment variable XML_CATALOG_PREFER with
39 *> values "system" and "public". I have made the default be "system" to
40 *> match yours.
41 */
42#define TODO \
43 xmlGenericError(xmlGenericErrorContext, \
44 "Unimplemented block at %s:%d\n", \
45 __FILE__, __LINE__);
46
William M. Brack42331a92004-07-29 07:07:16 +000047/*
48 * xmlSAX2ErrMemory:
49 * @ctxt: an XML validation parser context
50 * @msg: a string to accompany the error message
51 */
52static void
William M. Bracka3215c72004-07-31 16:24:01 +000053xmlSAX2ErrMemory(xmlParserCtxtPtr ctxt, const char *msg) {
William M. Brack42331a92004-07-29 07:07:16 +000054 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
55 ctxt->sax->error(ctxt->userData, "%s: out of memory\n", msg);
56 ctxt->errNo = XML_ERR_NO_MEMORY;
57 ctxt->instate = XML_PARSER_EOF;
58 ctxt->disableSAX = 1;
59}
60
Daniel Veillarde57ec792003-09-10 10:50:59 +000061/**
Daniel Veillardf88d8cf2003-12-08 10:25:02 +000062 * xmlValidError:
63 * @ctxt: an XML validation parser context
64 * @error: the error number
65 * @msg: the error message
66 * @str1: extra data
67 * @str2: extra data
68 *
69 * Handle a validation error
70 */
71static void
72xmlErrValid(xmlParserCtxtPtr ctxt, xmlParserErrors error,
73 const char *msg, const char *str1, const char *str2)
74{
75 xmlStructuredErrorFunc schannel = NULL;
76
77 if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
78 (ctxt->instate == XML_PARSER_EOF))
79 return;
80 ctxt->errNo = error;
81 if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
82 schannel = ctxt->sax->serror;
83 __xmlRaiseError(schannel,
84 ctxt->vctxt.error, ctxt->vctxt.userData,
85 ctxt, NULL, XML_FROM_DTD, error,
86 XML_ERR_ERROR, NULL, 0, (const char *) str1,
87 (const char *) str2, NULL, 0, 0,
88 msg, (const char *) str1, (const char *) str2);
89 ctxt->valid = 0;
90}
91
92/**
Daniel Veillard1af9a412003-08-20 22:54:39 +000093 * xmlSAX2GetPublicId:
94 * @ctx: the user data (XML parser context)
95 *
96 * Provides the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
97 *
98 * Returns a xmlChar *
99 */
100const xmlChar *
101xmlSAX2GetPublicId(void *ctx ATTRIBUTE_UNUSED)
102{
103 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
104 return(NULL);
105}
106
107/**
108 * xmlSAX2GetSystemId:
109 * @ctx: the user data (XML parser context)
110 *
111 * Provides the system ID, basically URL or filename e.g.
112 * http://www.sgmlsource.com/dtds/memo.dtd
113 *
114 * Returns a xmlChar *
115 */
116const xmlChar *
117xmlSAX2GetSystemId(void *ctx)
118{
119 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
120 return((const xmlChar *) ctxt->input->filename);
121}
122
123/**
124 * xmlSAX2GetLineNumber:
125 * @ctx: the user data (XML parser context)
126 *
127 * Provide the line number of the current parsing point.
128 *
129 * Returns an int
130 */
131int
132xmlSAX2GetLineNumber(void *ctx)
133{
134 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
135 return(ctxt->input->line);
136}
137
138/**
139 * xmlSAX2GetColumnNumber:
140 * @ctx: the user data (XML parser context)
141 *
142 * Provide the column number of the current parsing point.
143 *
144 * Returns an int
145 */
146int
147xmlSAX2GetColumnNumber(void *ctx)
148{
149 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
150 return(ctxt->input->col);
151}
152
153/**
154 * xmlSAX2IsStandalone:
155 * @ctx: the user data (XML parser context)
156 *
157 * Is this document tagged standalone ?
158 *
159 * Returns 1 if true
160 */
161int
162xmlSAX2IsStandalone(void *ctx)
163{
164 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
165 return(ctxt->myDoc->standalone == 1);
166}
167
168/**
169 * xmlSAX2HasInternalSubset:
170 * @ctx: the user data (XML parser context)
171 *
172 * Does this document has an internal subset
173 *
174 * Returns 1 if true
175 */
176int
177xmlSAX2HasInternalSubset(void *ctx)
178{
179 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
180 return(ctxt->myDoc->intSubset != NULL);
181}
182
183/**
184 * xmlSAX2HasExternalSubset:
185 * @ctx: the user data (XML parser context)
186 *
187 * Does this document has an external subset
188 *
189 * Returns 1 if true
190 */
191int
192xmlSAX2HasExternalSubset(void *ctx)
193{
194 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
195 return(ctxt->myDoc->extSubset != NULL);
196}
197
198/**
199 * xmlSAX2InternalSubset:
200 * @ctx: the user data (XML parser context)
201 * @name: the root element name
202 * @ExternalID: the external ID
203 * @SystemID: the SYSTEM ID (e.g. filename or URL)
204 *
205 * Callback on internal subset declaration.
206 */
207void
208xmlSAX2InternalSubset(void *ctx, const xmlChar *name,
209 const xmlChar *ExternalID, const xmlChar *SystemID)
210{
211 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
212 xmlDtdPtr dtd;
213#ifdef DEBUG_SAX
214 xmlGenericError(xmlGenericErrorContext,
215 "SAX.xmlSAX2InternalSubset(%s, %s, %s)\n",
216 name, ExternalID, SystemID);
217#endif
218
219 if (ctxt->myDoc == NULL)
220 return;
221 dtd = xmlGetIntSubset(ctxt->myDoc);
222 if (dtd != NULL) {
223 if (ctxt->html)
224 return;
225 xmlUnlinkNode((xmlNodePtr) dtd);
226 xmlFreeDtd(dtd);
227 ctxt->myDoc->intSubset = NULL;
228 }
229 ctxt->myDoc->intSubset =
230 xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
William M. Brack42331a92004-07-29 07:07:16 +0000231 if (ctxt->myDoc->intSubset == NULL)
232 xmlSAX2ErrMemory(ctxt, "xmlSAX2InternalSubset");
Daniel Veillard1af9a412003-08-20 22:54:39 +0000233}
234
235/**
236 * xmlSAX2ExternalSubset:
237 * @ctx: the user data (XML parser context)
238 * @name: the root element name
239 * @ExternalID: the external ID
240 * @SystemID: the SYSTEM ID (e.g. filename or URL)
241 *
242 * Callback on external subset declaration.
243 */
244void
245xmlSAX2ExternalSubset(void *ctx, const xmlChar *name,
246 const xmlChar *ExternalID, const xmlChar *SystemID)
247{
248 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
249#ifdef DEBUG_SAX
250 xmlGenericError(xmlGenericErrorContext,
251 "SAX.xmlSAX2ExternalSubset(%s, %s, %s)\n",
252 name, ExternalID, SystemID);
253#endif
254 if (((ExternalID != NULL) || (SystemID != NULL)) &&
255 (((ctxt->validate) || (ctxt->loadsubset != 0)) &&
256 (ctxt->wellFormed && ctxt->myDoc))) {
257 /*
258 * Try to fetch and parse the external subset.
259 */
260 xmlParserInputPtr oldinput;
261 int oldinputNr;
262 int oldinputMax;
263 xmlParserInputPtr *oldinputTab;
264 xmlParserInputPtr input = NULL;
265 xmlCharEncoding enc;
266 int oldcharset;
267
268 /*
269 * Ask the Entity resolver to load the damn thing
270 */
271 if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
272 input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
273 SystemID);
274 if (input == NULL) {
275 return;
276 }
277
278 xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
279
280 /*
281 * make sure we won't destroy the main document context
282 */
283 oldinput = ctxt->input;
284 oldinputNr = ctxt->inputNr;
285 oldinputMax = ctxt->inputMax;
286 oldinputTab = ctxt->inputTab;
287 oldcharset = ctxt->charset;
288
289 ctxt->inputTab = (xmlParserInputPtr *)
290 xmlMalloc(5 * sizeof(xmlParserInputPtr));
291 if (ctxt->inputTab == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +0000292 xmlSAX2ErrMemory(ctxt, "xmlSAX2ExternalSubset");
Daniel Veillard1af9a412003-08-20 22:54:39 +0000293 ctxt->input = oldinput;
294 ctxt->inputNr = oldinputNr;
295 ctxt->inputMax = oldinputMax;
296 ctxt->inputTab = oldinputTab;
297 ctxt->charset = oldcharset;
298 return;
299 }
300 ctxt->inputNr = 0;
301 ctxt->inputMax = 5;
302 ctxt->input = NULL;
303 xmlPushInput(ctxt, input);
304
305 /*
306 * On the fly encoding conversion if needed
307 */
308 if (ctxt->input->length >= 4) {
309 enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
310 xmlSwitchEncoding(ctxt, enc);
311 }
312
313 if (input->filename == NULL)
314 input->filename = (char *) xmlCanonicPath(SystemID);
315 input->line = 1;
316 input->col = 1;
317 input->base = ctxt->input->cur;
318 input->cur = ctxt->input->cur;
319 input->free = NULL;
320
321 /*
322 * let's parse that entity knowing it's an external subset.
323 */
324 xmlParseExternalSubset(ctxt, ExternalID, SystemID);
325
326 /*
327 * Free up the external entities
328 */
329
330 while (ctxt->inputNr > 1)
331 xmlPopInput(ctxt);
332 xmlFreeInputStream(ctxt->input);
333 xmlFree(ctxt->inputTab);
334
335 /*
336 * Restore the parsing context of the main entity
337 */
338 ctxt->input = oldinput;
339 ctxt->inputNr = oldinputNr;
340 ctxt->inputMax = oldinputMax;
341 ctxt->inputTab = oldinputTab;
342 ctxt->charset = oldcharset;
343 /* ctxt->wellFormed = oldwellFormed; */
344 }
345}
346
347/**
348 * xmlSAX2ResolveEntity:
349 * @ctx: the user data (XML parser context)
350 * @publicId: The public ID of the entity
351 * @systemId: The system ID of the entity
352 *
353 * The entity loader, to control the loading of external entities,
354 * the application can either:
355 * - override this xmlSAX2ResolveEntity() callback in the SAX block
356 * - or better use the xmlSetExternalEntityLoader() function to
357 * set up it's own entity resolution routine
358 *
359 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
360 */
361xmlParserInputPtr
362xmlSAX2ResolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
363{
364 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
365 xmlParserInputPtr ret;
366 xmlChar *URI;
367 const char *base = NULL;
368
369 if (ctxt->input != NULL)
370 base = ctxt->input->filename;
371 if (base == NULL)
372 base = ctxt->directory;
373
374 URI = xmlBuildURI(systemId, (const xmlChar *) base);
375
376#ifdef DEBUG_SAX
377 xmlGenericError(xmlGenericErrorContext,
378 "SAX.xmlSAX2ResolveEntity(%s, %s)\n", publicId, systemId);
379#endif
380
381 ret = xmlLoadExternalEntity((const char *) URI,
382 (const char *) publicId, ctxt);
383 if (URI != NULL)
384 xmlFree(URI);
385 return(ret);
386}
387
388/**
389 * xmlSAX2GetEntity:
390 * @ctx: the user data (XML parser context)
391 * @name: The entity name
392 *
393 * Get an entity by name
394 *
395 * Returns the xmlEntityPtr if found.
396 */
397xmlEntityPtr
398xmlSAX2GetEntity(void *ctx, const xmlChar *name)
399{
400 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
401 xmlEntityPtr ret = NULL;
402
403#ifdef DEBUG_SAX
404 xmlGenericError(xmlGenericErrorContext,
405 "SAX.xmlSAX2GetEntity(%s)\n", name);
406#endif
407
408 if (ctxt->inSubset == 0) {
409 ret = xmlGetPredefinedEntity(name);
410 if (ret != NULL)
411 return(ret);
412 }
413 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->standalone == 1)) {
414 if (ctxt->inSubset == 2) {
415 ctxt->myDoc->standalone = 0;
416 ret = xmlGetDocEntity(ctxt->myDoc, name);
417 ctxt->myDoc->standalone = 1;
418 } else {
419 ret = xmlGetDocEntity(ctxt->myDoc, name);
420 if (ret == NULL) {
421 ctxt->myDoc->standalone = 0;
422 ret = xmlGetDocEntity(ctxt->myDoc, name);
423 if (ret != NULL) {
424 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000425 ctxt->sax->error(ctxt->userData,
426 "Entity(%s) document marked standalone but requires external subset\n",
Daniel Veillard1af9a412003-08-20 22:54:39 +0000427 name);
428 ctxt->valid = 0;
429 ctxt->wellFormed = 0;
430 }
431 ctxt->myDoc->standalone = 1;
432 }
433 }
434 } else {
435 ret = xmlGetDocEntity(ctxt->myDoc, name);
436 }
437 if ((ret != NULL) &&
438 ((ctxt->validate) || (ctxt->replaceEntities)) &&
439 (ret->children == NULL) &&
440 (ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
441 int val;
442
443 /*
444 * for validation purposes we really need to fetch and
445 * parse the external entity
446 */
447 xmlNodePtr children;
448
449 val = xmlParseCtxtExternalEntity(ctxt, ret->URI,
450 ret->ExternalID, &children);
451 if (val == 0) {
452 xmlAddChildList((xmlNodePtr) ret, children);
453 } else {
William M. Brack4811ba32003-09-06 18:02:53 +0000454 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
455 ctxt->sax->error(ctxt->userData,
456 "Failure to process entity %s\n", name);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000457 ctxt->wellFormed = 0;
458 ctxt->valid = 0;
459 ctxt->validate = 0;
460 return(NULL);
461 }
462 ret->owner = 1;
463 }
464 return(ret);
465}
466
467/**
468 * xmlSAX2GetParameterEntity:
469 * @ctx: the user data (XML parser context)
470 * @name: The entity name
471 *
472 * Get a parameter entity by name
473 *
474 * Returns the xmlEntityPtr if found.
475 */
476xmlEntityPtr
477xmlSAX2GetParameterEntity(void *ctx, const xmlChar *name)
478{
479 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
480 xmlEntityPtr ret;
481
482#ifdef DEBUG_SAX
483 xmlGenericError(xmlGenericErrorContext,
484 "SAX.xmlSAX2GetParameterEntity(%s)\n", name);
485#endif
486
487 ret = xmlGetParameterEntity(ctxt->myDoc, name);
488 return(ret);
489}
490
491
492/**
493 * xmlSAX2EntityDecl:
494 * @ctx: the user data (XML parser context)
495 * @name: the entity name
496 * @type: the entity type
497 * @publicId: The public ID of the entity
498 * @systemId: The system ID of the entity
499 * @content: the entity value (without processing).
500 *
501 * An entity definition has been parsed
502 */
503void
504xmlSAX2EntityDecl(void *ctx, const xmlChar *name, int type,
505 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
506{
507 xmlEntityPtr ent;
508 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
509
510#ifdef DEBUG_SAX
511 xmlGenericError(xmlGenericErrorContext,
512 "SAX.xmlSAX2EntityDecl(%s, %d, %s, %s, %s)\n",
513 name, type, publicId, systemId, content);
514#endif
515 if (ctxt->inSubset == 1) {
516 ent = xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
517 systemId, content);
518 if ((ent == NULL) && (ctxt->pedantic) &&
519 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000520 ctxt->sax->warning(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000521 "Entity(%s) already defined in the internal subset\n", name);
522 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
523 xmlChar *URI;
524 const char *base = NULL;
525
526 if (ctxt->input != NULL)
527 base = ctxt->input->filename;
528 if (base == NULL)
529 base = ctxt->directory;
530
531 URI = xmlBuildURI(systemId, (const xmlChar *) base);
532 ent->URI = URI;
533 }
534 } else if (ctxt->inSubset == 2) {
535 ent = xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
536 systemId, content);
537 if ((ent == NULL) && (ctxt->pedantic) &&
538 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000539 ctxt->sax->warning(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000540 "Entity(%s) already defined in the external subset\n", name);
541 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
542 xmlChar *URI;
543 const char *base = NULL;
544
545 if (ctxt->input != NULL)
546 base = ctxt->input->filename;
547 if (base == NULL)
548 base = ctxt->directory;
549
550 URI = xmlBuildURI(systemId, (const xmlChar *) base);
551 ent->URI = URI;
552 }
553 } else {
554 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000555 ctxt->sax->error(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000556 "SAX.xmlSAX2EntityDecl(%s) called while not in subset\n", name);
557 }
558}
559
560/**
561 * xmlSAX2AttributeDecl:
562 * @ctx: the user data (XML parser context)
563 * @elem: the name of the element
564 * @fullname: the attribute name
565 * @type: the attribute type
566 * @def: the type of default value
567 * @defaultValue: the attribute default value
568 * @tree: the tree of enumerated value set
569 *
570 * An attribute definition has been parsed
571 */
572void
573xmlSAX2AttributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
574 int type, int def, const xmlChar *defaultValue,
575 xmlEnumerationPtr tree)
576{
577 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
578 xmlAttributePtr attr;
579 xmlChar *name = NULL, *prefix = NULL;
580
581#ifdef DEBUG_SAX
582 xmlGenericError(xmlGenericErrorContext,
583 "SAX.xmlSAX2AttributeDecl(%s, %s, %d, %d, %s, ...)\n",
584 elem, fullname, type, def, defaultValue);
585#endif
Daniel Veillard68cb4b22004-04-18 20:55:39 +0000586 if ((xmlStrEqual(fullname, BAD_CAST "xml:id")) &&
587 (type != XML_ATTRIBUTE_ID)) {
588 /*
589 * Raise the error but keep the validity flag
590 */
591 int tmp = ctxt->valid;
592 xmlErrValid(ctxt, XML_DTD_XMLID_TYPE,
593 "xml:id : attribute type should be ID\n", NULL, NULL);
594 ctxt->valid = tmp;
595 }
Daniel Veillarde57ec792003-09-10 10:50:59 +0000596 /* TODO: optimize name/prefix allocation */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000597 name = xmlSplitQName(ctxt, fullname, &prefix);
598 ctxt->vctxt.valid = 1;
599 if (ctxt->inSubset == 1)
600 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
601 name, prefix, (xmlAttributeType) type,
602 (xmlAttributeDefault) def, defaultValue, tree);
603 else if (ctxt->inSubset == 2)
604 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
605 name, prefix, (xmlAttributeType) type,
606 (xmlAttributeDefault) def, defaultValue, tree);
607 else {
608 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000609 ctxt->sax->error(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000610 "SAX.xmlSAX2AttributeDecl(%s) called while not in subset\n", name);
Daniel Veillarde57ec792003-09-10 10:50:59 +0000611 xmlFreeEnumeration(tree);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000612 return;
613 }
Daniel Veillard4432df22003-09-28 18:58:27 +0000614#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000615 if (ctxt->vctxt.valid == 0)
616 ctxt->valid = 0;
617 if ((attr != NULL) && (ctxt->validate) && (ctxt->wellFormed) &&
618 (ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset != NULL))
619 ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
620 attr);
Daniel Veillard4432df22003-09-28 18:58:27 +0000621#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000622 if (prefix != NULL)
623 xmlFree(prefix);
624 if (name != NULL)
625 xmlFree(name);
626}
627
628/**
629 * xmlSAX2ElementDecl:
630 * @ctx: the user data (XML parser context)
631 * @name: the element name
632 * @type: the element type
633 * @content: the element value tree
634 *
635 * An element definition has been parsed
636 */
637void
638xmlSAX2ElementDecl(void *ctx, const xmlChar * name, int type,
639 xmlElementContentPtr content)
640{
641 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
642 xmlElementPtr elem = NULL;
643
644#ifdef DEBUG_SAX
645 xmlGenericError(xmlGenericErrorContext,
646 "SAX.xmlSAX2ElementDecl(%s, %d, ...)\n", name, type);
647#endif
648
649 if (ctxt->inSubset == 1)
650 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
651 name, (xmlElementTypeVal) type, content);
652 else if (ctxt->inSubset == 2)
653 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
654 name, (xmlElementTypeVal) type, content);
655 else {
656 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000657 ctxt->sax->error(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000658 "SAX.xmlSAX2ElementDecl(%s) called while not in subset\n",
659 name);
660 return;
661 }
Daniel Veillard4432df22003-09-28 18:58:27 +0000662#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000663 if (elem == NULL)
664 ctxt->valid = 0;
665 if (ctxt->validate && ctxt->wellFormed &&
666 ctxt->myDoc && ctxt->myDoc->intSubset)
667 ctxt->valid &=
668 xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
Daniel Veillard4432df22003-09-28 18:58:27 +0000669#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000670}
671
672/**
673 * xmlSAX2NotationDecl:
674 * @ctx: the user data (XML parser context)
675 * @name: The name of the notation
676 * @publicId: The public ID of the entity
677 * @systemId: The system ID of the entity
678 *
679 * What to do when a notation declaration has been parsed.
680 */
681void
682xmlSAX2NotationDecl(void *ctx, const xmlChar *name,
683 const xmlChar *publicId, const xmlChar *systemId)
684{
685 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
686 xmlNotationPtr nota = NULL;
687
688#ifdef DEBUG_SAX
689 xmlGenericError(xmlGenericErrorContext,
690 "SAX.xmlSAX2NotationDecl(%s, %s, %s)\n", name, publicId, systemId);
691#endif
692
693 if ((publicId == NULL) && (systemId == NULL)) {
694 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000695 ctxt->sax->error(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000696 "SAX.xmlSAX2NotationDecl(%s) externalID or PublicID missing\n", name);
697 ctxt->valid = 0;
698 ctxt->wellFormed = 0;
699 return;
700 } else if (ctxt->inSubset == 1)
701 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
702 publicId, systemId);
703 else if (ctxt->inSubset == 2)
704 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, name,
705 publicId, systemId);
706 else {
707 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000708 ctxt->sax->error(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000709 "SAX.xmlSAX2NotationDecl(%s) called while not in subset\n", name);
710 return;
711 }
Daniel Veillard4432df22003-09-28 18:58:27 +0000712#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000713 if (nota == NULL) ctxt->valid = 0;
714 if (ctxt->validate && ctxt->wellFormed &&
715 ctxt->myDoc && ctxt->myDoc->intSubset)
716 ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
717 nota);
Daniel Veillard4432df22003-09-28 18:58:27 +0000718#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000719}
720
721/**
722 * xmlSAX2UnparsedEntityDecl:
723 * @ctx: the user data (XML parser context)
724 * @name: The name of the entity
725 * @publicId: The public ID of the entity
726 * @systemId: The system ID of the entity
727 * @notationName: the name of the notation
728 *
729 * What to do when an unparsed entity declaration is parsed
730 */
731void
732xmlSAX2UnparsedEntityDecl(void *ctx, const xmlChar *name,
733 const xmlChar *publicId, const xmlChar *systemId,
734 const xmlChar *notationName)
735{
736 xmlEntityPtr ent;
737 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
738#ifdef DEBUG_SAX
739 xmlGenericError(xmlGenericErrorContext,
740 "SAX.xmlSAX2UnparsedEntityDecl(%s, %s, %s, %s)\n",
741 name, publicId, systemId, notationName);
742#endif
743 if (ctxt->inSubset == 1) {
744 ent = xmlAddDocEntity(ctxt->myDoc, name,
745 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
746 publicId, systemId, notationName);
747 if ((ent == NULL) && (ctxt->pedantic) &&
748 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000749 ctxt->sax->warning(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000750 "Entity(%s) already defined in the internal subset\n", name);
751 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
752 xmlChar *URI;
753 const char *base = NULL;
754
755 if (ctxt->input != NULL)
756 base = ctxt->input->filename;
757 if (base == NULL)
758 base = ctxt->directory;
759
760 URI = xmlBuildURI(systemId, (const xmlChar *) base);
761 ent->URI = URI;
762 }
763 } else if (ctxt->inSubset == 2) {
764 ent = xmlAddDtdEntity(ctxt->myDoc, name,
765 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
766 publicId, systemId, notationName);
767 if ((ent == NULL) && (ctxt->pedantic) &&
768 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000769 ctxt->sax->warning(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000770 "Entity(%s) already defined in the external subset\n", name);
771 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
772 xmlChar *URI;
773 const char *base = NULL;
774
775 if (ctxt->input != NULL)
776 base = ctxt->input->filename;
777 if (base == NULL)
778 base = ctxt->directory;
779
780 URI = xmlBuildURI(systemId, (const xmlChar *) base);
781 ent->URI = URI;
782 }
783 } else {
784 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000785 ctxt->sax->error(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000786 "SAX.xmlSAX2UnparsedEntityDecl(%s) called while not in subset\n", name);
787 }
788}
789
790/**
791 * xmlSAX2SetDocumentLocator:
792 * @ctx: the user data (XML parser context)
793 * @loc: A SAX Locator
794 *
795 * Receive the document locator at startup, actually xmlDefaultSAXLocator
796 * Everything is available on the context, so this is useless in our case.
797 */
798void
799xmlSAX2SetDocumentLocator(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
800{
801 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
802#ifdef DEBUG_SAX
803 xmlGenericError(xmlGenericErrorContext,
804 "SAX.xmlSAX2SetDocumentLocator()\n");
805#endif
806}
807
808/**
809 * xmlSAX2StartDocument:
810 * @ctx: the user data (XML parser context)
811 *
812 * called when the document start being processed.
813 */
814void
815xmlSAX2StartDocument(void *ctx)
816{
817 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
818 xmlDocPtr doc;
819
820#ifdef DEBUG_SAX
821 xmlGenericError(xmlGenericErrorContext,
822 "SAX.xmlSAX2StartDocument()\n");
823#endif
824 if (ctxt->html) {
825#ifdef LIBXML_HTML_ENABLED
826 if (ctxt->myDoc == NULL)
827 ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
828 if (ctxt->myDoc == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +0000829 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
Daniel Veillard1af9a412003-08-20 22:54:39 +0000830 return;
831 }
832#else
833 xmlGenericError(xmlGenericErrorContext,
834 "libxml2 built without HTML support\n");
835 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
836 ctxt->instate = XML_PARSER_EOF;
837 ctxt->disableSAX = 1;
838 return;
839#endif
840 } else {
841 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
842 if (doc != NULL) {
843 if (ctxt->encoding != NULL)
844 doc->encoding = xmlStrdup(ctxt->encoding);
845 else
846 doc->encoding = NULL;
847 doc->standalone = ctxt->standalone;
848 } else {
William M. Brack42331a92004-07-29 07:07:16 +0000849 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
Daniel Veillard1af9a412003-08-20 22:54:39 +0000850 return;
851 }
Daniel Veillard500a1de2004-03-22 15:22:58 +0000852 if ((ctxt->dictNames) && (doc != NULL)) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +0000853 doc->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000854 xmlDictReference(doc->dict);
855 }
Daniel Veillard1af9a412003-08-20 22:54:39 +0000856 }
857 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
858 (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
859 ctxt->myDoc->URL = xmlCanonicPath((const xmlChar *) ctxt->input->filename);
860 if (ctxt->myDoc->URL == NULL)
William M. Bracka3215c72004-07-31 16:24:01 +0000861 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
Daniel Veillard1af9a412003-08-20 22:54:39 +0000862 }
863}
864
865/**
866 * xmlSAX2EndDocument:
867 * @ctx: the user data (XML parser context)
868 *
869 * called when the document end has been detected.
870 */
871void
872xmlSAX2EndDocument(void *ctx)
873{
874 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
875#ifdef DEBUG_SAX
876 xmlGenericError(xmlGenericErrorContext,
877 "SAX.xmlSAX2EndDocument()\n");
878#endif
Daniel Veillard4432df22003-09-28 18:58:27 +0000879#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000880 if (ctxt->validate && ctxt->wellFormed &&
881 ctxt->myDoc && ctxt->myDoc->intSubset)
882 ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
Daniel Veillard4432df22003-09-28 18:58:27 +0000883#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000884
885 /*
886 * Grab the encoding if it was added on-the-fly
887 */
888 if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
889 (ctxt->myDoc->encoding == NULL)) {
890 ctxt->myDoc->encoding = ctxt->encoding;
891 ctxt->encoding = NULL;
892 }
893 if ((ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
894 (ctxt->myDoc->encoding == NULL)) {
895 ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
896 }
897 if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
898 (ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
899 ctxt->myDoc->charset = ctxt->charset;
900 }
901}
902
Daniel Veillard81273902003-09-30 00:43:48 +0000903#if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED)
Daniel Veillard1af9a412003-08-20 22:54:39 +0000904/**
905 * xmlSAX2AttributeInternal:
906 * @ctx: the user data (XML parser context)
907 * @fullname: The attribute name, including namespace prefix
908 * @value: The attribute value
909 * @prefix: the prefix on the element node
910 *
911 * Handle an attribute that has been read by the parser.
912 * The default handling is to convert the attribute into an
913 * DOM subtree and past it in a new xmlAttr element added to
914 * the element.
915 */
916static void
917xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000918 const xmlChar *value, const xmlChar *prefix ATTRIBUTE_UNUSED)
Daniel Veillard1af9a412003-08-20 22:54:39 +0000919{
920 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
921 xmlAttrPtr ret;
922 xmlChar *name;
923 xmlChar *ns;
924 xmlChar *nval;
925 xmlNsPtr namespace;
926
927 /*
928 * Split the full name into a namespace prefix and the tag name
929 */
930 name = xmlSplitQName(ctxt, fullname, &ns);
931 if ((name != NULL) && (name[0] == 0)) {
932 if (xmlStrEqual(ns, BAD_CAST "xmlns")) {
933 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
934 ctxt->sax->error(ctxt->userData,
935 "invalid namespace declaration '%s'\n", fullname);
936 } else {
937 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
938 ctxt->sax->warning(ctxt->userData,
939 "Avoid attribute ending with ':' like '%s'\n", fullname);
940 }
941 if (ns != NULL)
942 xmlFree(ns);
943 ns = NULL;
944 xmlFree(name);
945 name = xmlStrdup(fullname);
946 }
947 if (name == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +0000948 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
Daniel Veillard1af9a412003-08-20 22:54:39 +0000949 if (ns != NULL)
950 xmlFree(ns);
951 return;
952 }
953
Daniel Veillard4432df22003-09-28 18:58:27 +0000954#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000955 /*
956 * Do the last stage of the attribute normalization
957 * Needed for HTML too:
958 * http://www.w3.org/TR/html4/types.html#h-6.2
959 */
960 ctxt->vctxt.valid = 1;
961 nval = xmlValidCtxtNormalizeAttributeValue(&ctxt->vctxt,
962 ctxt->myDoc, ctxt->node,
963 fullname, value);
964 if (ctxt->vctxt.valid != 1) {
965 ctxt->valid = 0;
966 }
967 if (nval != NULL)
968 value = nval;
Daniel Veillard4432df22003-09-28 18:58:27 +0000969#else
970 nval = NULL;
971#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000972
973 /*
974 * Check whether it's a namespace definition
975 */
976 if ((!ctxt->html) && (ns == NULL) &&
977 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
978 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
979 xmlNsPtr nsret;
980 xmlChar *val;
981
982 if (!ctxt->replaceEntities) {
983 ctxt->depth++;
984 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
985 0,0,0);
986 ctxt->depth--;
987 } else {
988 val = (xmlChar *) value;
989 }
990
991 if (val[0] != 0) {
992 xmlURIPtr uri;
993
994 uri = xmlParseURI((const char *)val);
995 if (uri == NULL) {
996 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
997 ctxt->sax->warning(ctxt->userData,
William M. Brack4811ba32003-09-06 18:02:53 +0000998 "xmlns: %s not a valid URI\n", val);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000999 } else {
1000 if (uri->scheme == NULL) {
1001 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1002 ctxt->sax->warning(ctxt->userData,
1003 "xmlns: URI %s is not absolute\n", val);
1004 }
1005 xmlFreeURI(uri);
1006 }
1007 }
1008
1009 /* a default namespace definition */
1010 nsret = xmlNewNs(ctxt->node, val, NULL);
1011
Daniel Veillard4432df22003-09-28 18:58:27 +00001012#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001013 /*
1014 * Validate also for namespace decls, they are attributes from
1015 * an XML-1.0 perspective
1016 */
1017 if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
1018 ctxt->myDoc && ctxt->myDoc->intSubset)
1019 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
1020 ctxt->node, prefix, nsret, val);
Daniel Veillard4432df22003-09-28 18:58:27 +00001021#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001022 if (name != NULL)
1023 xmlFree(name);
1024 if (nval != NULL)
1025 xmlFree(nval);
1026 if (val != value)
1027 xmlFree(val);
1028 return;
1029 }
1030 if ((!ctxt->html) &&
1031 (ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
1032 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
1033 xmlNsPtr nsret;
1034 xmlChar *val;
1035
1036 if (!ctxt->replaceEntities) {
1037 ctxt->depth++;
1038 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1039 0,0,0);
1040 ctxt->depth--;
1041 if (val == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001042 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
Daniel Veillard1af9a412003-08-20 22:54:39 +00001043 xmlFree(ns);
1044 if (name != NULL)
1045 xmlFree(name);
1046 return;
1047 }
1048 } else {
1049 val = (xmlChar *) value;
1050 }
1051
1052 if (val[0] == 0) {
1053 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1054 ctxt->sax->error(ctxt->userData,
1055 "Empty namespace name for prefix %s\n", name);
1056 }
1057 if ((ctxt->pedantic != 0) && (val[0] != 0)) {
1058 xmlURIPtr uri;
1059
1060 uri = xmlParseURI((const char *)val);
1061 if (uri == NULL) {
1062 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1063 ctxt->sax->warning(ctxt->userData,
1064 "xmlns:%s: %s not a valid URI\n", name, value);
1065 } else {
1066 if (uri->scheme == NULL) {
1067 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1068 ctxt->sax->warning(ctxt->userData,
1069 "xmlns:%s: URI %s is not absolute\n", name, value);
1070 }
1071 xmlFreeURI(uri);
1072 }
1073 }
1074
1075 /* a standard namespace definition */
1076 nsret = xmlNewNs(ctxt->node, val, name);
1077 xmlFree(ns);
Daniel Veillard4432df22003-09-28 18:58:27 +00001078#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001079 /*
1080 * Validate also for namespace decls, they are attributes from
1081 * an XML-1.0 perspective
1082 */
1083 if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
1084 ctxt->myDoc && ctxt->myDoc->intSubset)
1085 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
1086 ctxt->node, prefix, nsret, value);
Daniel Veillard4432df22003-09-28 18:58:27 +00001087#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001088 if (name != NULL)
1089 xmlFree(name);
1090 if (nval != NULL)
1091 xmlFree(nval);
1092 if (val != value)
1093 xmlFree(val);
1094 return;
1095 }
1096
1097 if (ns != NULL) {
1098 xmlAttrPtr prop;
1099 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
Daniel Veillard67906942003-08-28 21:13:25 +00001100 if (namespace == NULL) {
William M. Brack4811ba32003-09-06 18:02:53 +00001101 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1102 ctxt->sax->error(ctxt->userData,
1103 "Namespace prefix %s of attribute %s is not defined\n",
Daniel Veillard67906942003-08-28 21:13:25 +00001104 ns, name);
1105 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001106
1107 prop = ctxt->node->properties;
1108 while (prop != NULL) {
1109 if (prop->ns != NULL) {
1110 if ((xmlStrEqual(name, prop->name)) &&
1111 ((namespace == prop->ns) ||
1112 (xmlStrEqual(namespace->href, prop->ns->href)))) {
1113 ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
1114 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1115 ctxt->sax->error(ctxt->userData,
1116 "Attribute %s in %s redefined\n",
1117 name, namespace->href);
1118 ctxt->wellFormed = 0;
1119 if (ctxt->recovery == 0) ctxt->disableSAX = 1;
1120 goto error;
1121 }
1122 }
1123 prop = prop->next;
1124 }
1125 } else {
1126 namespace = NULL;
1127 }
1128
1129 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
1130 ret = xmlNewNsPropEatName(ctxt->node, namespace, name, NULL);
1131
1132 if (ret != NULL) {
1133 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
1134 xmlNodePtr tmp;
1135
1136 ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
1137 tmp = ret->children;
1138 while (tmp != NULL) {
1139 tmp->parent = (xmlNodePtr) ret;
1140 if (tmp->next == NULL)
1141 ret->last = tmp;
1142 tmp = tmp->next;
1143 }
1144 } else if (value != NULL) {
1145 ret->children = xmlNewDocText(ctxt->myDoc, value);
1146 ret->last = ret->children;
1147 if (ret->children != NULL)
1148 ret->children->parent = (xmlNodePtr) ret;
1149 }
1150 }
1151
Daniel Veillard4432df22003-09-28 18:58:27 +00001152#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001153 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
1154 ctxt->myDoc && ctxt->myDoc->intSubset) {
1155
1156 /*
1157 * If we don't substitute entities, the validation should be
1158 * done on a value with replaced entities anyway.
1159 */
1160 if (!ctxt->replaceEntities) {
1161 xmlChar *val;
1162
1163 ctxt->depth++;
1164 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1165 0,0,0);
1166 ctxt->depth--;
1167
1168 if (val == NULL)
1169 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1170 ctxt->myDoc, ctxt->node, ret, value);
1171 else {
1172 xmlChar *nvalnorm;
1173
1174 /*
1175 * Do the last stage of the attribute normalization
1176 * It need to be done twice ... it's an extra burden related
1177 * to the ability to keep xmlSAX2References in attributes
1178 */
1179 nvalnorm = xmlValidNormalizeAttributeValue(ctxt->myDoc,
1180 ctxt->node, fullname, val);
1181 if (nvalnorm != NULL) {
1182 xmlFree(val);
1183 val = nvalnorm;
1184 }
1185
1186 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1187 ctxt->myDoc, ctxt->node, ret, val);
1188 xmlFree(val);
1189 }
1190 } else {
1191 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
1192 ctxt->node, ret, value);
1193 }
Daniel Veillard4432df22003-09-28 18:58:27 +00001194 } else
1195#endif /* LIBXML_VALID_ENABLED */
1196 if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
Daniel Veillard1af9a412003-08-20 22:54:39 +00001197 (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
1198 ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
1199 /*
1200 * when validating, the ID registration is done at the attribute
1201 * validation level. Otherwise we have to do specific handling here.
1202 */
1203 if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
1204 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
1205 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
1206 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00001207 else if (xmlStrEqual(fullname, BAD_CAST "xml:id")) {
1208 /*
1209 * Add the xml:id value
1210 *
1211 * Open issue: normalization of the value.
1212 */
Daniel Veillard68cb4b22004-04-18 20:55:39 +00001213 if (xmlValidateNCName(value, 1) != 0) {
1214 xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
1215 "xml:id : attribute value %s is not an NCName\n",
1216 (const char *) value, NULL);
1217 }
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00001218 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
1219 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001220 }
1221
1222error:
1223 if (nval != NULL)
1224 xmlFree(nval);
1225 if (ns != NULL)
1226 xmlFree(ns);
1227}
1228
Daniel Veillard1af9a412003-08-20 22:54:39 +00001229/*
1230 * xmlCheckDefaultedAttributes:
1231 *
1232 * Check defaulted attributes from the DTD
1233 */
1234static void
1235xmlCheckDefaultedAttributes(xmlParserCtxtPtr ctxt, const xmlChar *name,
1236 const xmlChar *prefix, const xmlChar **atts) {
1237 xmlElementPtr elemDecl;
1238 const xmlChar *att;
1239 int internal = 1;
1240 int i;
1241
1242 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset, name, prefix);
1243 if (elemDecl == NULL) {
1244 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset, name, prefix);
1245 internal = 0;
1246 }
1247
1248process_external_subset:
1249
1250 if (elemDecl != NULL) {
1251 xmlAttributePtr attr = elemDecl->attributes;
1252 /*
1253 * Check against defaulted attributes from the external subset
1254 * if the document is stamped as standalone
1255 */
1256 if ((ctxt->myDoc->standalone == 1) &&
1257 (ctxt->myDoc->extSubset != NULL) &&
1258 (ctxt->validate)) {
1259 while (attr != NULL) {
1260 if ((attr->defaultValue != NULL) &&
1261 (xmlGetDtdQAttrDesc(ctxt->myDoc->extSubset,
1262 attr->elem, attr->name,
1263 attr->prefix) == attr) &&
1264 (xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1265 attr->elem, attr->name,
1266 attr->prefix) == NULL)) {
1267 xmlChar *fulln;
1268
1269 if (attr->prefix != NULL) {
1270 fulln = xmlStrdup(attr->prefix);
1271 fulln = xmlStrcat(fulln, BAD_CAST ":");
1272 fulln = xmlStrcat(fulln, attr->name);
1273 } else {
1274 fulln = xmlStrdup(attr->name);
1275 }
1276
1277 /*
1278 * Check that the attribute is not declared in the
1279 * serialization
1280 */
1281 att = NULL;
1282 if (atts != NULL) {
1283 i = 0;
1284 att = atts[i];
1285 while (att != NULL) {
1286 if (xmlStrEqual(att, fulln))
1287 break;
1288 i += 2;
1289 att = atts[i];
1290 }
1291 }
1292 if (att == NULL) {
Daniel Veillardf88d8cf2003-12-08 10:25:02 +00001293 xmlErrValid(ctxt, XML_DTD_STANDALONE_DEFAULTED,
Daniel Veillard1af9a412003-08-20 22:54:39 +00001294 "standalone: attribute %s on %s defaulted from external subset\n",
Daniel Veillard427174f2003-12-10 10:42:59 +00001295 (const char *)fulln,
1296 (const char *)attr->elem);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001297 }
1298 }
1299 attr = attr->nexth;
1300 }
1301 }
1302
1303 /*
1304 * Actually insert defaulted values when needed
1305 */
1306 attr = elemDecl->attributes;
1307 while (attr != NULL) {
1308 /*
1309 * Make sure that attributes redefinition occuring in the
1310 * internal subset are not overriden by definitions in the
1311 * external subset.
1312 */
1313 if (attr->defaultValue != NULL) {
1314 /*
1315 * the element should be instantiated in the tree if:
1316 * - this is a namespace prefix
1317 * - the user required for completion in the tree
1318 * like XSLT
1319 * - there isn't already an attribute definition
1320 * in the internal subset overriding it.
1321 */
1322 if (((attr->prefix != NULL) &&
1323 (xmlStrEqual(attr->prefix, BAD_CAST "xmlns"))) ||
1324 ((attr->prefix == NULL) &&
1325 (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) ||
1326 (ctxt->loadsubset & XML_COMPLETE_ATTRS)) {
1327 xmlAttributePtr tst;
1328
1329 tst = xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1330 attr->elem, attr->name,
1331 attr->prefix);
1332 if ((tst == attr) || (tst == NULL)) {
1333 xmlChar fn[50];
1334 xmlChar *fulln;
1335
1336 fulln = xmlBuildQName(attr->name, attr->prefix, fn, 50);
1337 if (fulln == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001338 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
Daniel Veillard1af9a412003-08-20 22:54:39 +00001339 return;
1340 }
1341
1342 /*
1343 * Check that the attribute is not declared in the
1344 * serialization
1345 */
1346 att = NULL;
1347 if (atts != NULL) {
1348 i = 0;
1349 att = atts[i];
1350 while (att != NULL) {
1351 if (xmlStrEqual(att, fulln))
1352 break;
1353 i += 2;
1354 att = atts[i];
1355 }
1356 }
1357 if (att == NULL) {
1358 xmlSAX2AttributeInternal(ctxt, fulln,
1359 attr->defaultValue, prefix);
1360 }
1361 if ((fulln != fn) && (fulln != attr->name))
1362 xmlFree(fulln);
1363 }
1364 }
1365 }
1366 attr = attr->nexth;
1367 }
1368 if (internal == 1) {
1369 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset,
1370 name, prefix);
1371 internal = 0;
1372 goto process_external_subset;
1373 }
1374 }
1375}
1376
1377/**
1378 * xmlSAX2StartElement:
1379 * @ctx: the user data (XML parser context)
1380 * @fullname: The element name, including namespace prefix
1381 * @atts: An array of name/value attributes pairs, NULL terminated
1382 *
1383 * called when an opening tag has been processed.
1384 */
1385void
1386xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
1387{
1388 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1389 xmlNodePtr ret;
1390 xmlNodePtr parent = ctxt->node;
1391 xmlNsPtr ns;
1392 xmlChar *name;
1393 xmlChar *prefix;
1394 const xmlChar *att;
1395 const xmlChar *value;
1396 int i;
1397
1398#ifdef DEBUG_SAX
1399 xmlGenericError(xmlGenericErrorContext,
1400 "SAX.xmlSAX2StartElement(%s)\n", fullname);
1401#endif
1402
1403 /*
1404 * First check on validity:
1405 */
1406 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
1407 ((ctxt->myDoc->intSubset == NULL) ||
1408 ((ctxt->myDoc->intSubset->notations == NULL) &&
1409 (ctxt->myDoc->intSubset->elements == NULL) &&
1410 (ctxt->myDoc->intSubset->attributes == NULL) &&
1411 (ctxt->myDoc->intSubset->entities == NULL)))) {
Daniel Veillardf88d8cf2003-12-08 10:25:02 +00001412 xmlErrValid(ctxt, XML_ERR_NO_DTD,
1413 "Validation failed: no DTD found !", NULL, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001414 ctxt->validate = 0;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001415 }
1416
1417
1418 /*
1419 * Split the full name into a namespace prefix and the tag name
1420 */
1421 name = xmlSplitQName(ctxt, fullname, &prefix);
1422
1423
1424 /*
1425 * Note : the namespace resolution is deferred until the end of the
1426 * attributes parsing, since local namespace can be defined as
1427 * an attribute at this level.
1428 */
1429 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL);
1430 if (ret == NULL) {
1431 if (prefix != NULL)
1432 xmlFree(prefix);
William M. Brack42331a92004-07-29 07:07:16 +00001433 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
Daniel Veillard1af9a412003-08-20 22:54:39 +00001434 return;
1435 }
1436 if (ctxt->myDoc->children == NULL) {
1437#ifdef DEBUG_SAX_TREE
1438 xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
1439#endif
1440 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1441 } else if (parent == NULL) {
1442 parent = ctxt->myDoc->children;
1443 }
1444 ctxt->nodemem = -1;
1445 if (ctxt->linenumbers) {
Daniel Veillard3e35f8e2003-10-21 00:05:38 +00001446 if (ctxt->input != NULL) {
1447 if (ctxt->input->line < 65535)
1448 ret->line = (short) ctxt->input->line;
1449 else
1450 ret->line = 65535;
1451 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001452 }
1453
1454 /*
1455 * We are parsing a new node.
1456 */
1457#ifdef DEBUG_SAX_TREE
1458 xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);
1459#endif
1460 nodePush(ctxt, ret);
1461
1462 /*
1463 * Link the child element
1464 */
1465 if (parent != NULL) {
1466 if (parent->type == XML_ELEMENT_NODE) {
1467#ifdef DEBUG_SAX_TREE
1468 xmlGenericError(xmlGenericErrorContext,
1469 "adding child %s to %s\n", name, parent->name);
1470#endif
1471 xmlAddChild(parent, ret);
1472 } else {
1473#ifdef DEBUG_SAX_TREE
1474 xmlGenericError(xmlGenericErrorContext,
1475 "adding sibling %s to ", name);
1476 xmlDebugDumpOneNode(stderr, parent, 0);
1477#endif
1478 xmlAddSibling(parent, ret);
1479 }
1480 }
1481
1482 /*
1483 * Insert all the defaulted attributes from the DTD especially namespaces
1484 */
1485 if ((!ctxt->html) &&
1486 ((ctxt->myDoc->intSubset != NULL) ||
1487 (ctxt->myDoc->extSubset != NULL))) {
1488 xmlCheckDefaultedAttributes(ctxt, name, prefix, atts);
1489 }
1490
1491 /*
1492 * process all the attributes whose name start with "xmlns"
1493 */
1494 if (atts != NULL) {
1495 i = 0;
1496 att = atts[i++];
1497 value = atts[i++];
1498 if (!ctxt->html) {
1499 while ((att != NULL) && (value != NULL)) {
1500 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l') &&
1501 (att[3] == 'n') && (att[4] == 's'))
1502 xmlSAX2AttributeInternal(ctxt, att, value, prefix);
1503
1504 att = atts[i++];
1505 value = atts[i++];
1506 }
1507 }
1508 }
1509
1510 /*
1511 * Search the namespace, note that since the attributes have been
1512 * processed, the local namespaces are available.
1513 */
1514 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
1515 if ((ns == NULL) && (parent != NULL))
1516 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
1517 if ((prefix != NULL) && (ns == NULL)) {
1518 ns = xmlNewNs(ret, NULL, prefix);
1519 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1520 ctxt->sax->warning(ctxt->userData,
1521 "Namespace prefix %s is not defined\n", prefix);
1522 }
1523
1524 /*
1525 * set the namespace node, making sure that if the default namspace
1526 * is unbound on a parent we simply kee it NULL
1527 */
1528 if ((ns != NULL) && (ns->href != NULL) &&
1529 ((ns->href[0] != 0) || (ns->prefix != NULL)))
1530 xmlSetNs(ret, ns);
1531
1532 /*
1533 * process all the other attributes
1534 */
1535 if (atts != NULL) {
1536 i = 0;
1537 att = atts[i++];
1538 value = atts[i++];
1539 if (ctxt->html) {
1540 while (att != NULL) {
1541 xmlSAX2AttributeInternal(ctxt, att, value, NULL);
1542 att = atts[i++];
1543 value = atts[i++];
1544 }
1545 } else {
1546 while ((att != NULL) && (value != NULL)) {
1547 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l') ||
1548 (att[3] != 'n') || (att[4] != 's'))
1549 xmlSAX2AttributeInternal(ctxt, att, value, NULL);
1550
1551 /*
1552 * Next ones
1553 */
1554 att = atts[i++];
1555 value = atts[i++];
1556 }
1557 }
1558 }
1559
Daniel Veillard4432df22003-09-28 18:58:27 +00001560#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001561 /*
1562 * If it's the Document root, finish the DTD validation and
1563 * check the document root element for validity
1564 */
1565 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
1566 int chk;
1567
1568 chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
1569 if (chk <= 0)
1570 ctxt->valid = 0;
1571 if (chk < 0)
1572 ctxt->wellFormed = 0;
1573 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
1574 ctxt->vctxt.finishDtd = 1;
1575 }
Daniel Veillard4432df22003-09-28 18:58:27 +00001576#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001577
1578 if (prefix != NULL)
1579 xmlFree(prefix);
1580
1581}
1582
1583/**
1584 * xmlSAX2EndElement:
1585 * @ctx: the user data (XML parser context)
1586 * @name: The element name
1587 *
1588 * called when the end of an element has been detected.
1589 */
1590void
1591xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
1592{
1593 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1594 xmlParserNodeInfo node_info;
1595 xmlNodePtr cur = ctxt->node;
1596
1597#ifdef DEBUG_SAX
1598 if (name == NULL)
1599 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(NULL)\n");
1600 else
1601 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(%s)\n", name);
1602#endif
1603
1604 /* Capture end position and add node */
1605 if (cur != NULL && ctxt->record_info) {
1606 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
1607 node_info.end_line = ctxt->input->line;
1608 node_info.node = cur;
1609 xmlParserAddNodeInfo(ctxt, &node_info);
1610 }
1611 ctxt->nodemem = -1;
1612
Daniel Veillard4432df22003-09-28 18:58:27 +00001613#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001614 if (ctxt->validate && ctxt->wellFormed &&
1615 ctxt->myDoc && ctxt->myDoc->intSubset)
1616 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
1617 cur);
Daniel Veillard4432df22003-09-28 18:58:27 +00001618#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001619
1620
1621 /*
1622 * end of parsing of this node.
1623 */
1624#ifdef DEBUG_SAX_TREE
1625 xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);
1626#endif
1627 nodePop(ctxt);
1628}
Daniel Veillard81273902003-09-30 00:43:48 +00001629#endif /* LIBXML_SAX1_ENABLED || LIBXML_HTML_ENABLE */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001630
Daniel Veillarde57ec792003-09-10 10:50:59 +00001631/*
Daniel Veillard19895052003-09-17 13:59:32 +00001632 * xmlSAX2TextNode:
1633 * @ctxt: the parser context
1634 * @str: the input string
1635 * @len: the string length
1636 *
1637 * Remove the entities from an attribute value
1638 *
1639 * Returns the newly allocated string or NULL if not needed or error
1640 */
1641static xmlNodePtr
1642xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
1643 xmlNodePtr ret;
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001644 const xmlChar *intern = NULL;
Daniel Veillard19895052003-09-17 13:59:32 +00001645
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001646 /*
1647 * Allocate
1648 */
Daniel Veillard19895052003-09-17 13:59:32 +00001649 if (ctxt->freeElems != NULL) {
1650 ret = ctxt->freeElems;
1651 ctxt->freeElems = ret->next;
1652 ctxt->freeElemsNr--;
Daniel Veillard19895052003-09-17 13:59:32 +00001653 } else {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001654 ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard19895052003-09-17 13:59:32 +00001655 }
1656 if (ret == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001657 xmlErrMemory(ctxt, "xmlSAX2Characters");
Daniel Veillard19895052003-09-17 13:59:32 +00001658 return(NULL);
1659 }
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001660 /*
1661 * intern the formatting blanks found between tags, or the
1662 * very short strings
1663 */
1664 if (ctxt->dictNames) {
1665 xmlChar cur = str[len];
1666
Daniel Veillarddca8cc72003-09-26 13:53:14 +00001667 if ((len <= 3) && ((cur == '"') || (cur == '\'') ||
1668 ((cur == '<') && (str[len + 1] != '!')))) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001669 intern = xmlDictLookup(ctxt->dict, str, len);
William M. Brack76e95df2003-10-18 16:20:14 +00001670 } else if (IS_BLANK_CH(*str) && (len < 60) && (cur == '<') &&
Daniel Veillarddca8cc72003-09-26 13:53:14 +00001671 (str[len + 1] != '!')) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001672 int i;
1673
1674 for (i = 1;i < len;i++) {
Daniel Veillard1a9b7082004-01-02 10:42:01 +00001675 if (!IS_BLANK_CH(str[i])) goto skip;
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001676 }
1677 intern = xmlDictLookup(ctxt->dict, str, len);
1678 }
1679 }
1680skip:
1681 memset(ret, 0, sizeof(xmlNode));
1682 ret->type = XML_TEXT_NODE;
1683
1684 ret->name = xmlStringText;
William M. Brack9f797ab2004-07-28 07:40:12 +00001685 if (intern == NULL) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001686 ret->content = xmlStrndup(str, len);
William M. Brack9f797ab2004-07-28 07:40:12 +00001687 if (ret->content == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001688 xmlSAX2ErrMemory(ctxt, "xmlSAX2TextNode");
1689 xmlFree(ret);
William M. Brack9f797ab2004-07-28 07:40:12 +00001690 return(NULL);
1691 }
1692 } else
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001693 ret->content = (xmlChar *) intern;
1694
1695 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1696 xmlRegisterNodeDefaultValue(ret);
Daniel Veillard19895052003-09-17 13:59:32 +00001697 return(ret);
1698}
1699
Daniel Veillard4432df22003-09-28 18:58:27 +00001700#ifdef LIBXML_VALID_ENABLED
Daniel Veillard19895052003-09-17 13:59:32 +00001701/*
Daniel Veillarde57ec792003-09-10 10:50:59 +00001702 * xmlSAX2DecodeAttrEntities:
1703 * @ctxt: the parser context
1704 * @str: the input string
1705 * @len: the string length
1706 *
1707 * Remove the entities from an attribute value
1708 *
1709 * Returns the newly allocated string or NULL if not needed or error
1710 */
1711static xmlChar *
1712xmlSAX2DecodeAttrEntities(xmlParserCtxtPtr ctxt, const xmlChar *str,
1713 const xmlChar *end) {
1714 const xmlChar *in;
1715 xmlChar *ret;
1716
1717 in = str;
1718 while (in < end)
1719 if (*in++ == '&')
1720 goto decode;
1721 return(NULL);
1722decode:
1723 ctxt->depth++;
1724 ret = xmlStringLenDecodeEntities(ctxt, str, end - str,
1725 XML_SUBSTITUTE_REF, 0,0,0);
1726 ctxt->depth--;
1727 return(ret);
1728}
Daniel Veillard4432df22003-09-28 18:58:27 +00001729#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00001730
1731/**
1732 * xmlSAX2AttributeNs:
1733 * @ctx: the user data (XML parser context)
Daniel Veillard62998c02003-09-15 12:56:36 +00001734 * @localname: the local name of the attribute
1735 * @prefix: the attribute namespace prefix if available
1736 * @URI: the attribute namespace name if available
Daniel Veillarde57ec792003-09-10 10:50:59 +00001737 * @value: Start of the attribute value
1738 * @valueend: end of the attribute value
1739 *
1740 * Handle an attribute that has been read by the parser.
1741 * The default handling is to convert the attribute into an
1742 * DOM subtree and past it in a new xmlAttr element added to
1743 * the element.
1744 */
1745static void
1746xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
1747 const xmlChar * localname,
1748 const xmlChar * prefix,
1749 const xmlChar * value,
1750 const xmlChar * valueend)
1751{
1752 xmlAttrPtr ret;
1753 xmlNsPtr namespace = NULL;
1754 xmlChar *dup = NULL;
1755
Daniel Veillarde57ec792003-09-10 10:50:59 +00001756 /*
1757 * Note: if prefix == NULL, the attribute is not in the default namespace
1758 */
1759 if (prefix != NULL)
1760 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, prefix);
1761
Daniel Veillard8a44e592003-09-15 14:50:06 +00001762 /*
1763 * allocate the node
1764 */
1765 if (ctxt->freeAttrs != NULL) {
1766 ret = ctxt->freeAttrs;
1767 ctxt->freeAttrs = ret->next;
Daniel Veillard19895052003-09-17 13:59:32 +00001768 ctxt->freeAttrsNr--;
Daniel Veillard8a44e592003-09-15 14:50:06 +00001769 memset(ret, 0, sizeof(xmlAttr));
1770 ret->type = XML_ATTRIBUTE_NODE;
Daniel Veillarde57ec792003-09-10 10:50:59 +00001771
Daniel Veillard8a44e592003-09-15 14:50:06 +00001772 ret->parent = ctxt->node;
1773 ret->doc = ctxt->myDoc;
1774 ret->ns = namespace;
Daniel Veillarde57ec792003-09-10 10:50:59 +00001775
Daniel Veillard8a44e592003-09-15 14:50:06 +00001776 if (ctxt->dictNames)
1777 ret->name = localname;
1778 else
1779 ret->name = xmlStrdup(localname);
1780
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001781 /* link at the end to preserv order, TODO speed up with a last */
1782 if (ctxt->node->properties == NULL) {
1783 ctxt->node->properties = ret;
1784 } else {
1785 xmlAttrPtr prev = ctxt->node->properties;
1786
1787 while (prev->next != NULL) prev = prev->next;
1788 prev->next = ret;
1789 ret->prev = prev;
1790 }
1791
Daniel Veillard8a44e592003-09-15 14:50:06 +00001792 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1793 xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
1794 } else {
1795 if (ctxt->dictNames)
1796 ret = xmlNewNsPropEatName(ctxt->node, namespace,
1797 (xmlChar *) localname, NULL);
1798 else
1799 ret = xmlNewNsProp(ctxt->node, namespace, localname, NULL);
1800 if (ret == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001801 xmlErrMemory(ctxt, "xmlSAX2AttributeNs");
Daniel Veillard8a44e592003-09-15 14:50:06 +00001802 return;
Daniel Veillarde57ec792003-09-10 10:50:59 +00001803 }
1804 }
1805
Daniel Veillard8a44e592003-09-15 14:50:06 +00001806 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
1807 xmlNodePtr tmp;
1808
Daniel Veillard19895052003-09-17 13:59:32 +00001809 /*
1810 * We know that if there is an entity reference, then
1811 * the string has been dup'ed and terminates with 0
1812 * otherwise with ' or "
1813 */
1814 if (*valueend != 0) {
1815 tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
1816 ret->children = tmp;
1817 ret->last = tmp;
1818 if (tmp != NULL) {
1819 tmp->doc = ret->doc;
1820 tmp->parent = (xmlNodePtr) ret;
1821 }
1822 } else {
1823 ret->children = xmlStringLenGetNodeList(ctxt->myDoc, value,
1824 valueend - value);
1825 tmp = ret->children;
1826 while (tmp != NULL) {
Daniel Veillard8de5c0b2004-10-07 13:14:19 +00001827 tmp->doc = ret->doc;
Daniel Veillard19895052003-09-17 13:59:32 +00001828 tmp->parent = (xmlNodePtr) ret;
1829 if (tmp->next == NULL)
1830 ret->last = tmp;
1831 tmp = tmp->next;
1832 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00001833 }
1834 } else if (value != NULL) {
Daniel Veillard19895052003-09-17 13:59:32 +00001835 xmlNodePtr tmp;
1836
1837 tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
1838 ret->children = tmp;
1839 ret->last = tmp;
1840 if (tmp != NULL) {
1841 tmp->doc = ret->doc;
1842 tmp->parent = (xmlNodePtr) ret;
1843 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00001844 }
1845
Daniel Veillard4432df22003-09-28 18:58:27 +00001846#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00001847 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
1848 ctxt->myDoc && ctxt->myDoc->intSubset) {
1849 /*
1850 * If we don't substitute entities, the validation should be
1851 * done on a value with replaced entities anyway.
1852 */
1853 if (!ctxt->replaceEntities) {
1854 dup = xmlSAX2DecodeAttrEntities(ctxt, value, valueend);
1855 if (dup == NULL) {
Daniel Veillard62998c02003-09-15 12:56:36 +00001856 if (*valueend == 0) {
1857 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1858 ctxt->myDoc, ctxt->node, ret, value);
1859 } else {
1860 /*
1861 * That should already be normalized.
1862 * cheaper to finally allocate here than duplicate
1863 * entry points in the full validation code
1864 */
1865 dup = xmlStrndup(value, valueend - value);
Daniel Veillarde57ec792003-09-10 10:50:59 +00001866
Daniel Veillard62998c02003-09-15 12:56:36 +00001867 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1868 ctxt->myDoc, ctxt->node, ret, dup);
1869 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00001870 } else {
Daniel Veillard62998c02003-09-15 12:56:36 +00001871 /*
1872 * dup now contains a string of the flattened attribute
1873 * content with entities substitued. Check if we need to
1874 * apply an extra layer of normalization.
Daniel Veillarde57ec792003-09-10 10:50:59 +00001875 * It need to be done twice ... it's an extra burden related
1876 * to the ability to keep references in attributes
1877 */
Daniel Veillard62998c02003-09-15 12:56:36 +00001878 if (ctxt->attsSpecial != NULL) {
1879 xmlChar *nvalnorm;
1880 xmlChar fn[50];
1881 xmlChar *fullname;
1882
1883 fullname = xmlBuildQName(localname, prefix, fn, 50);
1884 if (fullname != NULL) {
1885 ctxt->vctxt.valid = 1;
1886 nvalnorm = xmlValidCtxtNormalizeAttributeValue(
1887 &ctxt->vctxt, ctxt->myDoc,
1888 ctxt->node, fullname, dup);
1889 if (ctxt->vctxt.valid != 1)
1890 ctxt->valid = 0;
1891
1892 if ((fullname != fn) && (fullname != localname))
1893 xmlFree(fullname);
1894 if (nvalnorm != NULL) {
1895 xmlFree(dup);
1896 dup = nvalnorm;
1897 }
1898 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00001899 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00001900
1901 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1902 ctxt->myDoc, ctxt->node, ret, dup);
1903 }
1904 } else {
Daniel Veillard8e36e6a2003-09-10 10:50:59 +00001905 /*
1906 * if entities already have been substitued, then
1907 * the attribute as passed is already normalized
1908 */
Daniel Veillarde57ec792003-09-10 10:50:59 +00001909 dup = xmlStrndup(value, valueend - value);
1910
1911 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1912 ctxt->myDoc, ctxt->node, ret, dup);
1913 }
Daniel Veillard4432df22003-09-28 18:58:27 +00001914 } else
1915#endif /* LIBXML_VALID_ENABLED */
1916 if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
Daniel Veillarde57ec792003-09-10 10:50:59 +00001917 (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
1918 ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
1919 /*
1920 * when validating, the ID registration is done at the attribute
1921 * validation level. Otherwise we have to do specific handling here.
1922 */
1923 if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) {
1924 /* might be worth duplicate entry points and not copy */
1925 if (dup == NULL)
1926 dup = xmlStrndup(value, valueend - value);
1927 xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
1928 } else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) {
1929 if (dup == NULL)
1930 dup = xmlStrndup(value, valueend - value);
1931 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, dup, ret);
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00001932 } else if ((prefix == ctxt->str_xml) &&
1933 (localname[0] == 'i') && (localname[1] == 'd') &&
1934 (localname[2] == 0)) {
1935 /*
1936 * Add the xml:id value
1937 *
1938 * Open issue: normalization of the value.
1939 */
1940 if (dup == NULL)
1941 dup = xmlStrndup(value, valueend - value);
William M. Brack5ef2f812004-05-23 23:56:47 +00001942#ifdef LIBXML_VALID_ENABLED
Daniel Veillard68cb4b22004-04-18 20:55:39 +00001943 if (xmlValidateNCName(dup, 1) != 0) {
1944 xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
1945 "xml:id : attribute value %s is not an NCName\n",
1946 (const char *) dup, NULL);
1947 }
William M. Brack3f147372004-05-22 01:09:26 +00001948#endif
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00001949 xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
1950 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00001951 }
1952 if (dup != NULL)
1953 xmlFree(dup);
1954}
1955
1956/**
1957 * xmlSAX2StartElementNs:
1958 * @ctx: the user data (XML parser context)
1959 * @localname: the local name of the element
1960 * @prefix: the element namespace prefix if available
1961 * @URI: the element namespace name if available
1962 * @nb_namespaces: number of namespace definitions on that node
1963 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
1964 * @nb_attributes: the number of attributes on that node
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00001965 * @nb_defaulted: the number of defaulted attributes.
Daniel Veillarde57ec792003-09-10 10:50:59 +00001966 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
1967 * attribute values.
1968 *
1969 * SAX2 callback when an element start has been detected by the parser.
1970 * It provides the namespace informations for the element, as well as
1971 * the new namespace declarations on the element.
1972 */
1973void
1974xmlSAX2StartElementNs(void *ctx,
1975 const xmlChar *localname,
1976 const xmlChar *prefix,
1977 const xmlChar *URI,
1978 int nb_namespaces,
1979 const xmlChar **namespaces,
1980 int nb_attributes,
1981 int nb_defaulted,
1982 const xmlChar **attributes)
1983{
1984 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1985 xmlNodePtr ret;
1986 xmlNodePtr parent = ctxt->node;
1987 xmlNsPtr last = NULL, ns;
1988 const xmlChar *uri, *pref;
1989 int i, j;
1990
1991 /*
1992 * First check on validity:
1993 */
1994 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
1995 ((ctxt->myDoc->intSubset == NULL) ||
1996 ((ctxt->myDoc->intSubset->notations == NULL) &&
1997 (ctxt->myDoc->intSubset->elements == NULL) &&
1998 (ctxt->myDoc->intSubset->attributes == NULL) &&
1999 (ctxt->myDoc->intSubset->entities == NULL)))) {
Daniel Veillardf88d8cf2003-12-08 10:25:02 +00002000 xmlErrValid(ctxt, XML_ERR_NO_DTD,
2001 "Validation failed: no DTD found !", NULL, NULL);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002002 ctxt->validate = 0;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002003 }
2004
Daniel Veillard8a44e592003-09-15 14:50:06 +00002005 /*
2006 * allocate the node
2007 */
2008 if (ctxt->freeElems != NULL) {
2009 ret = ctxt->freeElems;
2010 ctxt->freeElems = ret->next;
Daniel Veillard19895052003-09-17 13:59:32 +00002011 ctxt->freeElemsNr--;
Daniel Veillard8a44e592003-09-15 14:50:06 +00002012 memset(ret, 0, sizeof(xmlNode));
2013 ret->type = XML_ELEMENT_NODE;
2014
2015 if (ctxt->dictNames)
2016 ret->name = localname;
William M. Brack9f797ab2004-07-28 07:40:12 +00002017 else {
Daniel Veillard8a44e592003-09-15 14:50:06 +00002018 ret->name = xmlStrdup(localname);
William M. Brack9f797ab2004-07-28 07:40:12 +00002019 if (ret->name == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002020 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
William M. Brack9f797ab2004-07-28 07:40:12 +00002021 return;
2022 }
2023 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00002024 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2025 xmlRegisterNodeDefaultValue(ret);
2026 } else {
2027 if (ctxt->dictNames)
2028 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
2029 (xmlChar *) localname, NULL);
2030 else
2031 ret = xmlNewDocNode(ctxt->myDoc, NULL, localname, NULL);
2032 if (ret == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002033 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
Daniel Veillard8a44e592003-09-15 14:50:06 +00002034 return;
2035 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002036 }
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002037 if (ctxt->linenumbers) {
Daniel Veillard3e35f8e2003-10-21 00:05:38 +00002038 if (ctxt->input != NULL) {
2039 if (ctxt->input->line < 65535)
2040 ret->line = (short) ctxt->input->line;
2041 else
2042 ret->line = 65535;
2043 }
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002044 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00002045
Daniel Veillard29b17482004-08-16 00:39:03 +00002046 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
Daniel Veillarde57ec792003-09-10 10:50:59 +00002047 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002048 }
2049 /*
2050 * Build the namespace list
2051 */
2052 for (i = 0,j = 0;j < nb_namespaces;j++) {
2053 pref = namespaces[i++];
2054 uri = namespaces[i++];
2055 ns = xmlNewNs(NULL, uri, pref);
2056 if (ns != NULL) {
2057 if (last == NULL) {
2058 ret->nsDef = last = ns;
2059 } else {
2060 last->next = ns;
2061 last = ns;
2062 }
2063 if ((URI != NULL) && (prefix == pref))
2064 ret->ns = ns;
2065 } else {
William M. Brack42331a92004-07-29 07:07:16 +00002066 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
Daniel Veillarde57ec792003-09-10 10:50:59 +00002067 return;
2068 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002069#ifdef LIBXML_VALID_ENABLED
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002070 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
2071 ctxt->myDoc && ctxt->myDoc->intSubset) {
2072 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
2073 ret, prefix, ns, uri);
2074 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002075#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002076 }
2077 ctxt->nodemem = -1;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002078
2079 /*
2080 * We are parsing a new node.
2081 */
2082 nodePush(ctxt, ret);
2083
2084 /*
2085 * Link the child element
2086 */
2087 if (parent != NULL) {
2088 if (parent->type == XML_ELEMENT_NODE) {
2089 xmlAddChild(parent, ret);
2090 } else {
2091 xmlAddSibling(parent, ret);
2092 }
2093 }
2094
2095 /*
2096 * Insert the defaulted attributes from the DTD only if requested:
2097 */
2098 if ((nb_defaulted != 0) &&
2099 ((ctxt->loadsubset & XML_COMPLETE_ATTRS) == 0))
2100 nb_attributes -= nb_defaulted;
2101
2102 /*
2103 * Search the namespace if it wasn't already found
William M. Brackbf5cf212004-08-31 06:47:17 +00002104 * Note that, if prefix is NULL, this searches for the default Ns
Daniel Veillarde57ec792003-09-10 10:50:59 +00002105 */
2106 if ((URI != NULL) && (ret->ns == NULL)) {
William M. Brackbf5cf212004-08-31 06:47:17 +00002107 ret->ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002108 if (ret->ns == NULL) {
2109 ns = xmlNewNs(ret, NULL, prefix);
William M. Brack9f797ab2004-07-28 07:40:12 +00002110 if (ns == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002111 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
William M. Brack9f797ab2004-07-28 07:40:12 +00002112 return;
2113 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002114 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
2115 ctxt->sax->warning(ctxt->userData,
2116 "Namespace prefix %s was not found\n", prefix);
2117 }
2118 }
2119
2120 /*
2121 * process all the other attributes
2122 */
2123 if (nb_attributes > 0) {
2124 for (j = 0,i = 0;i < nb_attributes;i++,j+=5) {
2125 xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1],
2126 attributes[j+3], attributes[j+4]);
2127 }
2128 }
2129
Daniel Veillard4432df22003-09-28 18:58:27 +00002130#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002131 /*
2132 * If it's the Document root, finish the DTD validation and
2133 * check the document root element for validity
2134 */
2135 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
2136 int chk;
2137
2138 chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
2139 if (chk <= 0)
2140 ctxt->valid = 0;
2141 if (chk < 0)
2142 ctxt->wellFormed = 0;
2143 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
2144 ctxt->vctxt.finishDtd = 1;
2145 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002146#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002147}
2148
2149/**
2150 * xmlSAX2EndElementNs:
2151 * @ctx: the user data (XML parser context)
2152 * @localname: the local name of the element
2153 * @prefix: the element namespace prefix if available
2154 * @URI: the element namespace name if available
2155 *
2156 * SAX2 callback when an element end has been detected by the parser.
2157 * It provides the namespace informations for the element.
2158 */
2159void
2160xmlSAX2EndElementNs(void *ctx,
2161 const xmlChar * localname ATTRIBUTE_UNUSED,
2162 const xmlChar * prefix ATTRIBUTE_UNUSED,
2163 const xmlChar * URI ATTRIBUTE_UNUSED)
2164{
2165 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2166 xmlParserNodeInfo node_info;
2167 xmlNodePtr cur = ctxt->node;
2168
2169 /* Capture end position and add node */
2170 if ((ctxt->record_info) && (cur != NULL)) {
2171 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
2172 node_info.end_line = ctxt->input->line;
2173 node_info.node = cur;
2174 xmlParserAddNodeInfo(ctxt, &node_info);
2175 }
2176 ctxt->nodemem = -1;
2177
Daniel Veillard4432df22003-09-28 18:58:27 +00002178#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002179 if (ctxt->validate && ctxt->wellFormed &&
2180 ctxt->myDoc && ctxt->myDoc->intSubset)
2181 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, cur);
Daniel Veillard4432df22003-09-28 18:58:27 +00002182#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002183
2184 /*
2185 * end of parsing of this node.
2186 */
2187 nodePop(ctxt);
2188}
2189
Daniel Veillard1af9a412003-08-20 22:54:39 +00002190/**
2191 * xmlSAX2Reference:
2192 * @ctx: the user data (XML parser context)
2193 * @name: The entity name
2194 *
2195 * called when an entity xmlSAX2Reference is detected.
2196 */
2197void
2198xmlSAX2Reference(void *ctx, const xmlChar *name)
2199{
2200 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2201 xmlNodePtr ret;
2202
2203#ifdef DEBUG_SAX
2204 xmlGenericError(xmlGenericErrorContext,
2205 "SAX.xmlSAX2Reference(%s)\n", name);
2206#endif
2207 if (name[0] == '#')
2208 ret = xmlNewCharRef(ctxt->myDoc, name);
2209 else
2210 ret = xmlNewReference(ctxt->myDoc, name);
2211#ifdef DEBUG_SAX_TREE
2212 xmlGenericError(xmlGenericErrorContext,
2213 "add xmlSAX2Reference %s to %s \n", name, ctxt->node->name);
2214#endif
2215 xmlAddChild(ctxt->node, ret);
2216}
2217
2218/**
2219 * xmlSAX2Characters:
2220 * @ctx: the user data (XML parser context)
2221 * @ch: a xmlChar string
2222 * @len: the number of xmlChar
2223 *
2224 * receiving some chars from the parser.
2225 */
2226void
2227xmlSAX2Characters(void *ctx, const xmlChar *ch, int len)
2228{
2229 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2230 xmlNodePtr lastChild;
2231
2232#ifdef DEBUG_SAX
2233 xmlGenericError(xmlGenericErrorContext,
2234 "SAX.xmlSAX2Characters(%.30s, %d)\n", ch, len);
2235#endif
2236 /*
2237 * Handle the data if any. If there is no child
2238 * add it as content, otherwise if the last child is text,
2239 * concatenate it, else create a new node of type text.
2240 */
2241
2242 if (ctxt->node == NULL) {
2243#ifdef DEBUG_SAX_TREE
2244 xmlGenericError(xmlGenericErrorContext,
2245 "add chars: ctxt->node == NULL !\n");
2246#endif
2247 return;
2248 }
Daniel Veillard19895052003-09-17 13:59:32 +00002249 lastChild = ctxt->node->last;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002250#ifdef DEBUG_SAX_TREE
2251 xmlGenericError(xmlGenericErrorContext,
2252 "add chars to %s \n", ctxt->node->name);
2253#endif
2254
2255 /*
2256 * Here we needed an accelerator mechanism in case of very large
2257 * elements. Use an attribute in the structure !!!
2258 */
2259 if (lastChild == NULL) {
Daniel Veillard19895052003-09-17 13:59:32 +00002260 lastChild = xmlSAX2TextNode(ctxt, ch, len);
2261 if (lastChild != NULL) {
2262 ctxt->node->children = lastChild;
2263 ctxt->node->last = lastChild;
2264 lastChild->parent = ctxt->node;
2265 lastChild->doc = ctxt->node->doc;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002266 ctxt->nodelen = len;
2267 ctxt->nodemem = len + 1;
William M. Bracka3215c72004-07-31 16:24:01 +00002268 } else {
2269 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
2270 return;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002271 }
2272 } else {
2273 int coalesceText = (lastChild != NULL) &&
2274 (lastChild->type == XML_TEXT_NODE) &&
2275 (lastChild->name == xmlStringText);
2276 if ((coalesceText) && (ctxt->nodemem != 0)) {
2277 /*
2278 * The whole point of maintaining nodelen and nodemem,
2279 * xmlTextConcat is too costly, i.e. compute length,
2280 * reallocate a new buffer, move data, append ch. Here
2281 * We try to minimaze realloc() uses and avoid copying
2282 * and recomputing length over and over.
2283 */
Daniel Veillard2b0f8792003-10-10 19:36:36 +00002284 if ((ctxt->nodemem == ctxt->nodelen + 1) &&
2285 (xmlDictOwns(ctxt->dict, lastChild->content))) {
2286 lastChild->content = xmlStrdup(lastChild->content);
2287 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00002288 if (ctxt->nodelen + len >= ctxt->nodemem) {
2289 xmlChar *newbuf;
2290 int size;
2291
2292 size = ctxt->nodemem + len;
2293 size *= 2;
2294 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
2295 if (newbuf == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002296 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
Daniel Veillard1af9a412003-08-20 22:54:39 +00002297 return;
2298 }
2299 ctxt->nodemem = size;
2300 lastChild->content = newbuf;
2301 }
2302 memcpy(&lastChild->content[ctxt->nodelen], ch, len);
2303 ctxt->nodelen += len;
2304 lastChild->content[ctxt->nodelen] = 0;
2305 } else if (coalesceText) {
2306 if (xmlTextConcat(lastChild, ch, len)) {
William M. Brack42331a92004-07-29 07:07:16 +00002307 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
Daniel Veillard1af9a412003-08-20 22:54:39 +00002308 }
2309 if (ctxt->node->children != NULL) {
2310 ctxt->nodelen = xmlStrlen(lastChild->content);
2311 ctxt->nodemem = ctxt->nodelen + 1;
2312 }
2313 } else {
2314 /* Mixed content, first time */
Daniel Veillard19895052003-09-17 13:59:32 +00002315 lastChild = xmlSAX2TextNode(ctxt, ch, len);
2316 if (lastChild != NULL) {
Daniel Veillard1af9a412003-08-20 22:54:39 +00002317 xmlAddChild(ctxt->node, lastChild);
2318 if (ctxt->node->children != NULL) {
2319 ctxt->nodelen = len;
2320 ctxt->nodemem = len + 1;
2321 }
2322 }
2323 }
2324 }
2325}
2326
2327/**
2328 * xmlSAX2IgnorableWhitespace:
2329 * @ctx: the user data (XML parser context)
2330 * @ch: a xmlChar string
2331 * @len: the number of xmlChar
2332 *
2333 * receiving some ignorable whitespaces from the parser.
2334 * UNUSED: by default the DOM building will use xmlSAX2Characters
2335 */
2336void
2337xmlSAX2IgnorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
2338{
2339 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
2340#ifdef DEBUG_SAX
2341 xmlGenericError(xmlGenericErrorContext,
2342 "SAX.xmlSAX2IgnorableWhitespace(%.30s, %d)\n", ch, len);
2343#endif
2344}
2345
2346/**
2347 * xmlSAX2ProcessingInstruction:
2348 * @ctx: the user data (XML parser context)
2349 * @target: the target name
2350 * @data: the PI data's
2351 *
2352 * A processing instruction has been parsed.
2353 */
2354void
2355xmlSAX2ProcessingInstruction(void *ctx, const xmlChar *target,
2356 const xmlChar *data)
2357{
2358 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2359 xmlNodePtr ret;
2360 xmlNodePtr parent = ctxt->node;
2361
2362#ifdef DEBUG_SAX
2363 xmlGenericError(xmlGenericErrorContext,
2364 "SAX.xmlSAX2ProcessingInstruction(%s, %s)\n", target, data);
2365#endif
2366
2367 ret = xmlNewPI(target, data);
2368 if (ret == NULL) return;
2369 parent = ctxt->node;
2370
2371 if (ctxt->inSubset == 1) {
2372 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2373 return;
2374 } else if (ctxt->inSubset == 2) {
2375 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2376 return;
2377 }
2378 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
2379#ifdef DEBUG_SAX_TREE
2380 xmlGenericError(xmlGenericErrorContext,
2381 "Setting PI %s as root\n", target);
2382#endif
2383 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2384 return;
2385 }
2386 if (parent->type == XML_ELEMENT_NODE) {
2387#ifdef DEBUG_SAX_TREE
2388 xmlGenericError(xmlGenericErrorContext,
2389 "adding PI %s child to %s\n", target, parent->name);
2390#endif
2391 xmlAddChild(parent, ret);
2392 } else {
2393#ifdef DEBUG_SAX_TREE
2394 xmlGenericError(xmlGenericErrorContext,
2395 "adding PI %s sibling to ", target);
2396 xmlDebugDumpOneNode(stderr, parent, 0);
2397#endif
2398 xmlAddSibling(parent, ret);
2399 }
2400}
2401
2402/**
2403 * xmlSAX2Comment:
2404 * @ctx: the user data (XML parser context)
2405 * @value: the xmlSAX2Comment content
2406 *
2407 * A xmlSAX2Comment has been parsed.
2408 */
2409void
2410xmlSAX2Comment(void *ctx, const xmlChar *value)
2411{
2412 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2413 xmlNodePtr ret;
2414 xmlNodePtr parent = ctxt->node;
2415
2416#ifdef DEBUG_SAX
2417 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2Comment(%s)\n", value);
2418#endif
2419 ret = xmlNewDocComment(ctxt->myDoc, value);
2420 if (ret == NULL) return;
2421
2422 if (ctxt->inSubset == 1) {
2423 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2424 return;
2425 } else if (ctxt->inSubset == 2) {
2426 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2427 return;
2428 }
2429 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
2430#ifdef DEBUG_SAX_TREE
2431 xmlGenericError(xmlGenericErrorContext,
2432 "Setting xmlSAX2Comment as root\n");
2433#endif
2434 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2435 return;
2436 }
2437 if (parent->type == XML_ELEMENT_NODE) {
2438#ifdef DEBUG_SAX_TREE
2439 xmlGenericError(xmlGenericErrorContext,
2440 "adding xmlSAX2Comment child to %s\n", parent->name);
2441#endif
2442 xmlAddChild(parent, ret);
2443 } else {
2444#ifdef DEBUG_SAX_TREE
2445 xmlGenericError(xmlGenericErrorContext,
2446 "adding xmlSAX2Comment sibling to ");
2447 xmlDebugDumpOneNode(stderr, parent, 0);
2448#endif
2449 xmlAddSibling(parent, ret);
2450 }
2451}
2452
2453/**
2454 * xmlSAX2CDataBlock:
2455 * @ctx: the user data (XML parser context)
2456 * @value: The pcdata content
2457 * @len: the block length
2458 *
2459 * called when a pcdata block has been parsed
2460 */
2461void
2462xmlSAX2CDataBlock(void *ctx, const xmlChar *value, int len)
2463{
2464 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2465 xmlNodePtr ret, lastChild;
2466
2467#ifdef DEBUG_SAX
2468 xmlGenericError(xmlGenericErrorContext,
2469 "SAX.pcdata(%.10s, %d)\n", value, len);
2470#endif
2471 lastChild = xmlGetLastChild(ctxt->node);
2472#ifdef DEBUG_SAX_TREE
2473 xmlGenericError(xmlGenericErrorContext,
2474 "add chars to %s \n", ctxt->node->name);
2475#endif
2476 if ((lastChild != NULL) &&
2477 (lastChild->type == XML_CDATA_SECTION_NODE)) {
2478 xmlTextConcat(lastChild, value, len);
2479 } else {
2480 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
2481 xmlAddChild(ctxt->node, ret);
2482 }
2483}
2484
Daniel Veillard62998c02003-09-15 12:56:36 +00002485static int xmlSAX2DefaultVersionValue = 2;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002486
Daniel Veillard81273902003-09-30 00:43:48 +00002487#ifdef LIBXML_SAX1_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002488/**
2489 * xmlSAXDefaultVersion:
2490 * @version: the version, 1 or 2
2491 *
2492 * Set the default version of SAX used globally by the library.
William M. Brack96d2eff2004-06-30 11:48:47 +00002493 * By default, during initialization the default is set to 2.
2494 * Note that it is generally a better coding style to use
2495 * xmlSAXVersion() to set up the version explicitly for a given
2496 * parsing context.
Daniel Veillarde57ec792003-09-10 10:50:59 +00002497 *
2498 * Returns the previous value in case of success and -1 in case of error.
2499 */
2500int
2501xmlSAXDefaultVersion(int version)
2502{
2503 int ret = xmlSAX2DefaultVersionValue;
2504
2505 if ((version != 1) && (version != 2))
2506 return(-1);
2507 xmlSAX2DefaultVersionValue = version;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002508 return(ret);
2509}
Daniel Veillard81273902003-09-30 00:43:48 +00002510#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002511
2512/**
2513 * xmlSAXVersion:
2514 * @hdlr: the SAX handler
2515 * @version: the version, 1 or 2
2516 *
2517 * Initialize the default XML SAX handler according to the version
2518 *
2519 * Returns 0 in case of success and -1 in case of error.
2520 */
2521int
2522xmlSAXVersion(xmlSAXHandler *hdlr, int version)
2523{
2524 if (hdlr == NULL) return(-1);
Daniel Veillard81273902003-09-30 00:43:48 +00002525 if (version == 2) {
Daniel Veillarde57ec792003-09-10 10:50:59 +00002526 hdlr->startElement = NULL;
2527 hdlr->endElement = NULL;
2528 hdlr->startElementNs = xmlSAX2StartElementNs;
2529 hdlr->endElementNs = xmlSAX2EndElementNs;
Daniel Veillardffbbed42003-10-10 14:46:54 +00002530 hdlr->serror = NULL;
Daniel Veillard092643b2003-09-25 14:29:29 +00002531 hdlr->initialized = XML_SAX2_MAGIC;
Daniel Veillard81273902003-09-30 00:43:48 +00002532#ifdef LIBXML_SAX1_ENABLED
2533 } else if (version == 1) {
2534 hdlr->startElement = xmlSAX2StartElement;
2535 hdlr->endElement = xmlSAX2EndElement;
2536 hdlr->initialized = 1;
2537#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002538 } else
2539 return(-1);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002540 hdlr->internalSubset = xmlSAX2InternalSubset;
2541 hdlr->externalSubset = xmlSAX2ExternalSubset;
2542 hdlr->isStandalone = xmlSAX2IsStandalone;
2543 hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
2544 hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
2545 hdlr->resolveEntity = xmlSAX2ResolveEntity;
2546 hdlr->getEntity = xmlSAX2GetEntity;
2547 hdlr->getParameterEntity = xmlSAX2GetParameterEntity;
2548 hdlr->entityDecl = xmlSAX2EntityDecl;
2549 hdlr->attributeDecl = xmlSAX2AttributeDecl;
2550 hdlr->elementDecl = xmlSAX2ElementDecl;
2551 hdlr->notationDecl = xmlSAX2NotationDecl;
2552 hdlr->unparsedEntityDecl = xmlSAX2UnparsedEntityDecl;
2553 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2554 hdlr->startDocument = xmlSAX2StartDocument;
2555 hdlr->endDocument = xmlSAX2EndDocument;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002556 hdlr->reference = xmlSAX2Reference;
2557 hdlr->characters = xmlSAX2Characters;
2558 hdlr->cdataBlock = xmlSAX2CDataBlock;
2559 hdlr->ignorableWhitespace = xmlSAX2Characters;
2560 hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
2561 hdlr->comment = xmlSAX2Comment;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002562 hdlr->warning = xmlParserWarning;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002563 hdlr->error = xmlParserError;
2564 hdlr->fatalError = xmlParserError;
2565
Daniel Veillarde57ec792003-09-10 10:50:59 +00002566 return(0);
2567}
2568
2569/**
2570 * xmlSAX2InitDefaultSAXHandler:
2571 * @hdlr: the SAX handler
2572 * @warning: flag if non-zero sets the handler warning procedure
2573 *
2574 * Initialize the default XML SAX2 handler
2575 */
2576void
2577xmlSAX2InitDefaultSAXHandler(xmlSAXHandler *hdlr, int warning)
2578{
2579 if ((hdlr == NULL) || (hdlr->initialized != 0))
2580 return;
2581
2582 xmlSAXVersion(hdlr, xmlSAX2DefaultVersionValue);
2583 if (warning == 0)
2584 hdlr->warning = NULL;
2585 else
2586 hdlr->warning = xmlParserWarning;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002587}
2588
2589/**
2590 * xmlDefaultSAXHandlerInit:
2591 *
2592 * Initialize the default SAX2 handler
2593 */
2594void
2595xmlDefaultSAXHandlerInit(void)
2596{
Daniel Veillard81273902003-09-30 00:43:48 +00002597#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard092643b2003-09-25 14:29:29 +00002598 xmlSAXVersion((xmlSAXHandlerPtr) &xmlDefaultSAXHandler, 1);
Daniel Veillard81273902003-09-30 00:43:48 +00002599#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00002600}
2601
2602#ifdef LIBXML_HTML_ENABLED
2603
2604/**
2605 * xmlSAX2InitHtmlDefaultSAXHandler:
2606 * @hdlr: the SAX handler
2607 *
2608 * Initialize the default HTML SAX2 handler
2609 */
2610void
2611xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr)
2612{
2613 if(hdlr->initialized != 0)
2614 return;
2615
2616 hdlr->internalSubset = xmlSAX2InternalSubset;
2617 hdlr->externalSubset = NULL;
2618 hdlr->isStandalone = NULL;
2619 hdlr->hasInternalSubset = NULL;
2620 hdlr->hasExternalSubset = NULL;
2621 hdlr->resolveEntity = NULL;
2622 hdlr->getEntity = xmlSAX2GetEntity;
2623 hdlr->getParameterEntity = NULL;
2624 hdlr->entityDecl = NULL;
2625 hdlr->attributeDecl = NULL;
2626 hdlr->elementDecl = NULL;
2627 hdlr->notationDecl = NULL;
2628 hdlr->unparsedEntityDecl = NULL;
2629 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2630 hdlr->startDocument = xmlSAX2StartDocument;
2631 hdlr->endDocument = xmlSAX2EndDocument;
2632 hdlr->startElement = xmlSAX2StartElement;
2633 hdlr->endElement = xmlSAX2EndElement;
2634 hdlr->reference = NULL;
2635 hdlr->characters = xmlSAX2Characters;
2636 hdlr->cdataBlock = xmlSAX2CDataBlock;
2637 hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
Daniel Veillardfc484dd2004-10-22 14:34:23 +00002638 hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002639 hdlr->comment = xmlSAX2Comment;
2640 hdlr->warning = xmlParserWarning;
2641 hdlr->error = xmlParserError;
2642 hdlr->fatalError = xmlParserError;
2643
Daniel Veillard092643b2003-09-25 14:29:29 +00002644 hdlr->initialized = 1;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002645}
2646
2647/**
2648 * htmlDefaultSAXHandlerInit:
2649 *
2650 * Initialize the default SAX handler
2651 */
2652void
2653htmlDefaultSAXHandlerInit(void)
2654{
Daniel Veillard092643b2003-09-25 14:29:29 +00002655 xmlSAX2InitHtmlDefaultSAXHandler((xmlSAXHandlerPtr) &htmlDefaultSAXHandler);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002656}
2657
2658#endif /* LIBXML_HTML_ENABLED */
2659
2660#ifdef LIBXML_DOCB_ENABLED
2661
2662/**
2663 * xmlSAX2InitDocbDefaultSAXHandler:
2664 * @hdlr: the SAX handler
2665 *
2666 * Initialize the default DocBook SAX2 handler
2667 */
2668void
2669xmlSAX2InitDocbDefaultSAXHandler(xmlSAXHandler *hdlr)
2670{
2671 if(hdlr->initialized != 0)
2672 return;
2673
2674 hdlr->internalSubset = xmlSAX2InternalSubset;
2675 hdlr->externalSubset = NULL;
2676 hdlr->isStandalone = xmlSAX2IsStandalone;
2677 hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
2678 hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
2679 hdlr->resolveEntity = xmlSAX2ResolveEntity;
2680 hdlr->getEntity = xmlSAX2GetEntity;
2681 hdlr->getParameterEntity = NULL;
2682 hdlr->entityDecl = xmlSAX2EntityDecl;
2683 hdlr->attributeDecl = NULL;
2684 hdlr->elementDecl = NULL;
2685 hdlr->notationDecl = NULL;
2686 hdlr->unparsedEntityDecl = NULL;
2687 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2688 hdlr->startDocument = xmlSAX2StartDocument;
2689 hdlr->endDocument = xmlSAX2EndDocument;
2690 hdlr->startElement = xmlSAX2StartElement;
2691 hdlr->endElement = xmlSAX2EndElement;
2692 hdlr->reference = xmlSAX2Reference;
2693 hdlr->characters = xmlSAX2Characters;
2694 hdlr->cdataBlock = NULL;
2695 hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
2696 hdlr->processingInstruction = NULL;
2697 hdlr->comment = xmlSAX2Comment;
2698 hdlr->warning = xmlParserWarning;
2699 hdlr->error = xmlParserError;
2700 hdlr->fatalError = xmlParserError;
2701
Daniel Veillardffbbed42003-10-10 14:46:54 +00002702 hdlr->initialized = 1;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002703}
2704
2705/**
2706 * docbDefaultSAXHandlerInit:
2707 *
2708 * Initialize the default SAX handler
2709 */
2710void
2711docbDefaultSAXHandlerInit(void)
2712{
Daniel Veillard092643b2003-09-25 14:29:29 +00002713 xmlSAX2InitDocbDefaultSAXHandler((xmlSAXHandlerPtr) &docbDefaultSAXHandler);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002714}
2715
2716#endif /* LIBXML_DOCB_ENABLED */