blob: c705cc37b7af39222901b75674bb2be63434dd44 [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) {
1827 tmp->parent = (xmlNodePtr) ret;
1828 if (tmp->next == NULL)
1829 ret->last = tmp;
1830 tmp = tmp->next;
1831 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00001832 }
1833 } else if (value != NULL) {
Daniel Veillard19895052003-09-17 13:59:32 +00001834 xmlNodePtr tmp;
1835
1836 tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
1837 ret->children = tmp;
1838 ret->last = tmp;
1839 if (tmp != NULL) {
1840 tmp->doc = ret->doc;
1841 tmp->parent = (xmlNodePtr) ret;
1842 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00001843 }
1844
Daniel Veillard4432df22003-09-28 18:58:27 +00001845#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00001846 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
1847 ctxt->myDoc && ctxt->myDoc->intSubset) {
1848 /*
1849 * If we don't substitute entities, the validation should be
1850 * done on a value with replaced entities anyway.
1851 */
1852 if (!ctxt->replaceEntities) {
1853 dup = xmlSAX2DecodeAttrEntities(ctxt, value, valueend);
1854 if (dup == NULL) {
Daniel Veillard62998c02003-09-15 12:56:36 +00001855 if (*valueend == 0) {
1856 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1857 ctxt->myDoc, ctxt->node, ret, value);
1858 } else {
1859 /*
1860 * That should already be normalized.
1861 * cheaper to finally allocate here than duplicate
1862 * entry points in the full validation code
1863 */
1864 dup = xmlStrndup(value, valueend - value);
Daniel Veillarde57ec792003-09-10 10:50:59 +00001865
Daniel Veillard62998c02003-09-15 12:56:36 +00001866 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1867 ctxt->myDoc, ctxt->node, ret, dup);
1868 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00001869 } else {
Daniel Veillard62998c02003-09-15 12:56:36 +00001870 /*
1871 * dup now contains a string of the flattened attribute
1872 * content with entities substitued. Check if we need to
1873 * apply an extra layer of normalization.
Daniel Veillarde57ec792003-09-10 10:50:59 +00001874 * It need to be done twice ... it's an extra burden related
1875 * to the ability to keep references in attributes
1876 */
Daniel Veillard62998c02003-09-15 12:56:36 +00001877 if (ctxt->attsSpecial != NULL) {
1878 xmlChar *nvalnorm;
1879 xmlChar fn[50];
1880 xmlChar *fullname;
1881
1882 fullname = xmlBuildQName(localname, prefix, fn, 50);
1883 if (fullname != NULL) {
1884 ctxt->vctxt.valid = 1;
1885 nvalnorm = xmlValidCtxtNormalizeAttributeValue(
1886 &ctxt->vctxt, ctxt->myDoc,
1887 ctxt->node, fullname, dup);
1888 if (ctxt->vctxt.valid != 1)
1889 ctxt->valid = 0;
1890
1891 if ((fullname != fn) && (fullname != localname))
1892 xmlFree(fullname);
1893 if (nvalnorm != NULL) {
1894 xmlFree(dup);
1895 dup = nvalnorm;
1896 }
1897 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00001898 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00001899
1900 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1901 ctxt->myDoc, ctxt->node, ret, dup);
1902 }
1903 } else {
Daniel Veillard8e36e6a2003-09-10 10:50:59 +00001904 /*
1905 * if entities already have been substitued, then
1906 * the attribute as passed is already normalized
1907 */
Daniel Veillarde57ec792003-09-10 10:50:59 +00001908 dup = xmlStrndup(value, valueend - value);
1909
1910 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1911 ctxt->myDoc, ctxt->node, ret, dup);
1912 }
Daniel Veillard4432df22003-09-28 18:58:27 +00001913 } else
1914#endif /* LIBXML_VALID_ENABLED */
1915 if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
Daniel Veillarde57ec792003-09-10 10:50:59 +00001916 (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
1917 ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
1918 /*
1919 * when validating, the ID registration is done at the attribute
1920 * validation level. Otherwise we have to do specific handling here.
1921 */
1922 if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) {
1923 /* might be worth duplicate entry points and not copy */
1924 if (dup == NULL)
1925 dup = xmlStrndup(value, valueend - value);
1926 xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
1927 } else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) {
1928 if (dup == NULL)
1929 dup = xmlStrndup(value, valueend - value);
1930 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, dup, ret);
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00001931 } else if ((prefix == ctxt->str_xml) &&
1932 (localname[0] == 'i') && (localname[1] == 'd') &&
1933 (localname[2] == 0)) {
1934 /*
1935 * Add the xml:id value
1936 *
1937 * Open issue: normalization of the value.
1938 */
1939 if (dup == NULL)
1940 dup = xmlStrndup(value, valueend - value);
William M. Brack5ef2f812004-05-23 23:56:47 +00001941#ifdef LIBXML_VALID_ENABLED
Daniel Veillard68cb4b22004-04-18 20:55:39 +00001942 if (xmlValidateNCName(dup, 1) != 0) {
1943 xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
1944 "xml:id : attribute value %s is not an NCName\n",
1945 (const char *) dup, NULL);
1946 }
William M. Brack3f147372004-05-22 01:09:26 +00001947#endif
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00001948 xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
1949 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00001950 }
1951 if (dup != NULL)
1952 xmlFree(dup);
1953}
1954
1955/**
1956 * xmlSAX2StartElementNs:
1957 * @ctx: the user data (XML parser context)
1958 * @localname: the local name of the element
1959 * @prefix: the element namespace prefix if available
1960 * @URI: the element namespace name if available
1961 * @nb_namespaces: number of namespace definitions on that node
1962 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
1963 * @nb_attributes: the number of attributes on that node
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00001964 * @nb_defaulted: the number of defaulted attributes.
Daniel Veillarde57ec792003-09-10 10:50:59 +00001965 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
1966 * attribute values.
1967 *
1968 * SAX2 callback when an element start has been detected by the parser.
1969 * It provides the namespace informations for the element, as well as
1970 * the new namespace declarations on the element.
1971 */
1972void
1973xmlSAX2StartElementNs(void *ctx,
1974 const xmlChar *localname,
1975 const xmlChar *prefix,
1976 const xmlChar *URI,
1977 int nb_namespaces,
1978 const xmlChar **namespaces,
1979 int nb_attributes,
1980 int nb_defaulted,
1981 const xmlChar **attributes)
1982{
1983 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1984 xmlNodePtr ret;
1985 xmlNodePtr parent = ctxt->node;
1986 xmlNsPtr last = NULL, ns;
1987 const xmlChar *uri, *pref;
1988 int i, j;
1989
1990 /*
1991 * First check on validity:
1992 */
1993 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
1994 ((ctxt->myDoc->intSubset == NULL) ||
1995 ((ctxt->myDoc->intSubset->notations == NULL) &&
1996 (ctxt->myDoc->intSubset->elements == NULL) &&
1997 (ctxt->myDoc->intSubset->attributes == NULL) &&
1998 (ctxt->myDoc->intSubset->entities == NULL)))) {
Daniel Veillardf88d8cf2003-12-08 10:25:02 +00001999 xmlErrValid(ctxt, XML_ERR_NO_DTD,
2000 "Validation failed: no DTD found !", NULL, NULL);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002001 ctxt->validate = 0;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002002 }
2003
Daniel Veillard8a44e592003-09-15 14:50:06 +00002004 /*
2005 * allocate the node
2006 */
2007 if (ctxt->freeElems != NULL) {
2008 ret = ctxt->freeElems;
2009 ctxt->freeElems = ret->next;
Daniel Veillard19895052003-09-17 13:59:32 +00002010 ctxt->freeElemsNr--;
Daniel Veillard8a44e592003-09-15 14:50:06 +00002011 memset(ret, 0, sizeof(xmlNode));
2012 ret->type = XML_ELEMENT_NODE;
2013
2014 if (ctxt->dictNames)
2015 ret->name = localname;
William M. Brack9f797ab2004-07-28 07:40:12 +00002016 else {
Daniel Veillard8a44e592003-09-15 14:50:06 +00002017 ret->name = xmlStrdup(localname);
William M. Brack9f797ab2004-07-28 07:40:12 +00002018 if (ret->name == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002019 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
William M. Brack9f797ab2004-07-28 07:40:12 +00002020 return;
2021 }
2022 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00002023 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2024 xmlRegisterNodeDefaultValue(ret);
2025 } else {
2026 if (ctxt->dictNames)
2027 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
2028 (xmlChar *) localname, NULL);
2029 else
2030 ret = xmlNewDocNode(ctxt->myDoc, NULL, localname, NULL);
2031 if (ret == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002032 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
Daniel Veillard8a44e592003-09-15 14:50:06 +00002033 return;
2034 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002035 }
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002036 if (ctxt->linenumbers) {
Daniel Veillard3e35f8e2003-10-21 00:05:38 +00002037 if (ctxt->input != NULL) {
2038 if (ctxt->input->line < 65535)
2039 ret->line = (short) ctxt->input->line;
2040 else
2041 ret->line = 65535;
2042 }
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002043 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00002044
Daniel Veillard29b17482004-08-16 00:39:03 +00002045 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
Daniel Veillarde57ec792003-09-10 10:50:59 +00002046 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002047 }
2048 /*
2049 * Build the namespace list
2050 */
2051 for (i = 0,j = 0;j < nb_namespaces;j++) {
2052 pref = namespaces[i++];
2053 uri = namespaces[i++];
2054 ns = xmlNewNs(NULL, uri, pref);
2055 if (ns != NULL) {
2056 if (last == NULL) {
2057 ret->nsDef = last = ns;
2058 } else {
2059 last->next = ns;
2060 last = ns;
2061 }
2062 if ((URI != NULL) && (prefix == pref))
2063 ret->ns = ns;
2064 } else {
William M. Brack42331a92004-07-29 07:07:16 +00002065 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
Daniel Veillarde57ec792003-09-10 10:50:59 +00002066 return;
2067 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002068#ifdef LIBXML_VALID_ENABLED
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002069 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
2070 ctxt->myDoc && ctxt->myDoc->intSubset) {
2071 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
2072 ret, prefix, ns, uri);
2073 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002074#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002075 }
2076 ctxt->nodemem = -1;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002077
2078 /*
2079 * We are parsing a new node.
2080 */
2081 nodePush(ctxt, ret);
2082
2083 /*
2084 * Link the child element
2085 */
2086 if (parent != NULL) {
2087 if (parent->type == XML_ELEMENT_NODE) {
2088 xmlAddChild(parent, ret);
2089 } else {
2090 xmlAddSibling(parent, ret);
2091 }
2092 }
2093
2094 /*
2095 * Insert the defaulted attributes from the DTD only if requested:
2096 */
2097 if ((nb_defaulted != 0) &&
2098 ((ctxt->loadsubset & XML_COMPLETE_ATTRS) == 0))
2099 nb_attributes -= nb_defaulted;
2100
2101 /*
2102 * Search the namespace if it wasn't already found
2103 */
2104 if ((URI != NULL) && (ret->ns == NULL)) {
William M. Brack9f797ab2004-07-28 07:40:12 +00002105 if (prefix != NULL)
2106 ret->ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
2107 else
2108 ret->ns = xmlSearchNsByHref(ctxt->myDoc, parent, URI);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002109 if (ret->ns == NULL) {
2110 ns = xmlNewNs(ret, NULL, prefix);
William M. Brack9f797ab2004-07-28 07:40:12 +00002111 if (ns == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002112 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
William M. Brack9f797ab2004-07-28 07:40:12 +00002113 return;
2114 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002115 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
2116 ctxt->sax->warning(ctxt->userData,
2117 "Namespace prefix %s was not found\n", prefix);
2118 }
2119 }
2120
2121 /*
2122 * process all the other attributes
2123 */
2124 if (nb_attributes > 0) {
2125 for (j = 0,i = 0;i < nb_attributes;i++,j+=5) {
2126 xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1],
2127 attributes[j+3], attributes[j+4]);
2128 }
2129 }
2130
Daniel Veillard4432df22003-09-28 18:58:27 +00002131#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002132 /*
2133 * If it's the Document root, finish the DTD validation and
2134 * check the document root element for validity
2135 */
2136 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
2137 int chk;
2138
2139 chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
2140 if (chk <= 0)
2141 ctxt->valid = 0;
2142 if (chk < 0)
2143 ctxt->wellFormed = 0;
2144 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
2145 ctxt->vctxt.finishDtd = 1;
2146 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002147#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002148}
2149
2150/**
2151 * xmlSAX2EndElementNs:
2152 * @ctx: the user data (XML parser context)
2153 * @localname: the local name of the element
2154 * @prefix: the element namespace prefix if available
2155 * @URI: the element namespace name if available
2156 *
2157 * SAX2 callback when an element end has been detected by the parser.
2158 * It provides the namespace informations for the element.
2159 */
2160void
2161xmlSAX2EndElementNs(void *ctx,
2162 const xmlChar * localname ATTRIBUTE_UNUSED,
2163 const xmlChar * prefix ATTRIBUTE_UNUSED,
2164 const xmlChar * URI ATTRIBUTE_UNUSED)
2165{
2166 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2167 xmlParserNodeInfo node_info;
2168 xmlNodePtr cur = ctxt->node;
2169
2170 /* Capture end position and add node */
2171 if ((ctxt->record_info) && (cur != NULL)) {
2172 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
2173 node_info.end_line = ctxt->input->line;
2174 node_info.node = cur;
2175 xmlParserAddNodeInfo(ctxt, &node_info);
2176 }
2177 ctxt->nodemem = -1;
2178
Daniel Veillard4432df22003-09-28 18:58:27 +00002179#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002180 if (ctxt->validate && ctxt->wellFormed &&
2181 ctxt->myDoc && ctxt->myDoc->intSubset)
2182 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, cur);
Daniel Veillard4432df22003-09-28 18:58:27 +00002183#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002184
2185 /*
2186 * end of parsing of this node.
2187 */
2188 nodePop(ctxt);
2189}
2190
Daniel Veillard1af9a412003-08-20 22:54:39 +00002191/**
2192 * xmlSAX2Reference:
2193 * @ctx: the user data (XML parser context)
2194 * @name: The entity name
2195 *
2196 * called when an entity xmlSAX2Reference is detected.
2197 */
2198void
2199xmlSAX2Reference(void *ctx, const xmlChar *name)
2200{
2201 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2202 xmlNodePtr ret;
2203
2204#ifdef DEBUG_SAX
2205 xmlGenericError(xmlGenericErrorContext,
2206 "SAX.xmlSAX2Reference(%s)\n", name);
2207#endif
2208 if (name[0] == '#')
2209 ret = xmlNewCharRef(ctxt->myDoc, name);
2210 else
2211 ret = xmlNewReference(ctxt->myDoc, name);
2212#ifdef DEBUG_SAX_TREE
2213 xmlGenericError(xmlGenericErrorContext,
2214 "add xmlSAX2Reference %s to %s \n", name, ctxt->node->name);
2215#endif
2216 xmlAddChild(ctxt->node, ret);
2217}
2218
2219/**
2220 * xmlSAX2Characters:
2221 * @ctx: the user data (XML parser context)
2222 * @ch: a xmlChar string
2223 * @len: the number of xmlChar
2224 *
2225 * receiving some chars from the parser.
2226 */
2227void
2228xmlSAX2Characters(void *ctx, const xmlChar *ch, int len)
2229{
2230 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2231 xmlNodePtr lastChild;
2232
2233#ifdef DEBUG_SAX
2234 xmlGenericError(xmlGenericErrorContext,
2235 "SAX.xmlSAX2Characters(%.30s, %d)\n", ch, len);
2236#endif
2237 /*
2238 * Handle the data if any. If there is no child
2239 * add it as content, otherwise if the last child is text,
2240 * concatenate it, else create a new node of type text.
2241 */
2242
2243 if (ctxt->node == NULL) {
2244#ifdef DEBUG_SAX_TREE
2245 xmlGenericError(xmlGenericErrorContext,
2246 "add chars: ctxt->node == NULL !\n");
2247#endif
2248 return;
2249 }
Daniel Veillard19895052003-09-17 13:59:32 +00002250 lastChild = ctxt->node->last;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002251#ifdef DEBUG_SAX_TREE
2252 xmlGenericError(xmlGenericErrorContext,
2253 "add chars to %s \n", ctxt->node->name);
2254#endif
2255
2256 /*
2257 * Here we needed an accelerator mechanism in case of very large
2258 * elements. Use an attribute in the structure !!!
2259 */
2260 if (lastChild == NULL) {
Daniel Veillard19895052003-09-17 13:59:32 +00002261 lastChild = xmlSAX2TextNode(ctxt, ch, len);
2262 if (lastChild != NULL) {
2263 ctxt->node->children = lastChild;
2264 ctxt->node->last = lastChild;
2265 lastChild->parent = ctxt->node;
2266 lastChild->doc = ctxt->node->doc;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002267 ctxt->nodelen = len;
2268 ctxt->nodemem = len + 1;
William M. Bracka3215c72004-07-31 16:24:01 +00002269 } else {
2270 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
2271 return;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002272 }
2273 } else {
2274 int coalesceText = (lastChild != NULL) &&
2275 (lastChild->type == XML_TEXT_NODE) &&
2276 (lastChild->name == xmlStringText);
2277 if ((coalesceText) && (ctxt->nodemem != 0)) {
2278 /*
2279 * The whole point of maintaining nodelen and nodemem,
2280 * xmlTextConcat is too costly, i.e. compute length,
2281 * reallocate a new buffer, move data, append ch. Here
2282 * We try to minimaze realloc() uses and avoid copying
2283 * and recomputing length over and over.
2284 */
Daniel Veillard2b0f8792003-10-10 19:36:36 +00002285 if ((ctxt->nodemem == ctxt->nodelen + 1) &&
2286 (xmlDictOwns(ctxt->dict, lastChild->content))) {
2287 lastChild->content = xmlStrdup(lastChild->content);
2288 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00002289 if (ctxt->nodelen + len >= ctxt->nodemem) {
2290 xmlChar *newbuf;
2291 int size;
2292
2293 size = ctxt->nodemem + len;
2294 size *= 2;
2295 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
2296 if (newbuf == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002297 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
Daniel Veillard1af9a412003-08-20 22:54:39 +00002298 return;
2299 }
2300 ctxt->nodemem = size;
2301 lastChild->content = newbuf;
2302 }
2303 memcpy(&lastChild->content[ctxt->nodelen], ch, len);
2304 ctxt->nodelen += len;
2305 lastChild->content[ctxt->nodelen] = 0;
2306 } else if (coalesceText) {
2307 if (xmlTextConcat(lastChild, ch, len)) {
William M. Brack42331a92004-07-29 07:07:16 +00002308 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
Daniel Veillard1af9a412003-08-20 22:54:39 +00002309 }
2310 if (ctxt->node->children != NULL) {
2311 ctxt->nodelen = xmlStrlen(lastChild->content);
2312 ctxt->nodemem = ctxt->nodelen + 1;
2313 }
2314 } else {
2315 /* Mixed content, first time */
Daniel Veillard19895052003-09-17 13:59:32 +00002316 lastChild = xmlSAX2TextNode(ctxt, ch, len);
2317 if (lastChild != NULL) {
Daniel Veillard1af9a412003-08-20 22:54:39 +00002318 xmlAddChild(ctxt->node, lastChild);
2319 if (ctxt->node->children != NULL) {
2320 ctxt->nodelen = len;
2321 ctxt->nodemem = len + 1;
2322 }
2323 }
2324 }
2325 }
2326}
2327
2328/**
2329 * xmlSAX2IgnorableWhitespace:
2330 * @ctx: the user data (XML parser context)
2331 * @ch: a xmlChar string
2332 * @len: the number of xmlChar
2333 *
2334 * receiving some ignorable whitespaces from the parser.
2335 * UNUSED: by default the DOM building will use xmlSAX2Characters
2336 */
2337void
2338xmlSAX2IgnorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
2339{
2340 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
2341#ifdef DEBUG_SAX
2342 xmlGenericError(xmlGenericErrorContext,
2343 "SAX.xmlSAX2IgnorableWhitespace(%.30s, %d)\n", ch, len);
2344#endif
2345}
2346
2347/**
2348 * xmlSAX2ProcessingInstruction:
2349 * @ctx: the user data (XML parser context)
2350 * @target: the target name
2351 * @data: the PI data's
2352 *
2353 * A processing instruction has been parsed.
2354 */
2355void
2356xmlSAX2ProcessingInstruction(void *ctx, const xmlChar *target,
2357 const xmlChar *data)
2358{
2359 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2360 xmlNodePtr ret;
2361 xmlNodePtr parent = ctxt->node;
2362
2363#ifdef DEBUG_SAX
2364 xmlGenericError(xmlGenericErrorContext,
2365 "SAX.xmlSAX2ProcessingInstruction(%s, %s)\n", target, data);
2366#endif
2367
2368 ret = xmlNewPI(target, data);
2369 if (ret == NULL) return;
2370 parent = ctxt->node;
2371
2372 if (ctxt->inSubset == 1) {
2373 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2374 return;
2375 } else if (ctxt->inSubset == 2) {
2376 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2377 return;
2378 }
2379 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
2380#ifdef DEBUG_SAX_TREE
2381 xmlGenericError(xmlGenericErrorContext,
2382 "Setting PI %s as root\n", target);
2383#endif
2384 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2385 return;
2386 }
2387 if (parent->type == XML_ELEMENT_NODE) {
2388#ifdef DEBUG_SAX_TREE
2389 xmlGenericError(xmlGenericErrorContext,
2390 "adding PI %s child to %s\n", target, parent->name);
2391#endif
2392 xmlAddChild(parent, ret);
2393 } else {
2394#ifdef DEBUG_SAX_TREE
2395 xmlGenericError(xmlGenericErrorContext,
2396 "adding PI %s sibling to ", target);
2397 xmlDebugDumpOneNode(stderr, parent, 0);
2398#endif
2399 xmlAddSibling(parent, ret);
2400 }
2401}
2402
2403/**
2404 * xmlSAX2Comment:
2405 * @ctx: the user data (XML parser context)
2406 * @value: the xmlSAX2Comment content
2407 *
2408 * A xmlSAX2Comment has been parsed.
2409 */
2410void
2411xmlSAX2Comment(void *ctx, const xmlChar *value)
2412{
2413 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2414 xmlNodePtr ret;
2415 xmlNodePtr parent = ctxt->node;
2416
2417#ifdef DEBUG_SAX
2418 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2Comment(%s)\n", value);
2419#endif
2420 ret = xmlNewDocComment(ctxt->myDoc, value);
2421 if (ret == NULL) return;
2422
2423 if (ctxt->inSubset == 1) {
2424 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2425 return;
2426 } else if (ctxt->inSubset == 2) {
2427 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2428 return;
2429 }
2430 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
2431#ifdef DEBUG_SAX_TREE
2432 xmlGenericError(xmlGenericErrorContext,
2433 "Setting xmlSAX2Comment as root\n");
2434#endif
2435 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2436 return;
2437 }
2438 if (parent->type == XML_ELEMENT_NODE) {
2439#ifdef DEBUG_SAX_TREE
2440 xmlGenericError(xmlGenericErrorContext,
2441 "adding xmlSAX2Comment child to %s\n", parent->name);
2442#endif
2443 xmlAddChild(parent, ret);
2444 } else {
2445#ifdef DEBUG_SAX_TREE
2446 xmlGenericError(xmlGenericErrorContext,
2447 "adding xmlSAX2Comment sibling to ");
2448 xmlDebugDumpOneNode(stderr, parent, 0);
2449#endif
2450 xmlAddSibling(parent, ret);
2451 }
2452}
2453
2454/**
2455 * xmlSAX2CDataBlock:
2456 * @ctx: the user data (XML parser context)
2457 * @value: The pcdata content
2458 * @len: the block length
2459 *
2460 * called when a pcdata block has been parsed
2461 */
2462void
2463xmlSAX2CDataBlock(void *ctx, const xmlChar *value, int len)
2464{
2465 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2466 xmlNodePtr ret, lastChild;
2467
2468#ifdef DEBUG_SAX
2469 xmlGenericError(xmlGenericErrorContext,
2470 "SAX.pcdata(%.10s, %d)\n", value, len);
2471#endif
2472 lastChild = xmlGetLastChild(ctxt->node);
2473#ifdef DEBUG_SAX_TREE
2474 xmlGenericError(xmlGenericErrorContext,
2475 "add chars to %s \n", ctxt->node->name);
2476#endif
2477 if ((lastChild != NULL) &&
2478 (lastChild->type == XML_CDATA_SECTION_NODE)) {
2479 xmlTextConcat(lastChild, value, len);
2480 } else {
2481 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
2482 xmlAddChild(ctxt->node, ret);
2483 }
2484}
2485
Daniel Veillard62998c02003-09-15 12:56:36 +00002486static int xmlSAX2DefaultVersionValue = 2;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002487
Daniel Veillard81273902003-09-30 00:43:48 +00002488#ifdef LIBXML_SAX1_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002489/**
2490 * xmlSAXDefaultVersion:
2491 * @version: the version, 1 or 2
2492 *
2493 * Set the default version of SAX used globally by the library.
William M. Brack96d2eff2004-06-30 11:48:47 +00002494 * By default, during initialization the default is set to 2.
2495 * Note that it is generally a better coding style to use
2496 * xmlSAXVersion() to set up the version explicitly for a given
2497 * parsing context.
Daniel Veillarde57ec792003-09-10 10:50:59 +00002498 *
2499 * Returns the previous value in case of success and -1 in case of error.
2500 */
2501int
2502xmlSAXDefaultVersion(int version)
2503{
2504 int ret = xmlSAX2DefaultVersionValue;
2505
2506 if ((version != 1) && (version != 2))
2507 return(-1);
2508 xmlSAX2DefaultVersionValue = version;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002509 return(ret);
2510}
Daniel Veillard81273902003-09-30 00:43:48 +00002511#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002512
2513/**
2514 * xmlSAXVersion:
2515 * @hdlr: the SAX handler
2516 * @version: the version, 1 or 2
2517 *
2518 * Initialize the default XML SAX handler according to the version
2519 *
2520 * Returns 0 in case of success and -1 in case of error.
2521 */
2522int
2523xmlSAXVersion(xmlSAXHandler *hdlr, int version)
2524{
2525 if (hdlr == NULL) return(-1);
Daniel Veillard81273902003-09-30 00:43:48 +00002526 if (version == 2) {
Daniel Veillarde57ec792003-09-10 10:50:59 +00002527 hdlr->startElement = NULL;
2528 hdlr->endElement = NULL;
2529 hdlr->startElementNs = xmlSAX2StartElementNs;
2530 hdlr->endElementNs = xmlSAX2EndElementNs;
Daniel Veillardffbbed42003-10-10 14:46:54 +00002531 hdlr->serror = NULL;
Daniel Veillard092643b2003-09-25 14:29:29 +00002532 hdlr->initialized = XML_SAX2_MAGIC;
Daniel Veillard81273902003-09-30 00:43:48 +00002533#ifdef LIBXML_SAX1_ENABLED
2534 } else if (version == 1) {
2535 hdlr->startElement = xmlSAX2StartElement;
2536 hdlr->endElement = xmlSAX2EndElement;
2537 hdlr->initialized = 1;
2538#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002539 } else
2540 return(-1);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002541 hdlr->internalSubset = xmlSAX2InternalSubset;
2542 hdlr->externalSubset = xmlSAX2ExternalSubset;
2543 hdlr->isStandalone = xmlSAX2IsStandalone;
2544 hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
2545 hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
2546 hdlr->resolveEntity = xmlSAX2ResolveEntity;
2547 hdlr->getEntity = xmlSAX2GetEntity;
2548 hdlr->getParameterEntity = xmlSAX2GetParameterEntity;
2549 hdlr->entityDecl = xmlSAX2EntityDecl;
2550 hdlr->attributeDecl = xmlSAX2AttributeDecl;
2551 hdlr->elementDecl = xmlSAX2ElementDecl;
2552 hdlr->notationDecl = xmlSAX2NotationDecl;
2553 hdlr->unparsedEntityDecl = xmlSAX2UnparsedEntityDecl;
2554 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2555 hdlr->startDocument = xmlSAX2StartDocument;
2556 hdlr->endDocument = xmlSAX2EndDocument;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002557 hdlr->reference = xmlSAX2Reference;
2558 hdlr->characters = xmlSAX2Characters;
2559 hdlr->cdataBlock = xmlSAX2CDataBlock;
2560 hdlr->ignorableWhitespace = xmlSAX2Characters;
2561 hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
2562 hdlr->comment = xmlSAX2Comment;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002563 hdlr->warning = xmlParserWarning;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002564 hdlr->error = xmlParserError;
2565 hdlr->fatalError = xmlParserError;
2566
Daniel Veillarde57ec792003-09-10 10:50:59 +00002567 return(0);
2568}
2569
2570/**
2571 * xmlSAX2InitDefaultSAXHandler:
2572 * @hdlr: the SAX handler
2573 * @warning: flag if non-zero sets the handler warning procedure
2574 *
2575 * Initialize the default XML SAX2 handler
2576 */
2577void
2578xmlSAX2InitDefaultSAXHandler(xmlSAXHandler *hdlr, int warning)
2579{
2580 if ((hdlr == NULL) || (hdlr->initialized != 0))
2581 return;
2582
2583 xmlSAXVersion(hdlr, xmlSAX2DefaultVersionValue);
2584 if (warning == 0)
2585 hdlr->warning = NULL;
2586 else
2587 hdlr->warning = xmlParserWarning;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002588}
2589
2590/**
2591 * xmlDefaultSAXHandlerInit:
2592 *
2593 * Initialize the default SAX2 handler
2594 */
2595void
2596xmlDefaultSAXHandlerInit(void)
2597{
Daniel Veillard81273902003-09-30 00:43:48 +00002598#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard092643b2003-09-25 14:29:29 +00002599 xmlSAXVersion((xmlSAXHandlerPtr) &xmlDefaultSAXHandler, 1);
Daniel Veillard81273902003-09-30 00:43:48 +00002600#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00002601}
2602
2603#ifdef LIBXML_HTML_ENABLED
2604
2605/**
2606 * xmlSAX2InitHtmlDefaultSAXHandler:
2607 * @hdlr: the SAX handler
2608 *
2609 * Initialize the default HTML SAX2 handler
2610 */
2611void
2612xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr)
2613{
2614 if(hdlr->initialized != 0)
2615 return;
2616
2617 hdlr->internalSubset = xmlSAX2InternalSubset;
2618 hdlr->externalSubset = NULL;
2619 hdlr->isStandalone = NULL;
2620 hdlr->hasInternalSubset = NULL;
2621 hdlr->hasExternalSubset = NULL;
2622 hdlr->resolveEntity = NULL;
2623 hdlr->getEntity = xmlSAX2GetEntity;
2624 hdlr->getParameterEntity = NULL;
2625 hdlr->entityDecl = NULL;
2626 hdlr->attributeDecl = NULL;
2627 hdlr->elementDecl = NULL;
2628 hdlr->notationDecl = NULL;
2629 hdlr->unparsedEntityDecl = NULL;
2630 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2631 hdlr->startDocument = xmlSAX2StartDocument;
2632 hdlr->endDocument = xmlSAX2EndDocument;
2633 hdlr->startElement = xmlSAX2StartElement;
2634 hdlr->endElement = xmlSAX2EndElement;
2635 hdlr->reference = NULL;
2636 hdlr->characters = xmlSAX2Characters;
2637 hdlr->cdataBlock = xmlSAX2CDataBlock;
2638 hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
2639 hdlr->processingInstruction = NULL;
2640 hdlr->comment = xmlSAX2Comment;
2641 hdlr->warning = xmlParserWarning;
2642 hdlr->error = xmlParserError;
2643 hdlr->fatalError = xmlParserError;
2644
Daniel Veillard092643b2003-09-25 14:29:29 +00002645 hdlr->initialized = 1;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002646}
2647
2648/**
2649 * htmlDefaultSAXHandlerInit:
2650 *
2651 * Initialize the default SAX handler
2652 */
2653void
2654htmlDefaultSAXHandlerInit(void)
2655{
Daniel Veillard092643b2003-09-25 14:29:29 +00002656 xmlSAX2InitHtmlDefaultSAXHandler((xmlSAXHandlerPtr) &htmlDefaultSAXHandler);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002657}
2658
2659#endif /* LIBXML_HTML_ENABLED */
2660
2661#ifdef LIBXML_DOCB_ENABLED
2662
2663/**
2664 * xmlSAX2InitDocbDefaultSAXHandler:
2665 * @hdlr: the SAX handler
2666 *
2667 * Initialize the default DocBook SAX2 handler
2668 */
2669void
2670xmlSAX2InitDocbDefaultSAXHandler(xmlSAXHandler *hdlr)
2671{
2672 if(hdlr->initialized != 0)
2673 return;
2674
2675 hdlr->internalSubset = xmlSAX2InternalSubset;
2676 hdlr->externalSubset = NULL;
2677 hdlr->isStandalone = xmlSAX2IsStandalone;
2678 hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
2679 hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
2680 hdlr->resolveEntity = xmlSAX2ResolveEntity;
2681 hdlr->getEntity = xmlSAX2GetEntity;
2682 hdlr->getParameterEntity = NULL;
2683 hdlr->entityDecl = xmlSAX2EntityDecl;
2684 hdlr->attributeDecl = NULL;
2685 hdlr->elementDecl = NULL;
2686 hdlr->notationDecl = NULL;
2687 hdlr->unparsedEntityDecl = NULL;
2688 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2689 hdlr->startDocument = xmlSAX2StartDocument;
2690 hdlr->endDocument = xmlSAX2EndDocument;
2691 hdlr->startElement = xmlSAX2StartElement;
2692 hdlr->endElement = xmlSAX2EndElement;
2693 hdlr->reference = xmlSAX2Reference;
2694 hdlr->characters = xmlSAX2Characters;
2695 hdlr->cdataBlock = NULL;
2696 hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
2697 hdlr->processingInstruction = NULL;
2698 hdlr->comment = xmlSAX2Comment;
2699 hdlr->warning = xmlParserWarning;
2700 hdlr->error = xmlParserError;
2701 hdlr->fatalError = xmlParserError;
2702
Daniel Veillardffbbed42003-10-10 14:46:54 +00002703 hdlr->initialized = 1;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002704}
2705
2706/**
2707 * docbDefaultSAXHandlerInit:
2708 *
2709 * Initialize the default SAX handler
2710 */
2711void
2712docbDefaultSAXHandlerInit(void)
2713{
Daniel Veillard092643b2003-09-25 14:29:29 +00002714 xmlSAX2InitDocbDefaultSAXHandler((xmlSAXHandlerPtr) &docbDefaultSAXHandler);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002715}
2716
2717#endif /* LIBXML_DOCB_ENABLED */