blob: 6c866afcdb084e88e4b7cf276519561d57d3b0d3 [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) {
Daniel Veillard34099b42004-11-04 17:34:35 +000054 if (ctxt != NULL) {
55 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
56 ctxt->sax->error(ctxt->userData, "%s: out of memory\n", msg);
57 ctxt->errNo = XML_ERR_NO_MEMORY;
58 ctxt->instate = XML_PARSER_EOF;
59 ctxt->disableSAX = 1;
60 }
William M. Brack42331a92004-07-29 07:07:16 +000061}
62
Daniel Veillarde57ec792003-09-10 10:50:59 +000063/**
Daniel Veillardf88d8cf2003-12-08 10:25:02 +000064 * xmlValidError:
65 * @ctxt: an XML validation parser context
66 * @error: the error number
67 * @msg: the error message
68 * @str1: extra data
69 * @str2: extra data
70 *
71 * Handle a validation error
72 */
73static void
74xmlErrValid(xmlParserCtxtPtr ctxt, xmlParserErrors error,
75 const char *msg, const char *str1, const char *str2)
76{
77 xmlStructuredErrorFunc schannel = NULL;
78
79 if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
80 (ctxt->instate == XML_PARSER_EOF))
81 return;
Daniel Veillard34099b42004-11-04 17:34:35 +000082 if (ctxt != NULL) {
83 ctxt->errNo = error;
84 if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
85 schannel = ctxt->sax->serror;
86 }
Daniel Veillardf88d8cf2003-12-08 10:25:02 +000087 __xmlRaiseError(schannel,
88 ctxt->vctxt.error, ctxt->vctxt.userData,
89 ctxt, NULL, XML_FROM_DTD, error,
90 XML_ERR_ERROR, NULL, 0, (const char *) str1,
91 (const char *) str2, NULL, 0, 0,
92 msg, (const char *) str1, (const char *) str2);
Daniel Veillard34099b42004-11-04 17:34:35 +000093 if (ctxt != NULL)
94 ctxt->valid = 0;
Daniel Veillardf88d8cf2003-12-08 10:25:02 +000095}
96
97/**
Daniel Veillard1af9a412003-08-20 22:54:39 +000098 * xmlSAX2GetPublicId:
99 * @ctx: the user data (XML parser context)
100 *
101 * Provides the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
102 *
103 * Returns a xmlChar *
104 */
105const xmlChar *
106xmlSAX2GetPublicId(void *ctx ATTRIBUTE_UNUSED)
107{
108 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
109 return(NULL);
110}
111
112/**
113 * xmlSAX2GetSystemId:
114 * @ctx: the user data (XML parser context)
115 *
116 * Provides the system ID, basically URL or filename e.g.
117 * http://www.sgmlsource.com/dtds/memo.dtd
118 *
119 * Returns a xmlChar *
120 */
121const xmlChar *
122xmlSAX2GetSystemId(void *ctx)
123{
124 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard34099b42004-11-04 17:34:35 +0000125 if ((ctx == NULL) || (ctxt->input == NULL)) return(0);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000126 return((const xmlChar *) ctxt->input->filename);
127}
128
129/**
130 * xmlSAX2GetLineNumber:
131 * @ctx: the user data (XML parser context)
132 *
133 * Provide the line number of the current parsing point.
134 *
135 * Returns an int
136 */
137int
138xmlSAX2GetLineNumber(void *ctx)
139{
140 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard34099b42004-11-04 17:34:35 +0000141 if ((ctx == NULL) || (ctxt->input == NULL)) return(0);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000142 return(ctxt->input->line);
143}
144
145/**
146 * xmlSAX2GetColumnNumber:
147 * @ctx: the user data (XML parser context)
148 *
149 * Provide the column number of the current parsing point.
150 *
151 * Returns an int
152 */
153int
154xmlSAX2GetColumnNumber(void *ctx)
155{
156 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard34099b42004-11-04 17:34:35 +0000157 if ((ctx == NULL) || (ctxt->input == NULL)) return(0);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000158 return(ctxt->input->col);
159}
160
161/**
162 * xmlSAX2IsStandalone:
163 * @ctx: the user data (XML parser context)
164 *
165 * Is this document tagged standalone ?
166 *
167 * Returns 1 if true
168 */
169int
170xmlSAX2IsStandalone(void *ctx)
171{
172 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard34099b42004-11-04 17:34:35 +0000173 if ((ctx == NULL) || (ctxt->myDoc == NULL)) return(0);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000174 return(ctxt->myDoc->standalone == 1);
175}
176
177/**
178 * xmlSAX2HasInternalSubset:
179 * @ctx: the user data (XML parser context)
180 *
181 * Does this document has an internal subset
182 *
183 * Returns 1 if true
184 */
185int
186xmlSAX2HasInternalSubset(void *ctx)
187{
188 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +0000189 if ((ctxt == NULL) || (ctxt->myDoc == NULL)) return(0);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000190 return(ctxt->myDoc->intSubset != NULL);
191}
192
193/**
194 * xmlSAX2HasExternalSubset:
195 * @ctx: the user data (XML parser context)
196 *
197 * Does this document has an external subset
198 *
199 * Returns 1 if true
200 */
201int
202xmlSAX2HasExternalSubset(void *ctx)
203{
204 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +0000205 if ((ctxt == NULL) || (ctxt->myDoc == NULL)) return(0);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000206 return(ctxt->myDoc->extSubset != NULL);
207}
208
209/**
210 * xmlSAX2InternalSubset:
211 * @ctx: the user data (XML parser context)
212 * @name: the root element name
213 * @ExternalID: the external ID
214 * @SystemID: the SYSTEM ID (e.g. filename or URL)
215 *
216 * Callback on internal subset declaration.
217 */
218void
219xmlSAX2InternalSubset(void *ctx, const xmlChar *name,
220 const xmlChar *ExternalID, const xmlChar *SystemID)
221{
222 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
223 xmlDtdPtr dtd;
Daniel Veillard34099b42004-11-04 17:34:35 +0000224 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000225#ifdef DEBUG_SAX
226 xmlGenericError(xmlGenericErrorContext,
227 "SAX.xmlSAX2InternalSubset(%s, %s, %s)\n",
228 name, ExternalID, SystemID);
229#endif
230
231 if (ctxt->myDoc == NULL)
232 return;
233 dtd = xmlGetIntSubset(ctxt->myDoc);
234 if (dtd != NULL) {
235 if (ctxt->html)
236 return;
237 xmlUnlinkNode((xmlNodePtr) dtd);
238 xmlFreeDtd(dtd);
239 ctxt->myDoc->intSubset = NULL;
240 }
241 ctxt->myDoc->intSubset =
242 xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
William M. Brack42331a92004-07-29 07:07:16 +0000243 if (ctxt->myDoc->intSubset == NULL)
244 xmlSAX2ErrMemory(ctxt, "xmlSAX2InternalSubset");
Daniel Veillard1af9a412003-08-20 22:54:39 +0000245}
246
247/**
248 * xmlSAX2ExternalSubset:
249 * @ctx: the user data (XML parser context)
250 * @name: the root element name
251 * @ExternalID: the external ID
252 * @SystemID: the SYSTEM ID (e.g. filename or URL)
253 *
254 * Callback on external subset declaration.
255 */
256void
257xmlSAX2ExternalSubset(void *ctx, const xmlChar *name,
258 const xmlChar *ExternalID, const xmlChar *SystemID)
259{
260 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard34099b42004-11-04 17:34:35 +0000261 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000262#ifdef DEBUG_SAX
263 xmlGenericError(xmlGenericErrorContext,
264 "SAX.xmlSAX2ExternalSubset(%s, %s, %s)\n",
265 name, ExternalID, SystemID);
266#endif
267 if (((ExternalID != NULL) || (SystemID != NULL)) &&
268 (((ctxt->validate) || (ctxt->loadsubset != 0)) &&
269 (ctxt->wellFormed && ctxt->myDoc))) {
270 /*
271 * Try to fetch and parse the external subset.
272 */
273 xmlParserInputPtr oldinput;
274 int oldinputNr;
275 int oldinputMax;
276 xmlParserInputPtr *oldinputTab;
277 xmlParserInputPtr input = NULL;
278 xmlCharEncoding enc;
279 int oldcharset;
280
281 /*
282 * Ask the Entity resolver to load the damn thing
283 */
284 if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
285 input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
286 SystemID);
287 if (input == NULL) {
288 return;
289 }
290
291 xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
292
293 /*
294 * make sure we won't destroy the main document context
295 */
296 oldinput = ctxt->input;
297 oldinputNr = ctxt->inputNr;
298 oldinputMax = ctxt->inputMax;
299 oldinputTab = ctxt->inputTab;
300 oldcharset = ctxt->charset;
301
302 ctxt->inputTab = (xmlParserInputPtr *)
303 xmlMalloc(5 * sizeof(xmlParserInputPtr));
304 if (ctxt->inputTab == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +0000305 xmlSAX2ErrMemory(ctxt, "xmlSAX2ExternalSubset");
Daniel Veillard1af9a412003-08-20 22:54:39 +0000306 ctxt->input = oldinput;
307 ctxt->inputNr = oldinputNr;
308 ctxt->inputMax = oldinputMax;
309 ctxt->inputTab = oldinputTab;
310 ctxt->charset = oldcharset;
311 return;
312 }
313 ctxt->inputNr = 0;
314 ctxt->inputMax = 5;
315 ctxt->input = NULL;
316 xmlPushInput(ctxt, input);
317
318 /*
319 * On the fly encoding conversion if needed
320 */
321 if (ctxt->input->length >= 4) {
322 enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
323 xmlSwitchEncoding(ctxt, enc);
324 }
325
326 if (input->filename == NULL)
327 input->filename = (char *) xmlCanonicPath(SystemID);
328 input->line = 1;
329 input->col = 1;
330 input->base = ctxt->input->cur;
331 input->cur = ctxt->input->cur;
332 input->free = NULL;
333
334 /*
335 * let's parse that entity knowing it's an external subset.
336 */
337 xmlParseExternalSubset(ctxt, ExternalID, SystemID);
338
339 /*
340 * Free up the external entities
341 */
342
343 while (ctxt->inputNr > 1)
344 xmlPopInput(ctxt);
345 xmlFreeInputStream(ctxt->input);
346 xmlFree(ctxt->inputTab);
347
348 /*
349 * Restore the parsing context of the main entity
350 */
351 ctxt->input = oldinput;
352 ctxt->inputNr = oldinputNr;
353 ctxt->inputMax = oldinputMax;
354 ctxt->inputTab = oldinputTab;
355 ctxt->charset = oldcharset;
356 /* ctxt->wellFormed = oldwellFormed; */
357 }
358}
359
360/**
361 * xmlSAX2ResolveEntity:
362 * @ctx: the user data (XML parser context)
363 * @publicId: The public ID of the entity
364 * @systemId: The system ID of the entity
365 *
366 * The entity loader, to control the loading of external entities,
367 * the application can either:
368 * - override this xmlSAX2ResolveEntity() callback in the SAX block
369 * - or better use the xmlSetExternalEntityLoader() function to
370 * set up it's own entity resolution routine
371 *
372 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
373 */
374xmlParserInputPtr
375xmlSAX2ResolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
376{
377 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
378 xmlParserInputPtr ret;
379 xmlChar *URI;
380 const char *base = NULL;
381
Daniel Veillard34099b42004-11-04 17:34:35 +0000382 if (ctx == NULL) return(NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000383 if (ctxt->input != NULL)
384 base = ctxt->input->filename;
385 if (base == NULL)
386 base = ctxt->directory;
387
388 URI = xmlBuildURI(systemId, (const xmlChar *) base);
389
390#ifdef DEBUG_SAX
391 xmlGenericError(xmlGenericErrorContext,
392 "SAX.xmlSAX2ResolveEntity(%s, %s)\n", publicId, systemId);
393#endif
394
395 ret = xmlLoadExternalEntity((const char *) URI,
396 (const char *) publicId, ctxt);
397 if (URI != NULL)
398 xmlFree(URI);
399 return(ret);
400}
401
402/**
403 * xmlSAX2GetEntity:
404 * @ctx: the user data (XML parser context)
405 * @name: The entity name
406 *
407 * Get an entity by name
408 *
409 * Returns the xmlEntityPtr if found.
410 */
411xmlEntityPtr
412xmlSAX2GetEntity(void *ctx, const xmlChar *name)
413{
414 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
415 xmlEntityPtr ret = NULL;
416
Daniel Veillard34099b42004-11-04 17:34:35 +0000417 if (ctx == NULL) return(NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000418#ifdef DEBUG_SAX
419 xmlGenericError(xmlGenericErrorContext,
420 "SAX.xmlSAX2GetEntity(%s)\n", name);
421#endif
422
423 if (ctxt->inSubset == 0) {
424 ret = xmlGetPredefinedEntity(name);
425 if (ret != NULL)
426 return(ret);
427 }
428 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->standalone == 1)) {
429 if (ctxt->inSubset == 2) {
430 ctxt->myDoc->standalone = 0;
431 ret = xmlGetDocEntity(ctxt->myDoc, name);
432 ctxt->myDoc->standalone = 1;
433 } else {
434 ret = xmlGetDocEntity(ctxt->myDoc, name);
435 if (ret == NULL) {
436 ctxt->myDoc->standalone = 0;
437 ret = xmlGetDocEntity(ctxt->myDoc, name);
438 if (ret != NULL) {
439 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000440 ctxt->sax->error(ctxt->userData,
441 "Entity(%s) document marked standalone but requires external subset\n",
Daniel Veillard1af9a412003-08-20 22:54:39 +0000442 name);
443 ctxt->valid = 0;
444 ctxt->wellFormed = 0;
445 }
446 ctxt->myDoc->standalone = 1;
447 }
448 }
449 } else {
450 ret = xmlGetDocEntity(ctxt->myDoc, name);
451 }
452 if ((ret != NULL) &&
453 ((ctxt->validate) || (ctxt->replaceEntities)) &&
454 (ret->children == NULL) &&
455 (ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
456 int val;
457
458 /*
459 * for validation purposes we really need to fetch and
460 * parse the external entity
461 */
462 xmlNodePtr children;
463
464 val = xmlParseCtxtExternalEntity(ctxt, ret->URI,
465 ret->ExternalID, &children);
466 if (val == 0) {
467 xmlAddChildList((xmlNodePtr) ret, children);
468 } else {
William M. Brack4811ba32003-09-06 18:02:53 +0000469 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
470 ctxt->sax->error(ctxt->userData,
471 "Failure to process entity %s\n", name);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000472 ctxt->wellFormed = 0;
473 ctxt->valid = 0;
474 ctxt->validate = 0;
475 return(NULL);
476 }
477 ret->owner = 1;
478 }
479 return(ret);
480}
481
482/**
483 * xmlSAX2GetParameterEntity:
484 * @ctx: the user data (XML parser context)
485 * @name: The entity name
486 *
487 * Get a parameter entity by name
488 *
489 * Returns the xmlEntityPtr if found.
490 */
491xmlEntityPtr
492xmlSAX2GetParameterEntity(void *ctx, const xmlChar *name)
493{
494 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
495 xmlEntityPtr ret;
496
Daniel Veillard34099b42004-11-04 17:34:35 +0000497 if (ctx == NULL) return(NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000498#ifdef DEBUG_SAX
499 xmlGenericError(xmlGenericErrorContext,
500 "SAX.xmlSAX2GetParameterEntity(%s)\n", name);
501#endif
502
503 ret = xmlGetParameterEntity(ctxt->myDoc, name);
504 return(ret);
505}
506
507
508/**
509 * xmlSAX2EntityDecl:
510 * @ctx: the user data (XML parser context)
511 * @name: the entity name
512 * @type: the entity type
513 * @publicId: The public ID of the entity
514 * @systemId: The system ID of the entity
515 * @content: the entity value (without processing).
516 *
517 * An entity definition has been parsed
518 */
519void
520xmlSAX2EntityDecl(void *ctx, const xmlChar *name, int type,
521 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
522{
523 xmlEntityPtr ent;
524 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
525
Daniel Veillard34099b42004-11-04 17:34:35 +0000526 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000527#ifdef DEBUG_SAX
528 xmlGenericError(xmlGenericErrorContext,
529 "SAX.xmlSAX2EntityDecl(%s, %d, %s, %s, %s)\n",
530 name, type, publicId, systemId, content);
531#endif
532 if (ctxt->inSubset == 1) {
533 ent = xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
534 systemId, content);
535 if ((ent == NULL) && (ctxt->pedantic) &&
536 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000537 ctxt->sax->warning(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000538 "Entity(%s) already defined in the internal subset\n", name);
539 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
540 xmlChar *URI;
541 const char *base = NULL;
542
543 if (ctxt->input != NULL)
544 base = ctxt->input->filename;
545 if (base == NULL)
546 base = ctxt->directory;
547
548 URI = xmlBuildURI(systemId, (const xmlChar *) base);
549 ent->URI = URI;
550 }
551 } else if (ctxt->inSubset == 2) {
552 ent = xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
553 systemId, content);
554 if ((ent == NULL) && (ctxt->pedantic) &&
555 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000556 ctxt->sax->warning(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000557 "Entity(%s) already defined in the external subset\n", name);
558 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
559 xmlChar *URI;
560 const char *base = NULL;
561
562 if (ctxt->input != NULL)
563 base = ctxt->input->filename;
564 if (base == NULL)
565 base = ctxt->directory;
566
567 URI = xmlBuildURI(systemId, (const xmlChar *) base);
568 ent->URI = URI;
569 }
570 } else {
571 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000572 ctxt->sax->error(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000573 "SAX.xmlSAX2EntityDecl(%s) called while not in subset\n", name);
574 }
575}
576
577/**
578 * xmlSAX2AttributeDecl:
579 * @ctx: the user data (XML parser context)
580 * @elem: the name of the element
581 * @fullname: the attribute name
582 * @type: the attribute type
583 * @def: the type of default value
584 * @defaultValue: the attribute default value
585 * @tree: the tree of enumerated value set
586 *
587 * An attribute definition has been parsed
588 */
589void
590xmlSAX2AttributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
591 int type, int def, const xmlChar *defaultValue,
592 xmlEnumerationPtr tree)
593{
594 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
595 xmlAttributePtr attr;
596 xmlChar *name = NULL, *prefix = NULL;
597
Daniel Veillard34099b42004-11-04 17:34:35 +0000598 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000599#ifdef DEBUG_SAX
600 xmlGenericError(xmlGenericErrorContext,
601 "SAX.xmlSAX2AttributeDecl(%s, %s, %d, %d, %s, ...)\n",
602 elem, fullname, type, def, defaultValue);
603#endif
Daniel Veillard68cb4b22004-04-18 20:55:39 +0000604 if ((xmlStrEqual(fullname, BAD_CAST "xml:id")) &&
605 (type != XML_ATTRIBUTE_ID)) {
606 /*
607 * Raise the error but keep the validity flag
608 */
609 int tmp = ctxt->valid;
610 xmlErrValid(ctxt, XML_DTD_XMLID_TYPE,
611 "xml:id : attribute type should be ID\n", NULL, NULL);
612 ctxt->valid = tmp;
613 }
Daniel Veillarde57ec792003-09-10 10:50:59 +0000614 /* TODO: optimize name/prefix allocation */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000615 name = xmlSplitQName(ctxt, fullname, &prefix);
616 ctxt->vctxt.valid = 1;
617 if (ctxt->inSubset == 1)
618 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
619 name, prefix, (xmlAttributeType) type,
620 (xmlAttributeDefault) def, defaultValue, tree);
621 else if (ctxt->inSubset == 2)
622 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
623 name, prefix, (xmlAttributeType) type,
624 (xmlAttributeDefault) def, defaultValue, tree);
625 else {
626 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000627 ctxt->sax->error(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000628 "SAX.xmlSAX2AttributeDecl(%s) called while not in subset\n", name);
Daniel Veillarde57ec792003-09-10 10:50:59 +0000629 xmlFreeEnumeration(tree);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000630 return;
631 }
Daniel Veillard4432df22003-09-28 18:58:27 +0000632#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000633 if (ctxt->vctxt.valid == 0)
634 ctxt->valid = 0;
635 if ((attr != NULL) && (ctxt->validate) && (ctxt->wellFormed) &&
636 (ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset != NULL))
637 ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
638 attr);
Daniel Veillard4432df22003-09-28 18:58:27 +0000639#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000640 if (prefix != NULL)
641 xmlFree(prefix);
642 if (name != NULL)
643 xmlFree(name);
644}
645
646/**
647 * xmlSAX2ElementDecl:
648 * @ctx: the user data (XML parser context)
649 * @name: the element name
650 * @type: the element type
651 * @content: the element value tree
652 *
653 * An element definition has been parsed
654 */
655void
656xmlSAX2ElementDecl(void *ctx, const xmlChar * name, int type,
657 xmlElementContentPtr content)
658{
659 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
660 xmlElementPtr elem = NULL;
661
Daniel Veillard34099b42004-11-04 17:34:35 +0000662 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000663#ifdef DEBUG_SAX
664 xmlGenericError(xmlGenericErrorContext,
665 "SAX.xmlSAX2ElementDecl(%s, %d, ...)\n", name, type);
666#endif
667
668 if (ctxt->inSubset == 1)
669 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
670 name, (xmlElementTypeVal) type, content);
671 else if (ctxt->inSubset == 2)
672 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
673 name, (xmlElementTypeVal) type, content);
674 else {
675 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000676 ctxt->sax->error(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000677 "SAX.xmlSAX2ElementDecl(%s) called while not in subset\n",
678 name);
679 return;
680 }
Daniel Veillard4432df22003-09-28 18:58:27 +0000681#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000682 if (elem == NULL)
683 ctxt->valid = 0;
684 if (ctxt->validate && ctxt->wellFormed &&
685 ctxt->myDoc && ctxt->myDoc->intSubset)
686 ctxt->valid &=
687 xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
Daniel Veillard4432df22003-09-28 18:58:27 +0000688#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000689}
690
691/**
692 * xmlSAX2NotationDecl:
693 * @ctx: the user data (XML parser context)
694 * @name: The name of the notation
695 * @publicId: The public ID of the entity
696 * @systemId: The system ID of the entity
697 *
698 * What to do when a notation declaration has been parsed.
699 */
700void
701xmlSAX2NotationDecl(void *ctx, const xmlChar *name,
702 const xmlChar *publicId, const xmlChar *systemId)
703{
704 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
705 xmlNotationPtr nota = NULL;
706
Daniel Veillard34099b42004-11-04 17:34:35 +0000707 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000708#ifdef DEBUG_SAX
709 xmlGenericError(xmlGenericErrorContext,
710 "SAX.xmlSAX2NotationDecl(%s, %s, %s)\n", name, publicId, systemId);
711#endif
712
713 if ((publicId == NULL) && (systemId == NULL)) {
714 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000715 ctxt->sax->error(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000716 "SAX.xmlSAX2NotationDecl(%s) externalID or PublicID missing\n", name);
717 ctxt->valid = 0;
718 ctxt->wellFormed = 0;
719 return;
720 } else if (ctxt->inSubset == 1)
721 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
722 publicId, systemId);
723 else if (ctxt->inSubset == 2)
724 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, name,
725 publicId, systemId);
726 else {
727 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000728 ctxt->sax->error(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000729 "SAX.xmlSAX2NotationDecl(%s) called while not in subset\n", name);
730 return;
731 }
Daniel Veillard4432df22003-09-28 18:58:27 +0000732#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000733 if (nota == NULL) ctxt->valid = 0;
734 if (ctxt->validate && ctxt->wellFormed &&
735 ctxt->myDoc && ctxt->myDoc->intSubset)
736 ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
737 nota);
Daniel Veillard4432df22003-09-28 18:58:27 +0000738#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000739}
740
741/**
742 * xmlSAX2UnparsedEntityDecl:
743 * @ctx: the user data (XML parser context)
744 * @name: The name of the entity
745 * @publicId: The public ID of the entity
746 * @systemId: The system ID of the entity
747 * @notationName: the name of the notation
748 *
749 * What to do when an unparsed entity declaration is parsed
750 */
751void
752xmlSAX2UnparsedEntityDecl(void *ctx, const xmlChar *name,
753 const xmlChar *publicId, const xmlChar *systemId,
754 const xmlChar *notationName)
755{
756 xmlEntityPtr ent;
757 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard34099b42004-11-04 17:34:35 +0000758 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000759#ifdef DEBUG_SAX
760 xmlGenericError(xmlGenericErrorContext,
761 "SAX.xmlSAX2UnparsedEntityDecl(%s, %s, %s, %s)\n",
762 name, publicId, systemId, notationName);
763#endif
764 if (ctxt->inSubset == 1) {
765 ent = xmlAddDocEntity(ctxt->myDoc, name,
766 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
767 publicId, systemId, notationName);
768 if ((ent == NULL) && (ctxt->pedantic) &&
769 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000770 ctxt->sax->warning(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000771 "Entity(%s) already defined in the internal subset\n", name);
772 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
773 xmlChar *URI;
774 const char *base = NULL;
775
776 if (ctxt->input != NULL)
777 base = ctxt->input->filename;
778 if (base == NULL)
779 base = ctxt->directory;
780
781 URI = xmlBuildURI(systemId, (const xmlChar *) base);
782 ent->URI = URI;
783 }
784 } else if (ctxt->inSubset == 2) {
785 ent = xmlAddDtdEntity(ctxt->myDoc, name,
786 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
787 publicId, systemId, notationName);
788 if ((ent == NULL) && (ctxt->pedantic) &&
789 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000790 ctxt->sax->warning(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000791 "Entity(%s) already defined in the external subset\n", name);
792 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
793 xmlChar *URI;
794 const char *base = NULL;
795
796 if (ctxt->input != NULL)
797 base = ctxt->input->filename;
798 if (base == NULL)
799 base = ctxt->directory;
800
801 URI = xmlBuildURI(systemId, (const xmlChar *) base);
802 ent->URI = URI;
803 }
804 } else {
805 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000806 ctxt->sax->error(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000807 "SAX.xmlSAX2UnparsedEntityDecl(%s) called while not in subset\n", name);
808 }
809}
810
811/**
812 * xmlSAX2SetDocumentLocator:
813 * @ctx: the user data (XML parser context)
814 * @loc: A SAX Locator
815 *
816 * Receive the document locator at startup, actually xmlDefaultSAXLocator
817 * Everything is available on the context, so this is useless in our case.
818 */
819void
820xmlSAX2SetDocumentLocator(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
821{
822 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
823#ifdef DEBUG_SAX
824 xmlGenericError(xmlGenericErrorContext,
825 "SAX.xmlSAX2SetDocumentLocator()\n");
826#endif
827}
828
829/**
830 * xmlSAX2StartDocument:
831 * @ctx: the user data (XML parser context)
832 *
833 * called when the document start being processed.
834 */
835void
836xmlSAX2StartDocument(void *ctx)
837{
838 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
839 xmlDocPtr doc;
840
Daniel Veillard34099b42004-11-04 17:34:35 +0000841 if (ctx == NULL) return;
842
Daniel Veillard1af9a412003-08-20 22:54:39 +0000843#ifdef DEBUG_SAX
844 xmlGenericError(xmlGenericErrorContext,
845 "SAX.xmlSAX2StartDocument()\n");
846#endif
847 if (ctxt->html) {
848#ifdef LIBXML_HTML_ENABLED
849 if (ctxt->myDoc == NULL)
850 ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
851 if (ctxt->myDoc == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +0000852 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
Daniel Veillard1af9a412003-08-20 22:54:39 +0000853 return;
854 }
855#else
856 xmlGenericError(xmlGenericErrorContext,
857 "libxml2 built without HTML support\n");
858 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
859 ctxt->instate = XML_PARSER_EOF;
860 ctxt->disableSAX = 1;
861 return;
862#endif
863 } else {
864 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
865 if (doc != NULL) {
866 if (ctxt->encoding != NULL)
867 doc->encoding = xmlStrdup(ctxt->encoding);
868 else
869 doc->encoding = NULL;
870 doc->standalone = ctxt->standalone;
871 } else {
William M. Brack42331a92004-07-29 07:07:16 +0000872 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
Daniel Veillard1af9a412003-08-20 22:54:39 +0000873 return;
874 }
Daniel Veillard500a1de2004-03-22 15:22:58 +0000875 if ((ctxt->dictNames) && (doc != NULL)) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +0000876 doc->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000877 xmlDictReference(doc->dict);
878 }
Daniel Veillard1af9a412003-08-20 22:54:39 +0000879 }
880 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
881 (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
882 ctxt->myDoc->URL = xmlCanonicPath((const xmlChar *) ctxt->input->filename);
883 if (ctxt->myDoc->URL == NULL)
William M. Bracka3215c72004-07-31 16:24:01 +0000884 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
Daniel Veillard1af9a412003-08-20 22:54:39 +0000885 }
886}
887
888/**
889 * xmlSAX2EndDocument:
890 * @ctx: the user data (XML parser context)
891 *
892 * called when the document end has been detected.
893 */
894void
895xmlSAX2EndDocument(void *ctx)
896{
897 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
898#ifdef DEBUG_SAX
899 xmlGenericError(xmlGenericErrorContext,
900 "SAX.xmlSAX2EndDocument()\n");
901#endif
Daniel Veillard34099b42004-11-04 17:34:35 +0000902 if (ctx == NULL) return;
Daniel Veillard4432df22003-09-28 18:58:27 +0000903#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000904 if (ctxt->validate && ctxt->wellFormed &&
905 ctxt->myDoc && ctxt->myDoc->intSubset)
906 ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
Daniel Veillard4432df22003-09-28 18:58:27 +0000907#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000908
909 /*
910 * Grab the encoding if it was added on-the-fly
911 */
912 if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
913 (ctxt->myDoc->encoding == NULL)) {
914 ctxt->myDoc->encoding = ctxt->encoding;
915 ctxt->encoding = NULL;
916 }
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000917 if ((ctxt->inputTab != NULL) &&
918 (ctxt->inputNr > 0) && (ctxt->inputTab[0] != NULL) &&
919 (ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
Daniel Veillard1af9a412003-08-20 22:54:39 +0000920 (ctxt->myDoc->encoding == NULL)) {
921 ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
922 }
923 if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
924 (ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
925 ctxt->myDoc->charset = ctxt->charset;
926 }
927}
928
Daniel Veillard81273902003-09-30 00:43:48 +0000929#if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED)
Daniel Veillard1af9a412003-08-20 22:54:39 +0000930/**
931 * xmlSAX2AttributeInternal:
932 * @ctx: the user data (XML parser context)
933 * @fullname: The attribute name, including namespace prefix
934 * @value: The attribute value
935 * @prefix: the prefix on the element node
936 *
937 * Handle an attribute that has been read by the parser.
938 * The default handling is to convert the attribute into an
939 * DOM subtree and past it in a new xmlAttr element added to
940 * the element.
941 */
942static void
943xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000944 const xmlChar *value, const xmlChar *prefix ATTRIBUTE_UNUSED)
Daniel Veillard1af9a412003-08-20 22:54:39 +0000945{
946 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
947 xmlAttrPtr ret;
948 xmlChar *name;
949 xmlChar *ns;
950 xmlChar *nval;
951 xmlNsPtr namespace;
952
953 /*
954 * Split the full name into a namespace prefix and the tag name
955 */
956 name = xmlSplitQName(ctxt, fullname, &ns);
957 if ((name != NULL) && (name[0] == 0)) {
958 if (xmlStrEqual(ns, BAD_CAST "xmlns")) {
959 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
960 ctxt->sax->error(ctxt->userData,
961 "invalid namespace declaration '%s'\n", fullname);
962 } else {
963 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
964 ctxt->sax->warning(ctxt->userData,
965 "Avoid attribute ending with ':' like '%s'\n", fullname);
966 }
967 if (ns != NULL)
968 xmlFree(ns);
969 ns = NULL;
970 xmlFree(name);
971 name = xmlStrdup(fullname);
972 }
973 if (name == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +0000974 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
Daniel Veillard1af9a412003-08-20 22:54:39 +0000975 if (ns != NULL)
976 xmlFree(ns);
977 return;
978 }
979
Daniel Veillard4432df22003-09-28 18:58:27 +0000980#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000981 /*
982 * Do the last stage of the attribute normalization
983 * Needed for HTML too:
984 * http://www.w3.org/TR/html4/types.html#h-6.2
985 */
986 ctxt->vctxt.valid = 1;
987 nval = xmlValidCtxtNormalizeAttributeValue(&ctxt->vctxt,
988 ctxt->myDoc, ctxt->node,
989 fullname, value);
990 if (ctxt->vctxt.valid != 1) {
991 ctxt->valid = 0;
992 }
993 if (nval != NULL)
994 value = nval;
Daniel Veillard4432df22003-09-28 18:58:27 +0000995#else
996 nval = NULL;
997#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000998
999 /*
1000 * Check whether it's a namespace definition
1001 */
1002 if ((!ctxt->html) && (ns == NULL) &&
1003 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
1004 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
1005 xmlNsPtr nsret;
1006 xmlChar *val;
1007
1008 if (!ctxt->replaceEntities) {
1009 ctxt->depth++;
1010 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1011 0,0,0);
1012 ctxt->depth--;
1013 } else {
1014 val = (xmlChar *) value;
1015 }
1016
1017 if (val[0] != 0) {
1018 xmlURIPtr uri;
1019
1020 uri = xmlParseURI((const char *)val);
1021 if (uri == NULL) {
1022 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1023 ctxt->sax->warning(ctxt->userData,
William M. Brack4811ba32003-09-06 18:02:53 +00001024 "xmlns: %s not a valid URI\n", val);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001025 } else {
1026 if (uri->scheme == NULL) {
1027 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1028 ctxt->sax->warning(ctxt->userData,
1029 "xmlns: URI %s is not absolute\n", val);
1030 }
1031 xmlFreeURI(uri);
1032 }
1033 }
1034
1035 /* a default namespace definition */
1036 nsret = xmlNewNs(ctxt->node, val, NULL);
1037
Daniel Veillard4432df22003-09-28 18:58:27 +00001038#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001039 /*
1040 * Validate also for namespace decls, they are attributes from
1041 * an XML-1.0 perspective
1042 */
1043 if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
1044 ctxt->myDoc && ctxt->myDoc->intSubset)
1045 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
1046 ctxt->node, prefix, nsret, val);
Daniel Veillard4432df22003-09-28 18:58:27 +00001047#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001048 if (name != NULL)
1049 xmlFree(name);
1050 if (nval != NULL)
1051 xmlFree(nval);
1052 if (val != value)
1053 xmlFree(val);
1054 return;
1055 }
1056 if ((!ctxt->html) &&
1057 (ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
1058 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
1059 xmlNsPtr nsret;
1060 xmlChar *val;
1061
1062 if (!ctxt->replaceEntities) {
1063 ctxt->depth++;
1064 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1065 0,0,0);
1066 ctxt->depth--;
1067 if (val == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001068 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
Daniel Veillard1af9a412003-08-20 22:54:39 +00001069 xmlFree(ns);
1070 if (name != NULL)
1071 xmlFree(name);
1072 return;
1073 }
1074 } else {
1075 val = (xmlChar *) value;
1076 }
1077
1078 if (val[0] == 0) {
1079 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1080 ctxt->sax->error(ctxt->userData,
1081 "Empty namespace name for prefix %s\n", name);
1082 }
1083 if ((ctxt->pedantic != 0) && (val[0] != 0)) {
1084 xmlURIPtr uri;
1085
1086 uri = xmlParseURI((const char *)val);
1087 if (uri == NULL) {
1088 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1089 ctxt->sax->warning(ctxt->userData,
1090 "xmlns:%s: %s not a valid URI\n", name, value);
1091 } else {
1092 if (uri->scheme == NULL) {
1093 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1094 ctxt->sax->warning(ctxt->userData,
1095 "xmlns:%s: URI %s is not absolute\n", name, value);
1096 }
1097 xmlFreeURI(uri);
1098 }
1099 }
1100
1101 /* a standard namespace definition */
1102 nsret = xmlNewNs(ctxt->node, val, name);
1103 xmlFree(ns);
Daniel Veillard4432df22003-09-28 18:58:27 +00001104#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001105 /*
1106 * Validate also for namespace decls, they are attributes from
1107 * an XML-1.0 perspective
1108 */
1109 if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
1110 ctxt->myDoc && ctxt->myDoc->intSubset)
1111 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
1112 ctxt->node, prefix, nsret, value);
Daniel Veillard4432df22003-09-28 18:58:27 +00001113#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001114 if (name != NULL)
1115 xmlFree(name);
1116 if (nval != NULL)
1117 xmlFree(nval);
1118 if (val != value)
1119 xmlFree(val);
1120 return;
1121 }
1122
1123 if (ns != NULL) {
1124 xmlAttrPtr prop;
1125 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
Daniel Veillard67906942003-08-28 21:13:25 +00001126 if (namespace == NULL) {
William M. Brack4811ba32003-09-06 18:02:53 +00001127 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1128 ctxt->sax->error(ctxt->userData,
1129 "Namespace prefix %s of attribute %s is not defined\n",
Daniel Veillard67906942003-08-28 21:13:25 +00001130 ns, name);
1131 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001132
1133 prop = ctxt->node->properties;
1134 while (prop != NULL) {
1135 if (prop->ns != NULL) {
1136 if ((xmlStrEqual(name, prop->name)) &&
1137 ((namespace == prop->ns) ||
1138 (xmlStrEqual(namespace->href, prop->ns->href)))) {
1139 ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
1140 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1141 ctxt->sax->error(ctxt->userData,
1142 "Attribute %s in %s redefined\n",
1143 name, namespace->href);
1144 ctxt->wellFormed = 0;
1145 if (ctxt->recovery == 0) ctxt->disableSAX = 1;
1146 goto error;
1147 }
1148 }
1149 prop = prop->next;
1150 }
1151 } else {
1152 namespace = NULL;
1153 }
1154
1155 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
1156 ret = xmlNewNsPropEatName(ctxt->node, namespace, name, NULL);
1157
1158 if (ret != NULL) {
1159 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
1160 xmlNodePtr tmp;
1161
1162 ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
1163 tmp = ret->children;
1164 while (tmp != NULL) {
1165 tmp->parent = (xmlNodePtr) ret;
1166 if (tmp->next == NULL)
1167 ret->last = tmp;
1168 tmp = tmp->next;
1169 }
1170 } else if (value != NULL) {
1171 ret->children = xmlNewDocText(ctxt->myDoc, value);
1172 ret->last = ret->children;
1173 if (ret->children != NULL)
1174 ret->children->parent = (xmlNodePtr) ret;
1175 }
1176 }
1177
Daniel Veillard4432df22003-09-28 18:58:27 +00001178#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001179 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
1180 ctxt->myDoc && ctxt->myDoc->intSubset) {
1181
1182 /*
1183 * If we don't substitute entities, the validation should be
1184 * done on a value with replaced entities anyway.
1185 */
1186 if (!ctxt->replaceEntities) {
1187 xmlChar *val;
1188
1189 ctxt->depth++;
1190 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1191 0,0,0);
1192 ctxt->depth--;
1193
1194 if (val == NULL)
1195 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1196 ctxt->myDoc, ctxt->node, ret, value);
1197 else {
1198 xmlChar *nvalnorm;
1199
1200 /*
1201 * Do the last stage of the attribute normalization
1202 * It need to be done twice ... it's an extra burden related
1203 * to the ability to keep xmlSAX2References in attributes
1204 */
1205 nvalnorm = xmlValidNormalizeAttributeValue(ctxt->myDoc,
1206 ctxt->node, fullname, val);
1207 if (nvalnorm != NULL) {
1208 xmlFree(val);
1209 val = nvalnorm;
1210 }
1211
1212 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1213 ctxt->myDoc, ctxt->node, ret, val);
1214 xmlFree(val);
1215 }
1216 } else {
1217 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
1218 ctxt->node, ret, value);
1219 }
Daniel Veillard4432df22003-09-28 18:58:27 +00001220 } else
1221#endif /* LIBXML_VALID_ENABLED */
1222 if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
Daniel Veillard1af9a412003-08-20 22:54:39 +00001223 (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
1224 ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
1225 /*
1226 * when validating, the ID registration is done at the attribute
1227 * validation level. Otherwise we have to do specific handling here.
1228 */
1229 if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
1230 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
1231 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
1232 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00001233 else if (xmlStrEqual(fullname, BAD_CAST "xml:id")) {
1234 /*
1235 * Add the xml:id value
1236 *
1237 * Open issue: normalization of the value.
1238 */
Daniel Veillard68cb4b22004-04-18 20:55:39 +00001239 if (xmlValidateNCName(value, 1) != 0) {
1240 xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
1241 "xml:id : attribute value %s is not an NCName\n",
1242 (const char *) value, NULL);
1243 }
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00001244 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
1245 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001246 }
1247
1248error:
1249 if (nval != NULL)
1250 xmlFree(nval);
1251 if (ns != NULL)
1252 xmlFree(ns);
1253}
1254
Daniel Veillard1af9a412003-08-20 22:54:39 +00001255/*
1256 * xmlCheckDefaultedAttributes:
1257 *
1258 * Check defaulted attributes from the DTD
1259 */
1260static void
1261xmlCheckDefaultedAttributes(xmlParserCtxtPtr ctxt, const xmlChar *name,
1262 const xmlChar *prefix, const xmlChar **atts) {
1263 xmlElementPtr elemDecl;
1264 const xmlChar *att;
1265 int internal = 1;
1266 int i;
1267
1268 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset, name, prefix);
1269 if (elemDecl == NULL) {
1270 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset, name, prefix);
1271 internal = 0;
1272 }
1273
1274process_external_subset:
1275
1276 if (elemDecl != NULL) {
1277 xmlAttributePtr attr = elemDecl->attributes;
1278 /*
1279 * Check against defaulted attributes from the external subset
1280 * if the document is stamped as standalone
1281 */
1282 if ((ctxt->myDoc->standalone == 1) &&
1283 (ctxt->myDoc->extSubset != NULL) &&
1284 (ctxt->validate)) {
1285 while (attr != NULL) {
1286 if ((attr->defaultValue != NULL) &&
1287 (xmlGetDtdQAttrDesc(ctxt->myDoc->extSubset,
1288 attr->elem, attr->name,
1289 attr->prefix) == attr) &&
1290 (xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1291 attr->elem, attr->name,
1292 attr->prefix) == NULL)) {
1293 xmlChar *fulln;
1294
1295 if (attr->prefix != NULL) {
1296 fulln = xmlStrdup(attr->prefix);
1297 fulln = xmlStrcat(fulln, BAD_CAST ":");
1298 fulln = xmlStrcat(fulln, attr->name);
1299 } else {
1300 fulln = xmlStrdup(attr->name);
1301 }
1302
1303 /*
1304 * Check that the attribute is not declared in the
1305 * serialization
1306 */
1307 att = NULL;
1308 if (atts != NULL) {
1309 i = 0;
1310 att = atts[i];
1311 while (att != NULL) {
1312 if (xmlStrEqual(att, fulln))
1313 break;
1314 i += 2;
1315 att = atts[i];
1316 }
1317 }
1318 if (att == NULL) {
Daniel Veillardf88d8cf2003-12-08 10:25:02 +00001319 xmlErrValid(ctxt, XML_DTD_STANDALONE_DEFAULTED,
Daniel Veillard1af9a412003-08-20 22:54:39 +00001320 "standalone: attribute %s on %s defaulted from external subset\n",
Daniel Veillard427174f2003-12-10 10:42:59 +00001321 (const char *)fulln,
1322 (const char *)attr->elem);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001323 }
1324 }
1325 attr = attr->nexth;
1326 }
1327 }
1328
1329 /*
1330 * Actually insert defaulted values when needed
1331 */
1332 attr = elemDecl->attributes;
1333 while (attr != NULL) {
1334 /*
1335 * Make sure that attributes redefinition occuring in the
1336 * internal subset are not overriden by definitions in the
1337 * external subset.
1338 */
1339 if (attr->defaultValue != NULL) {
1340 /*
1341 * the element should be instantiated in the tree if:
1342 * - this is a namespace prefix
1343 * - the user required for completion in the tree
1344 * like XSLT
1345 * - there isn't already an attribute definition
1346 * in the internal subset overriding it.
1347 */
1348 if (((attr->prefix != NULL) &&
1349 (xmlStrEqual(attr->prefix, BAD_CAST "xmlns"))) ||
1350 ((attr->prefix == NULL) &&
1351 (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) ||
1352 (ctxt->loadsubset & XML_COMPLETE_ATTRS)) {
1353 xmlAttributePtr tst;
1354
1355 tst = xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1356 attr->elem, attr->name,
1357 attr->prefix);
1358 if ((tst == attr) || (tst == NULL)) {
1359 xmlChar fn[50];
1360 xmlChar *fulln;
1361
1362 fulln = xmlBuildQName(attr->name, attr->prefix, fn, 50);
1363 if (fulln == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001364 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
Daniel Veillard1af9a412003-08-20 22:54:39 +00001365 return;
1366 }
1367
1368 /*
1369 * Check that the attribute is not declared in the
1370 * serialization
1371 */
1372 att = NULL;
1373 if (atts != NULL) {
1374 i = 0;
1375 att = atts[i];
1376 while (att != NULL) {
1377 if (xmlStrEqual(att, fulln))
1378 break;
1379 i += 2;
1380 att = atts[i];
1381 }
1382 }
1383 if (att == NULL) {
1384 xmlSAX2AttributeInternal(ctxt, fulln,
1385 attr->defaultValue, prefix);
1386 }
1387 if ((fulln != fn) && (fulln != attr->name))
1388 xmlFree(fulln);
1389 }
1390 }
1391 }
1392 attr = attr->nexth;
1393 }
1394 if (internal == 1) {
1395 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset,
1396 name, prefix);
1397 internal = 0;
1398 goto process_external_subset;
1399 }
1400 }
1401}
1402
1403/**
1404 * xmlSAX2StartElement:
1405 * @ctx: the user data (XML parser context)
1406 * @fullname: The element name, including namespace prefix
1407 * @atts: An array of name/value attributes pairs, NULL terminated
1408 *
1409 * called when an opening tag has been processed.
1410 */
1411void
1412xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
1413{
1414 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1415 xmlNodePtr ret;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00001416 xmlNodePtr parent;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001417 xmlNsPtr ns;
1418 xmlChar *name;
1419 xmlChar *prefix;
1420 const xmlChar *att;
1421 const xmlChar *value;
1422 int i;
1423
Daniel Veillarda521d282004-11-09 14:59:59 +00001424 if ((ctx == NULL) || (fullname == NULL) || (ctxt->myDoc == NULL)) return;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00001425 parent = ctxt->node;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001426#ifdef DEBUG_SAX
1427 xmlGenericError(xmlGenericErrorContext,
1428 "SAX.xmlSAX2StartElement(%s)\n", fullname);
1429#endif
1430
1431 /*
1432 * First check on validity:
1433 */
1434 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
1435 ((ctxt->myDoc->intSubset == NULL) ||
1436 ((ctxt->myDoc->intSubset->notations == NULL) &&
1437 (ctxt->myDoc->intSubset->elements == NULL) &&
1438 (ctxt->myDoc->intSubset->attributes == NULL) &&
1439 (ctxt->myDoc->intSubset->entities == NULL)))) {
Daniel Veillardf88d8cf2003-12-08 10:25:02 +00001440 xmlErrValid(ctxt, XML_ERR_NO_DTD,
1441 "Validation failed: no DTD found !", NULL, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001442 ctxt->validate = 0;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001443 }
1444
1445
1446 /*
1447 * Split the full name into a namespace prefix and the tag name
1448 */
1449 name = xmlSplitQName(ctxt, fullname, &prefix);
1450
1451
1452 /*
1453 * Note : the namespace resolution is deferred until the end of the
1454 * attributes parsing, since local namespace can be defined as
1455 * an attribute at this level.
1456 */
1457 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL);
1458 if (ret == NULL) {
1459 if (prefix != NULL)
1460 xmlFree(prefix);
William M. Brack42331a92004-07-29 07:07:16 +00001461 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
Daniel Veillard1af9a412003-08-20 22:54:39 +00001462 return;
1463 }
1464 if (ctxt->myDoc->children == NULL) {
1465#ifdef DEBUG_SAX_TREE
1466 xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
1467#endif
1468 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1469 } else if (parent == NULL) {
1470 parent = ctxt->myDoc->children;
1471 }
1472 ctxt->nodemem = -1;
1473 if (ctxt->linenumbers) {
Daniel Veillard3e35f8e2003-10-21 00:05:38 +00001474 if (ctxt->input != NULL) {
1475 if (ctxt->input->line < 65535)
1476 ret->line = (short) ctxt->input->line;
1477 else
1478 ret->line = 65535;
1479 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001480 }
1481
1482 /*
1483 * We are parsing a new node.
1484 */
1485#ifdef DEBUG_SAX_TREE
1486 xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);
1487#endif
1488 nodePush(ctxt, ret);
1489
1490 /*
1491 * Link the child element
1492 */
1493 if (parent != NULL) {
1494 if (parent->type == XML_ELEMENT_NODE) {
1495#ifdef DEBUG_SAX_TREE
1496 xmlGenericError(xmlGenericErrorContext,
1497 "adding child %s to %s\n", name, parent->name);
1498#endif
1499 xmlAddChild(parent, ret);
1500 } else {
1501#ifdef DEBUG_SAX_TREE
1502 xmlGenericError(xmlGenericErrorContext,
1503 "adding sibling %s to ", name);
1504 xmlDebugDumpOneNode(stderr, parent, 0);
1505#endif
1506 xmlAddSibling(parent, ret);
1507 }
1508 }
1509
1510 /*
1511 * Insert all the defaulted attributes from the DTD especially namespaces
1512 */
1513 if ((!ctxt->html) &&
1514 ((ctxt->myDoc->intSubset != NULL) ||
1515 (ctxt->myDoc->extSubset != NULL))) {
1516 xmlCheckDefaultedAttributes(ctxt, name, prefix, atts);
1517 }
1518
1519 /*
1520 * process all the attributes whose name start with "xmlns"
1521 */
1522 if (atts != NULL) {
1523 i = 0;
1524 att = atts[i++];
1525 value = atts[i++];
1526 if (!ctxt->html) {
1527 while ((att != NULL) && (value != NULL)) {
1528 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l') &&
1529 (att[3] == 'n') && (att[4] == 's'))
1530 xmlSAX2AttributeInternal(ctxt, att, value, prefix);
1531
1532 att = atts[i++];
1533 value = atts[i++];
1534 }
1535 }
1536 }
1537
1538 /*
1539 * Search the namespace, note that since the attributes have been
1540 * processed, the local namespaces are available.
1541 */
1542 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
1543 if ((ns == NULL) && (parent != NULL))
1544 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
1545 if ((prefix != NULL) && (ns == NULL)) {
1546 ns = xmlNewNs(ret, NULL, prefix);
1547 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1548 ctxt->sax->warning(ctxt->userData,
1549 "Namespace prefix %s is not defined\n", prefix);
1550 }
1551
1552 /*
1553 * set the namespace node, making sure that if the default namspace
1554 * is unbound on a parent we simply kee it NULL
1555 */
1556 if ((ns != NULL) && (ns->href != NULL) &&
1557 ((ns->href[0] != 0) || (ns->prefix != NULL)))
1558 xmlSetNs(ret, ns);
1559
1560 /*
1561 * process all the other attributes
1562 */
1563 if (atts != NULL) {
1564 i = 0;
1565 att = atts[i++];
1566 value = atts[i++];
1567 if (ctxt->html) {
1568 while (att != NULL) {
1569 xmlSAX2AttributeInternal(ctxt, att, value, NULL);
1570 att = atts[i++];
1571 value = atts[i++];
1572 }
1573 } else {
1574 while ((att != NULL) && (value != NULL)) {
1575 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l') ||
1576 (att[3] != 'n') || (att[4] != 's'))
1577 xmlSAX2AttributeInternal(ctxt, att, value, NULL);
1578
1579 /*
1580 * Next ones
1581 */
1582 att = atts[i++];
1583 value = atts[i++];
1584 }
1585 }
1586 }
1587
Daniel Veillard4432df22003-09-28 18:58:27 +00001588#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001589 /*
1590 * If it's the Document root, finish the DTD validation and
1591 * check the document root element for validity
1592 */
Daniel Veillardeff45a92004-10-29 12:10:55 +00001593 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == XML_CTXT_FINISH_DTD_0)) {
Daniel Veillard1af9a412003-08-20 22:54:39 +00001594 int chk;
1595
1596 chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
1597 if (chk <= 0)
1598 ctxt->valid = 0;
1599 if (chk < 0)
1600 ctxt->wellFormed = 0;
1601 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
Daniel Veillardeff45a92004-10-29 12:10:55 +00001602 ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_1;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001603 }
Daniel Veillard4432df22003-09-28 18:58:27 +00001604#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001605
1606 if (prefix != NULL)
1607 xmlFree(prefix);
1608
1609}
1610
1611/**
1612 * xmlSAX2EndElement:
1613 * @ctx: the user data (XML parser context)
1614 * @name: The element name
1615 *
1616 * called when the end of an element has been detected.
1617 */
1618void
1619xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
1620{
1621 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1622 xmlParserNodeInfo node_info;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00001623 xmlNodePtr cur;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001624
Daniel Veillard34099b42004-11-04 17:34:35 +00001625 if (ctx == NULL) return;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00001626 cur = ctxt->node;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001627#ifdef DEBUG_SAX
1628 if (name == NULL)
1629 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(NULL)\n");
1630 else
1631 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(%s)\n", name);
1632#endif
1633
1634 /* Capture end position and add node */
1635 if (cur != NULL && ctxt->record_info) {
1636 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
1637 node_info.end_line = ctxt->input->line;
1638 node_info.node = cur;
1639 xmlParserAddNodeInfo(ctxt, &node_info);
1640 }
1641 ctxt->nodemem = -1;
1642
Daniel Veillard4432df22003-09-28 18:58:27 +00001643#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001644 if (ctxt->validate && ctxt->wellFormed &&
1645 ctxt->myDoc && ctxt->myDoc->intSubset)
1646 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
1647 cur);
Daniel Veillard4432df22003-09-28 18:58:27 +00001648#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001649
1650
1651 /*
1652 * end of parsing of this node.
1653 */
1654#ifdef DEBUG_SAX_TREE
1655 xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);
1656#endif
1657 nodePop(ctxt);
1658}
Daniel Veillard81273902003-09-30 00:43:48 +00001659#endif /* LIBXML_SAX1_ENABLED || LIBXML_HTML_ENABLE */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001660
Daniel Veillarde57ec792003-09-10 10:50:59 +00001661/*
Daniel Veillard19895052003-09-17 13:59:32 +00001662 * xmlSAX2TextNode:
1663 * @ctxt: the parser context
1664 * @str: the input string
1665 * @len: the string length
1666 *
1667 * Remove the entities from an attribute value
1668 *
1669 * Returns the newly allocated string or NULL if not needed or error
1670 */
1671static xmlNodePtr
1672xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
1673 xmlNodePtr ret;
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001674 const xmlChar *intern = NULL;
Daniel Veillard19895052003-09-17 13:59:32 +00001675
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001676 /*
1677 * Allocate
1678 */
Daniel Veillard19895052003-09-17 13:59:32 +00001679 if (ctxt->freeElems != NULL) {
1680 ret = ctxt->freeElems;
1681 ctxt->freeElems = ret->next;
1682 ctxt->freeElemsNr--;
Daniel Veillard19895052003-09-17 13:59:32 +00001683 } else {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001684 ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard19895052003-09-17 13:59:32 +00001685 }
1686 if (ret == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001687 xmlErrMemory(ctxt, "xmlSAX2Characters");
Daniel Veillard19895052003-09-17 13:59:32 +00001688 return(NULL);
1689 }
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001690 /*
1691 * intern the formatting blanks found between tags, or the
1692 * very short strings
1693 */
1694 if (ctxt->dictNames) {
1695 xmlChar cur = str[len];
1696
Daniel Veillarddca8cc72003-09-26 13:53:14 +00001697 if ((len <= 3) && ((cur == '"') || (cur == '\'') ||
1698 ((cur == '<') && (str[len + 1] != '!')))) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001699 intern = xmlDictLookup(ctxt->dict, str, len);
William M. Brack76e95df2003-10-18 16:20:14 +00001700 } else if (IS_BLANK_CH(*str) && (len < 60) && (cur == '<') &&
Daniel Veillarddca8cc72003-09-26 13:53:14 +00001701 (str[len + 1] != '!')) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001702 int i;
1703
1704 for (i = 1;i < len;i++) {
Daniel Veillard1a9b7082004-01-02 10:42:01 +00001705 if (!IS_BLANK_CH(str[i])) goto skip;
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001706 }
1707 intern = xmlDictLookup(ctxt->dict, str, len);
1708 }
1709 }
1710skip:
1711 memset(ret, 0, sizeof(xmlNode));
1712 ret->type = XML_TEXT_NODE;
1713
1714 ret->name = xmlStringText;
William M. Brack9f797ab2004-07-28 07:40:12 +00001715 if (intern == NULL) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001716 ret->content = xmlStrndup(str, len);
William M. Brack9f797ab2004-07-28 07:40:12 +00001717 if (ret->content == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001718 xmlSAX2ErrMemory(ctxt, "xmlSAX2TextNode");
1719 xmlFree(ret);
William M. Brack9f797ab2004-07-28 07:40:12 +00001720 return(NULL);
1721 }
1722 } else
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001723 ret->content = (xmlChar *) intern;
1724
1725 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1726 xmlRegisterNodeDefaultValue(ret);
Daniel Veillard19895052003-09-17 13:59:32 +00001727 return(ret);
1728}
1729
Daniel Veillard4432df22003-09-28 18:58:27 +00001730#ifdef LIBXML_VALID_ENABLED
Daniel Veillard19895052003-09-17 13:59:32 +00001731/*
Daniel Veillarde57ec792003-09-10 10:50:59 +00001732 * xmlSAX2DecodeAttrEntities:
1733 * @ctxt: the parser context
1734 * @str: the input string
1735 * @len: the string length
1736 *
1737 * Remove the entities from an attribute value
1738 *
1739 * Returns the newly allocated string or NULL if not needed or error
1740 */
1741static xmlChar *
1742xmlSAX2DecodeAttrEntities(xmlParserCtxtPtr ctxt, const xmlChar *str,
1743 const xmlChar *end) {
1744 const xmlChar *in;
1745 xmlChar *ret;
1746
1747 in = str;
1748 while (in < end)
1749 if (*in++ == '&')
1750 goto decode;
1751 return(NULL);
1752decode:
1753 ctxt->depth++;
1754 ret = xmlStringLenDecodeEntities(ctxt, str, end - str,
1755 XML_SUBSTITUTE_REF, 0,0,0);
1756 ctxt->depth--;
1757 return(ret);
1758}
Daniel Veillard4432df22003-09-28 18:58:27 +00001759#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00001760
1761/**
1762 * xmlSAX2AttributeNs:
1763 * @ctx: the user data (XML parser context)
Daniel Veillard62998c02003-09-15 12:56:36 +00001764 * @localname: the local name of the attribute
1765 * @prefix: the attribute namespace prefix if available
1766 * @URI: the attribute namespace name if available
Daniel Veillarde57ec792003-09-10 10:50:59 +00001767 * @value: Start of the attribute value
1768 * @valueend: end of the attribute value
1769 *
1770 * Handle an attribute that has been read by the parser.
1771 * The default handling is to convert the attribute into an
1772 * DOM subtree and past it in a new xmlAttr element added to
1773 * the element.
1774 */
1775static void
1776xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
1777 const xmlChar * localname,
1778 const xmlChar * prefix,
1779 const xmlChar * value,
1780 const xmlChar * valueend)
1781{
1782 xmlAttrPtr ret;
1783 xmlNsPtr namespace = NULL;
1784 xmlChar *dup = NULL;
1785
Daniel Veillarde57ec792003-09-10 10:50:59 +00001786 /*
1787 * Note: if prefix == NULL, the attribute is not in the default namespace
1788 */
1789 if (prefix != NULL)
1790 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, prefix);
1791
Daniel Veillard8a44e592003-09-15 14:50:06 +00001792 /*
1793 * allocate the node
1794 */
1795 if (ctxt->freeAttrs != NULL) {
1796 ret = ctxt->freeAttrs;
1797 ctxt->freeAttrs = ret->next;
Daniel Veillard19895052003-09-17 13:59:32 +00001798 ctxt->freeAttrsNr--;
Daniel Veillard8a44e592003-09-15 14:50:06 +00001799 memset(ret, 0, sizeof(xmlAttr));
1800 ret->type = XML_ATTRIBUTE_NODE;
Daniel Veillarde57ec792003-09-10 10:50:59 +00001801
Daniel Veillard8a44e592003-09-15 14:50:06 +00001802 ret->parent = ctxt->node;
1803 ret->doc = ctxt->myDoc;
1804 ret->ns = namespace;
Daniel Veillarde57ec792003-09-10 10:50:59 +00001805
Daniel Veillard8a44e592003-09-15 14:50:06 +00001806 if (ctxt->dictNames)
1807 ret->name = localname;
1808 else
1809 ret->name = xmlStrdup(localname);
1810
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001811 /* link at the end to preserv order, TODO speed up with a last */
1812 if (ctxt->node->properties == NULL) {
1813 ctxt->node->properties = ret;
1814 } else {
1815 xmlAttrPtr prev = ctxt->node->properties;
1816
1817 while (prev->next != NULL) prev = prev->next;
1818 prev->next = ret;
1819 ret->prev = prev;
1820 }
1821
Daniel Veillard8a44e592003-09-15 14:50:06 +00001822 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1823 xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
1824 } else {
1825 if (ctxt->dictNames)
1826 ret = xmlNewNsPropEatName(ctxt->node, namespace,
1827 (xmlChar *) localname, NULL);
1828 else
1829 ret = xmlNewNsProp(ctxt->node, namespace, localname, NULL);
1830 if (ret == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001831 xmlErrMemory(ctxt, "xmlSAX2AttributeNs");
Daniel Veillard8a44e592003-09-15 14:50:06 +00001832 return;
Daniel Veillarde57ec792003-09-10 10:50:59 +00001833 }
1834 }
1835
Daniel Veillard8a44e592003-09-15 14:50:06 +00001836 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
1837 xmlNodePtr tmp;
1838
Daniel Veillard19895052003-09-17 13:59:32 +00001839 /*
1840 * We know that if there is an entity reference, then
1841 * the string has been dup'ed and terminates with 0
1842 * otherwise with ' or "
1843 */
1844 if (*valueend != 0) {
1845 tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
1846 ret->children = tmp;
1847 ret->last = tmp;
1848 if (tmp != NULL) {
1849 tmp->doc = ret->doc;
1850 tmp->parent = (xmlNodePtr) ret;
1851 }
1852 } else {
1853 ret->children = xmlStringLenGetNodeList(ctxt->myDoc, value,
1854 valueend - value);
1855 tmp = ret->children;
1856 while (tmp != NULL) {
Daniel Veillard8de5c0b2004-10-07 13:14:19 +00001857 tmp->doc = ret->doc;
Daniel Veillard19895052003-09-17 13:59:32 +00001858 tmp->parent = (xmlNodePtr) ret;
1859 if (tmp->next == NULL)
1860 ret->last = tmp;
1861 tmp = tmp->next;
1862 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00001863 }
1864 } else if (value != NULL) {
Daniel Veillard19895052003-09-17 13:59:32 +00001865 xmlNodePtr tmp;
1866
1867 tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
1868 ret->children = tmp;
1869 ret->last = tmp;
1870 if (tmp != NULL) {
1871 tmp->doc = ret->doc;
1872 tmp->parent = (xmlNodePtr) ret;
1873 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00001874 }
1875
Daniel Veillard4432df22003-09-28 18:58:27 +00001876#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00001877 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
1878 ctxt->myDoc && ctxt->myDoc->intSubset) {
1879 /*
1880 * If we don't substitute entities, the validation should be
1881 * done on a value with replaced entities anyway.
1882 */
1883 if (!ctxt->replaceEntities) {
1884 dup = xmlSAX2DecodeAttrEntities(ctxt, value, valueend);
1885 if (dup == NULL) {
Daniel Veillard62998c02003-09-15 12:56:36 +00001886 if (*valueend == 0) {
1887 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1888 ctxt->myDoc, ctxt->node, ret, value);
1889 } else {
1890 /*
1891 * That should already be normalized.
1892 * cheaper to finally allocate here than duplicate
1893 * entry points in the full validation code
1894 */
1895 dup = xmlStrndup(value, valueend - value);
Daniel Veillarde57ec792003-09-10 10:50:59 +00001896
Daniel Veillard62998c02003-09-15 12:56:36 +00001897 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1898 ctxt->myDoc, ctxt->node, ret, dup);
1899 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00001900 } else {
Daniel Veillard62998c02003-09-15 12:56:36 +00001901 /*
1902 * dup now contains a string of the flattened attribute
1903 * content with entities substitued. Check if we need to
1904 * apply an extra layer of normalization.
Daniel Veillarde57ec792003-09-10 10:50:59 +00001905 * It need to be done twice ... it's an extra burden related
1906 * to the ability to keep references in attributes
1907 */
Daniel Veillard62998c02003-09-15 12:56:36 +00001908 if (ctxt->attsSpecial != NULL) {
1909 xmlChar *nvalnorm;
1910 xmlChar fn[50];
1911 xmlChar *fullname;
1912
1913 fullname = xmlBuildQName(localname, prefix, fn, 50);
1914 if (fullname != NULL) {
1915 ctxt->vctxt.valid = 1;
1916 nvalnorm = xmlValidCtxtNormalizeAttributeValue(
1917 &ctxt->vctxt, ctxt->myDoc,
1918 ctxt->node, fullname, dup);
1919 if (ctxt->vctxt.valid != 1)
1920 ctxt->valid = 0;
1921
1922 if ((fullname != fn) && (fullname != localname))
1923 xmlFree(fullname);
1924 if (nvalnorm != NULL) {
1925 xmlFree(dup);
1926 dup = nvalnorm;
1927 }
1928 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00001929 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00001930
1931 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1932 ctxt->myDoc, ctxt->node, ret, dup);
1933 }
1934 } else {
Daniel Veillard8e36e6a2003-09-10 10:50:59 +00001935 /*
1936 * if entities already have been substitued, then
1937 * the attribute as passed is already normalized
1938 */
Daniel Veillarde57ec792003-09-10 10:50:59 +00001939 dup = xmlStrndup(value, valueend - value);
1940
1941 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1942 ctxt->myDoc, ctxt->node, ret, dup);
1943 }
Daniel Veillard4432df22003-09-28 18:58:27 +00001944 } else
1945#endif /* LIBXML_VALID_ENABLED */
1946 if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
Daniel Veillarde57ec792003-09-10 10:50:59 +00001947 (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
1948 ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
1949 /*
1950 * when validating, the ID registration is done at the attribute
1951 * validation level. Otherwise we have to do specific handling here.
1952 */
1953 if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) {
1954 /* might be worth duplicate entry points and not copy */
1955 if (dup == NULL)
1956 dup = xmlStrndup(value, valueend - value);
1957 xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
1958 } else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) {
1959 if (dup == NULL)
1960 dup = xmlStrndup(value, valueend - value);
1961 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, dup, ret);
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00001962 } else if ((prefix == ctxt->str_xml) &&
1963 (localname[0] == 'i') && (localname[1] == 'd') &&
1964 (localname[2] == 0)) {
1965 /*
1966 * Add the xml:id value
1967 *
1968 * Open issue: normalization of the value.
1969 */
1970 if (dup == NULL)
1971 dup = xmlStrndup(value, valueend - value);
William M. Brack5ef2f812004-05-23 23:56:47 +00001972#ifdef LIBXML_VALID_ENABLED
Daniel Veillard68cb4b22004-04-18 20:55:39 +00001973 if (xmlValidateNCName(dup, 1) != 0) {
1974 xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
1975 "xml:id : attribute value %s is not an NCName\n",
1976 (const char *) dup, NULL);
1977 }
William M. Brack3f147372004-05-22 01:09:26 +00001978#endif
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00001979 xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
1980 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00001981 }
1982 if (dup != NULL)
1983 xmlFree(dup);
1984}
1985
1986/**
1987 * xmlSAX2StartElementNs:
1988 * @ctx: the user data (XML parser context)
1989 * @localname: the local name of the element
1990 * @prefix: the element namespace prefix if available
1991 * @URI: the element namespace name if available
1992 * @nb_namespaces: number of namespace definitions on that node
1993 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
1994 * @nb_attributes: the number of attributes on that node
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00001995 * @nb_defaulted: the number of defaulted attributes.
Daniel Veillarde57ec792003-09-10 10:50:59 +00001996 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
1997 * attribute values.
1998 *
1999 * SAX2 callback when an element start has been detected by the parser.
2000 * It provides the namespace informations for the element, as well as
2001 * the new namespace declarations on the element.
2002 */
2003void
2004xmlSAX2StartElementNs(void *ctx,
2005 const xmlChar *localname,
2006 const xmlChar *prefix,
2007 const xmlChar *URI,
2008 int nb_namespaces,
2009 const xmlChar **namespaces,
2010 int nb_attributes,
2011 int nb_defaulted,
2012 const xmlChar **attributes)
2013{
2014 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2015 xmlNodePtr ret;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002016 xmlNodePtr parent;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002017 xmlNsPtr last = NULL, ns;
2018 const xmlChar *uri, *pref;
2019 int i, j;
2020
Daniel Veillard34099b42004-11-04 17:34:35 +00002021 if (ctx == NULL) return;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002022 parent = ctxt->node;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002023 /*
2024 * First check on validity:
2025 */
2026 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
2027 ((ctxt->myDoc->intSubset == NULL) ||
2028 ((ctxt->myDoc->intSubset->notations == NULL) &&
2029 (ctxt->myDoc->intSubset->elements == NULL) &&
2030 (ctxt->myDoc->intSubset->attributes == NULL) &&
2031 (ctxt->myDoc->intSubset->entities == NULL)))) {
Daniel Veillardf88d8cf2003-12-08 10:25:02 +00002032 xmlErrValid(ctxt, XML_ERR_NO_DTD,
2033 "Validation failed: no DTD found !", NULL, NULL);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002034 ctxt->validate = 0;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002035 }
2036
Daniel Veillard8a44e592003-09-15 14:50:06 +00002037 /*
2038 * allocate the node
2039 */
2040 if (ctxt->freeElems != NULL) {
2041 ret = ctxt->freeElems;
2042 ctxt->freeElems = ret->next;
Daniel Veillard19895052003-09-17 13:59:32 +00002043 ctxt->freeElemsNr--;
Daniel Veillard8a44e592003-09-15 14:50:06 +00002044 memset(ret, 0, sizeof(xmlNode));
2045 ret->type = XML_ELEMENT_NODE;
2046
2047 if (ctxt->dictNames)
2048 ret->name = localname;
William M. Brack9f797ab2004-07-28 07:40:12 +00002049 else {
Daniel Veillard8a44e592003-09-15 14:50:06 +00002050 ret->name = xmlStrdup(localname);
William M. Brack9f797ab2004-07-28 07:40:12 +00002051 if (ret->name == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002052 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
William M. Brack9f797ab2004-07-28 07:40:12 +00002053 return;
2054 }
2055 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00002056 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2057 xmlRegisterNodeDefaultValue(ret);
2058 } else {
2059 if (ctxt->dictNames)
2060 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
2061 (xmlChar *) localname, NULL);
2062 else
2063 ret = xmlNewDocNode(ctxt->myDoc, NULL, localname, NULL);
2064 if (ret == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002065 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
Daniel Veillard8a44e592003-09-15 14:50:06 +00002066 return;
2067 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002068 }
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002069 if (ctxt->linenumbers) {
Daniel Veillard3e35f8e2003-10-21 00:05:38 +00002070 if (ctxt->input != NULL) {
2071 if (ctxt->input->line < 65535)
2072 ret->line = (short) ctxt->input->line;
2073 else
2074 ret->line = 65535;
2075 }
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002076 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00002077
Daniel Veillard29b17482004-08-16 00:39:03 +00002078 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
Daniel Veillarde57ec792003-09-10 10:50:59 +00002079 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002080 }
2081 /*
2082 * Build the namespace list
2083 */
2084 for (i = 0,j = 0;j < nb_namespaces;j++) {
2085 pref = namespaces[i++];
2086 uri = namespaces[i++];
2087 ns = xmlNewNs(NULL, uri, pref);
2088 if (ns != NULL) {
2089 if (last == NULL) {
2090 ret->nsDef = last = ns;
2091 } else {
2092 last->next = ns;
2093 last = ns;
2094 }
2095 if ((URI != NULL) && (prefix == pref))
2096 ret->ns = ns;
2097 } else {
William M. Brack42331a92004-07-29 07:07:16 +00002098 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
Daniel Veillarde57ec792003-09-10 10:50:59 +00002099 return;
2100 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002101#ifdef LIBXML_VALID_ENABLED
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002102 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
2103 ctxt->myDoc && ctxt->myDoc->intSubset) {
2104 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
2105 ret, prefix, ns, uri);
2106 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002107#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002108 }
2109 ctxt->nodemem = -1;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002110
2111 /*
2112 * We are parsing a new node.
2113 */
2114 nodePush(ctxt, ret);
2115
2116 /*
2117 * Link the child element
2118 */
2119 if (parent != NULL) {
2120 if (parent->type == XML_ELEMENT_NODE) {
2121 xmlAddChild(parent, ret);
2122 } else {
2123 xmlAddSibling(parent, ret);
2124 }
2125 }
2126
2127 /*
2128 * Insert the defaulted attributes from the DTD only if requested:
2129 */
2130 if ((nb_defaulted != 0) &&
2131 ((ctxt->loadsubset & XML_COMPLETE_ATTRS) == 0))
2132 nb_attributes -= nb_defaulted;
2133
2134 /*
2135 * Search the namespace if it wasn't already found
William M. Brackbf5cf212004-08-31 06:47:17 +00002136 * Note that, if prefix is NULL, this searches for the default Ns
Daniel Veillarde57ec792003-09-10 10:50:59 +00002137 */
2138 if ((URI != NULL) && (ret->ns == NULL)) {
William M. Brackbf5cf212004-08-31 06:47:17 +00002139 ret->ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002140 if (ret->ns == NULL) {
2141 ns = xmlNewNs(ret, NULL, prefix);
William M. Brack9f797ab2004-07-28 07:40:12 +00002142 if (ns == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002143 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
William M. Brack9f797ab2004-07-28 07:40:12 +00002144 return;
2145 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002146 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
2147 ctxt->sax->warning(ctxt->userData,
2148 "Namespace prefix %s was not found\n", prefix);
2149 }
2150 }
2151
2152 /*
2153 * process all the other attributes
2154 */
2155 if (nb_attributes > 0) {
2156 for (j = 0,i = 0;i < nb_attributes;i++,j+=5) {
2157 xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1],
2158 attributes[j+3], attributes[j+4]);
2159 }
2160 }
2161
Daniel Veillard4432df22003-09-28 18:58:27 +00002162#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002163 /*
2164 * If it's the Document root, finish the DTD validation and
2165 * check the document root element for validity
2166 */
Daniel Veillardeff45a92004-10-29 12:10:55 +00002167 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == XML_CTXT_FINISH_DTD_0)) {
Daniel Veillarde57ec792003-09-10 10:50:59 +00002168 int chk;
2169
2170 chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
2171 if (chk <= 0)
2172 ctxt->valid = 0;
2173 if (chk < 0)
2174 ctxt->wellFormed = 0;
2175 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
Daniel Veillardeff45a92004-10-29 12:10:55 +00002176 ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_1;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002177 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002178#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002179}
2180
2181/**
2182 * xmlSAX2EndElementNs:
2183 * @ctx: the user data (XML parser context)
2184 * @localname: the local name of the element
2185 * @prefix: the element namespace prefix if available
2186 * @URI: the element namespace name if available
2187 *
2188 * SAX2 callback when an element end has been detected by the parser.
2189 * It provides the namespace informations for the element.
2190 */
2191void
2192xmlSAX2EndElementNs(void *ctx,
2193 const xmlChar * localname ATTRIBUTE_UNUSED,
2194 const xmlChar * prefix ATTRIBUTE_UNUSED,
2195 const xmlChar * URI ATTRIBUTE_UNUSED)
2196{
2197 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2198 xmlParserNodeInfo node_info;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002199 xmlNodePtr cur;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002200
Daniel Veillard34099b42004-11-04 17:34:35 +00002201 if (ctx == NULL) return;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002202 cur = ctxt->node;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002203 /* Capture end position and add node */
2204 if ((ctxt->record_info) && (cur != NULL)) {
2205 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
2206 node_info.end_line = ctxt->input->line;
2207 node_info.node = cur;
2208 xmlParserAddNodeInfo(ctxt, &node_info);
2209 }
2210 ctxt->nodemem = -1;
2211
Daniel Veillard4432df22003-09-28 18:58:27 +00002212#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002213 if (ctxt->validate && ctxt->wellFormed &&
2214 ctxt->myDoc && ctxt->myDoc->intSubset)
2215 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, cur);
Daniel Veillard4432df22003-09-28 18:58:27 +00002216#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002217
2218 /*
2219 * end of parsing of this node.
2220 */
2221 nodePop(ctxt);
2222}
2223
Daniel Veillard1af9a412003-08-20 22:54:39 +00002224/**
2225 * xmlSAX2Reference:
2226 * @ctx: the user data (XML parser context)
2227 * @name: The entity name
2228 *
2229 * called when an entity xmlSAX2Reference is detected.
2230 */
2231void
2232xmlSAX2Reference(void *ctx, const xmlChar *name)
2233{
2234 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2235 xmlNodePtr ret;
2236
Daniel Veillard34099b42004-11-04 17:34:35 +00002237 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002238#ifdef DEBUG_SAX
2239 xmlGenericError(xmlGenericErrorContext,
2240 "SAX.xmlSAX2Reference(%s)\n", name);
2241#endif
2242 if (name[0] == '#')
2243 ret = xmlNewCharRef(ctxt->myDoc, name);
2244 else
2245 ret = xmlNewReference(ctxt->myDoc, name);
2246#ifdef DEBUG_SAX_TREE
2247 xmlGenericError(xmlGenericErrorContext,
2248 "add xmlSAX2Reference %s to %s \n", name, ctxt->node->name);
2249#endif
2250 xmlAddChild(ctxt->node, ret);
2251}
2252
2253/**
2254 * xmlSAX2Characters:
2255 * @ctx: the user data (XML parser context)
2256 * @ch: a xmlChar string
2257 * @len: the number of xmlChar
2258 *
2259 * receiving some chars from the parser.
2260 */
2261void
2262xmlSAX2Characters(void *ctx, const xmlChar *ch, int len)
2263{
2264 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2265 xmlNodePtr lastChild;
2266
Daniel Veillard34099b42004-11-04 17:34:35 +00002267 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002268#ifdef DEBUG_SAX
2269 xmlGenericError(xmlGenericErrorContext,
2270 "SAX.xmlSAX2Characters(%.30s, %d)\n", ch, len);
2271#endif
2272 /*
2273 * Handle the data if any. If there is no child
2274 * add it as content, otherwise if the last child is text,
2275 * concatenate it, else create a new node of type text.
2276 */
2277
2278 if (ctxt->node == NULL) {
2279#ifdef DEBUG_SAX_TREE
2280 xmlGenericError(xmlGenericErrorContext,
2281 "add chars: ctxt->node == NULL !\n");
2282#endif
2283 return;
2284 }
Daniel Veillard19895052003-09-17 13:59:32 +00002285 lastChild = ctxt->node->last;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002286#ifdef DEBUG_SAX_TREE
2287 xmlGenericError(xmlGenericErrorContext,
2288 "add chars to %s \n", ctxt->node->name);
2289#endif
2290
2291 /*
2292 * Here we needed an accelerator mechanism in case of very large
2293 * elements. Use an attribute in the structure !!!
2294 */
2295 if (lastChild == NULL) {
Daniel Veillard19895052003-09-17 13:59:32 +00002296 lastChild = xmlSAX2TextNode(ctxt, ch, len);
2297 if (lastChild != NULL) {
2298 ctxt->node->children = lastChild;
2299 ctxt->node->last = lastChild;
2300 lastChild->parent = ctxt->node;
2301 lastChild->doc = ctxt->node->doc;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002302 ctxt->nodelen = len;
2303 ctxt->nodemem = len + 1;
William M. Bracka3215c72004-07-31 16:24:01 +00002304 } else {
2305 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
2306 return;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002307 }
2308 } else {
2309 int coalesceText = (lastChild != NULL) &&
2310 (lastChild->type == XML_TEXT_NODE) &&
2311 (lastChild->name == xmlStringText);
2312 if ((coalesceText) && (ctxt->nodemem != 0)) {
2313 /*
2314 * The whole point of maintaining nodelen and nodemem,
2315 * xmlTextConcat is too costly, i.e. compute length,
2316 * reallocate a new buffer, move data, append ch. Here
2317 * We try to minimaze realloc() uses and avoid copying
2318 * and recomputing length over and over.
2319 */
Daniel Veillard2b0f8792003-10-10 19:36:36 +00002320 if ((ctxt->nodemem == ctxt->nodelen + 1) &&
2321 (xmlDictOwns(ctxt->dict, lastChild->content))) {
2322 lastChild->content = xmlStrdup(lastChild->content);
2323 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00002324 if (ctxt->nodelen + len >= ctxt->nodemem) {
2325 xmlChar *newbuf;
2326 int size;
2327
2328 size = ctxt->nodemem + len;
2329 size *= 2;
2330 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
2331 if (newbuf == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002332 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
Daniel Veillard1af9a412003-08-20 22:54:39 +00002333 return;
2334 }
2335 ctxt->nodemem = size;
2336 lastChild->content = newbuf;
2337 }
2338 memcpy(&lastChild->content[ctxt->nodelen], ch, len);
2339 ctxt->nodelen += len;
2340 lastChild->content[ctxt->nodelen] = 0;
2341 } else if (coalesceText) {
2342 if (xmlTextConcat(lastChild, ch, len)) {
William M. Brack42331a92004-07-29 07:07:16 +00002343 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
Daniel Veillard1af9a412003-08-20 22:54:39 +00002344 }
2345 if (ctxt->node->children != NULL) {
2346 ctxt->nodelen = xmlStrlen(lastChild->content);
2347 ctxt->nodemem = ctxt->nodelen + 1;
2348 }
2349 } else {
2350 /* Mixed content, first time */
Daniel Veillard19895052003-09-17 13:59:32 +00002351 lastChild = xmlSAX2TextNode(ctxt, ch, len);
2352 if (lastChild != NULL) {
Daniel Veillard1af9a412003-08-20 22:54:39 +00002353 xmlAddChild(ctxt->node, lastChild);
2354 if (ctxt->node->children != NULL) {
2355 ctxt->nodelen = len;
2356 ctxt->nodemem = len + 1;
2357 }
2358 }
2359 }
2360 }
2361}
2362
2363/**
2364 * xmlSAX2IgnorableWhitespace:
2365 * @ctx: the user data (XML parser context)
2366 * @ch: a xmlChar string
2367 * @len: the number of xmlChar
2368 *
2369 * receiving some ignorable whitespaces from the parser.
2370 * UNUSED: by default the DOM building will use xmlSAX2Characters
2371 */
2372void
2373xmlSAX2IgnorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
2374{
2375 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
2376#ifdef DEBUG_SAX
2377 xmlGenericError(xmlGenericErrorContext,
2378 "SAX.xmlSAX2IgnorableWhitespace(%.30s, %d)\n", ch, len);
2379#endif
2380}
2381
2382/**
2383 * xmlSAX2ProcessingInstruction:
2384 * @ctx: the user data (XML parser context)
2385 * @target: the target name
2386 * @data: the PI data's
2387 *
2388 * A processing instruction has been parsed.
2389 */
2390void
2391xmlSAX2ProcessingInstruction(void *ctx, const xmlChar *target,
2392 const xmlChar *data)
2393{
2394 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2395 xmlNodePtr ret;
Daniel Veillard6128c012004-11-08 17:16:15 +00002396 xmlNodePtr parent;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002397
Daniel Veillard34099b42004-11-04 17:34:35 +00002398 if (ctx == NULL) return;
Daniel Veillard6128c012004-11-08 17:16:15 +00002399 parent = ctxt->node;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002400#ifdef DEBUG_SAX
2401 xmlGenericError(xmlGenericErrorContext,
2402 "SAX.xmlSAX2ProcessingInstruction(%s, %s)\n", target, data);
2403#endif
2404
Daniel Veillard03a53c32004-10-26 16:06:51 +00002405 ret = xmlNewDocPI(ctxt->myDoc, target, data);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002406 if (ret == NULL) return;
2407 parent = ctxt->node;
2408
2409 if (ctxt->inSubset == 1) {
2410 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2411 return;
2412 } else if (ctxt->inSubset == 2) {
2413 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2414 return;
2415 }
2416 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
2417#ifdef DEBUG_SAX_TREE
2418 xmlGenericError(xmlGenericErrorContext,
2419 "Setting PI %s as root\n", target);
2420#endif
2421 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2422 return;
2423 }
2424 if (parent->type == XML_ELEMENT_NODE) {
2425#ifdef DEBUG_SAX_TREE
2426 xmlGenericError(xmlGenericErrorContext,
2427 "adding PI %s child to %s\n", target, parent->name);
2428#endif
2429 xmlAddChild(parent, ret);
2430 } else {
2431#ifdef DEBUG_SAX_TREE
2432 xmlGenericError(xmlGenericErrorContext,
2433 "adding PI %s sibling to ", target);
2434 xmlDebugDumpOneNode(stderr, parent, 0);
2435#endif
2436 xmlAddSibling(parent, ret);
2437 }
2438}
2439
2440/**
2441 * xmlSAX2Comment:
2442 * @ctx: the user data (XML parser context)
2443 * @value: the xmlSAX2Comment content
2444 *
2445 * A xmlSAX2Comment has been parsed.
2446 */
2447void
2448xmlSAX2Comment(void *ctx, const xmlChar *value)
2449{
2450 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2451 xmlNodePtr ret;
Daniel Veillard34099b42004-11-04 17:34:35 +00002452 xmlNodePtr parent;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002453
Daniel Veillard34099b42004-11-04 17:34:35 +00002454 if (ctx == NULL) return;
2455 parent = ctxt->node;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002456#ifdef DEBUG_SAX
2457 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2Comment(%s)\n", value);
2458#endif
2459 ret = xmlNewDocComment(ctxt->myDoc, value);
2460 if (ret == NULL) return;
2461
2462 if (ctxt->inSubset == 1) {
2463 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2464 return;
2465 } else if (ctxt->inSubset == 2) {
2466 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2467 return;
2468 }
2469 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
2470#ifdef DEBUG_SAX_TREE
2471 xmlGenericError(xmlGenericErrorContext,
2472 "Setting xmlSAX2Comment as root\n");
2473#endif
2474 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2475 return;
2476 }
2477 if (parent->type == XML_ELEMENT_NODE) {
2478#ifdef DEBUG_SAX_TREE
2479 xmlGenericError(xmlGenericErrorContext,
2480 "adding xmlSAX2Comment child to %s\n", parent->name);
2481#endif
2482 xmlAddChild(parent, ret);
2483 } else {
2484#ifdef DEBUG_SAX_TREE
2485 xmlGenericError(xmlGenericErrorContext,
2486 "adding xmlSAX2Comment sibling to ");
2487 xmlDebugDumpOneNode(stderr, parent, 0);
2488#endif
2489 xmlAddSibling(parent, ret);
2490 }
2491}
2492
2493/**
2494 * xmlSAX2CDataBlock:
2495 * @ctx: the user data (XML parser context)
2496 * @value: The pcdata content
2497 * @len: the block length
2498 *
2499 * called when a pcdata block has been parsed
2500 */
2501void
2502xmlSAX2CDataBlock(void *ctx, const xmlChar *value, int len)
2503{
2504 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2505 xmlNodePtr ret, lastChild;
2506
Daniel Veillard34099b42004-11-04 17:34:35 +00002507 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002508#ifdef DEBUG_SAX
2509 xmlGenericError(xmlGenericErrorContext,
2510 "SAX.pcdata(%.10s, %d)\n", value, len);
2511#endif
2512 lastChild = xmlGetLastChild(ctxt->node);
2513#ifdef DEBUG_SAX_TREE
2514 xmlGenericError(xmlGenericErrorContext,
2515 "add chars to %s \n", ctxt->node->name);
2516#endif
2517 if ((lastChild != NULL) &&
2518 (lastChild->type == XML_CDATA_SECTION_NODE)) {
2519 xmlTextConcat(lastChild, value, len);
2520 } else {
2521 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
2522 xmlAddChild(ctxt->node, ret);
2523 }
2524}
2525
Daniel Veillard62998c02003-09-15 12:56:36 +00002526static int xmlSAX2DefaultVersionValue = 2;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002527
Daniel Veillard81273902003-09-30 00:43:48 +00002528#ifdef LIBXML_SAX1_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002529/**
2530 * xmlSAXDefaultVersion:
2531 * @version: the version, 1 or 2
2532 *
2533 * Set the default version of SAX used globally by the library.
William M. Brack96d2eff2004-06-30 11:48:47 +00002534 * By default, during initialization the default is set to 2.
2535 * Note that it is generally a better coding style to use
2536 * xmlSAXVersion() to set up the version explicitly for a given
2537 * parsing context.
Daniel Veillarde57ec792003-09-10 10:50:59 +00002538 *
2539 * Returns the previous value in case of success and -1 in case of error.
2540 */
2541int
2542xmlSAXDefaultVersion(int version)
2543{
2544 int ret = xmlSAX2DefaultVersionValue;
2545
2546 if ((version != 1) && (version != 2))
2547 return(-1);
2548 xmlSAX2DefaultVersionValue = version;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002549 return(ret);
2550}
Daniel Veillard81273902003-09-30 00:43:48 +00002551#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002552
2553/**
2554 * xmlSAXVersion:
2555 * @hdlr: the SAX handler
2556 * @version: the version, 1 or 2
2557 *
2558 * Initialize the default XML SAX handler according to the version
2559 *
2560 * Returns 0 in case of success and -1 in case of error.
2561 */
2562int
2563xmlSAXVersion(xmlSAXHandler *hdlr, int version)
2564{
2565 if (hdlr == NULL) return(-1);
Daniel Veillard81273902003-09-30 00:43:48 +00002566 if (version == 2) {
Daniel Veillarde57ec792003-09-10 10:50:59 +00002567 hdlr->startElement = NULL;
2568 hdlr->endElement = NULL;
2569 hdlr->startElementNs = xmlSAX2StartElementNs;
2570 hdlr->endElementNs = xmlSAX2EndElementNs;
Daniel Veillardffbbed42003-10-10 14:46:54 +00002571 hdlr->serror = NULL;
Daniel Veillard092643b2003-09-25 14:29:29 +00002572 hdlr->initialized = XML_SAX2_MAGIC;
Daniel Veillard81273902003-09-30 00:43:48 +00002573#ifdef LIBXML_SAX1_ENABLED
2574 } else if (version == 1) {
2575 hdlr->startElement = xmlSAX2StartElement;
2576 hdlr->endElement = xmlSAX2EndElement;
2577 hdlr->initialized = 1;
2578#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002579 } else
2580 return(-1);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002581 hdlr->internalSubset = xmlSAX2InternalSubset;
2582 hdlr->externalSubset = xmlSAX2ExternalSubset;
2583 hdlr->isStandalone = xmlSAX2IsStandalone;
2584 hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
2585 hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
2586 hdlr->resolveEntity = xmlSAX2ResolveEntity;
2587 hdlr->getEntity = xmlSAX2GetEntity;
2588 hdlr->getParameterEntity = xmlSAX2GetParameterEntity;
2589 hdlr->entityDecl = xmlSAX2EntityDecl;
2590 hdlr->attributeDecl = xmlSAX2AttributeDecl;
2591 hdlr->elementDecl = xmlSAX2ElementDecl;
2592 hdlr->notationDecl = xmlSAX2NotationDecl;
2593 hdlr->unparsedEntityDecl = xmlSAX2UnparsedEntityDecl;
2594 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2595 hdlr->startDocument = xmlSAX2StartDocument;
2596 hdlr->endDocument = xmlSAX2EndDocument;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002597 hdlr->reference = xmlSAX2Reference;
2598 hdlr->characters = xmlSAX2Characters;
2599 hdlr->cdataBlock = xmlSAX2CDataBlock;
2600 hdlr->ignorableWhitespace = xmlSAX2Characters;
2601 hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
2602 hdlr->comment = xmlSAX2Comment;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002603 hdlr->warning = xmlParserWarning;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002604 hdlr->error = xmlParserError;
2605 hdlr->fatalError = xmlParserError;
2606
Daniel Veillarde57ec792003-09-10 10:50:59 +00002607 return(0);
2608}
2609
2610/**
2611 * xmlSAX2InitDefaultSAXHandler:
2612 * @hdlr: the SAX handler
2613 * @warning: flag if non-zero sets the handler warning procedure
2614 *
2615 * Initialize the default XML SAX2 handler
2616 */
2617void
2618xmlSAX2InitDefaultSAXHandler(xmlSAXHandler *hdlr, int warning)
2619{
2620 if ((hdlr == NULL) || (hdlr->initialized != 0))
2621 return;
2622
2623 xmlSAXVersion(hdlr, xmlSAX2DefaultVersionValue);
2624 if (warning == 0)
2625 hdlr->warning = NULL;
2626 else
2627 hdlr->warning = xmlParserWarning;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002628}
2629
2630/**
2631 * xmlDefaultSAXHandlerInit:
2632 *
2633 * Initialize the default SAX2 handler
2634 */
2635void
2636xmlDefaultSAXHandlerInit(void)
2637{
Daniel Veillard81273902003-09-30 00:43:48 +00002638#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard092643b2003-09-25 14:29:29 +00002639 xmlSAXVersion((xmlSAXHandlerPtr) &xmlDefaultSAXHandler, 1);
Daniel Veillard81273902003-09-30 00:43:48 +00002640#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00002641}
2642
2643#ifdef LIBXML_HTML_ENABLED
2644
2645/**
2646 * xmlSAX2InitHtmlDefaultSAXHandler:
2647 * @hdlr: the SAX handler
2648 *
2649 * Initialize the default HTML SAX2 handler
2650 */
2651void
2652xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr)
2653{
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002654 if ((hdlr == NULL) || (hdlr->initialized != 0))
Daniel Veillard1af9a412003-08-20 22:54:39 +00002655 return;
2656
2657 hdlr->internalSubset = xmlSAX2InternalSubset;
2658 hdlr->externalSubset = NULL;
2659 hdlr->isStandalone = NULL;
2660 hdlr->hasInternalSubset = NULL;
2661 hdlr->hasExternalSubset = NULL;
2662 hdlr->resolveEntity = NULL;
2663 hdlr->getEntity = xmlSAX2GetEntity;
2664 hdlr->getParameterEntity = NULL;
2665 hdlr->entityDecl = NULL;
2666 hdlr->attributeDecl = NULL;
2667 hdlr->elementDecl = NULL;
2668 hdlr->notationDecl = NULL;
2669 hdlr->unparsedEntityDecl = NULL;
2670 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2671 hdlr->startDocument = xmlSAX2StartDocument;
2672 hdlr->endDocument = xmlSAX2EndDocument;
2673 hdlr->startElement = xmlSAX2StartElement;
2674 hdlr->endElement = xmlSAX2EndElement;
2675 hdlr->reference = NULL;
2676 hdlr->characters = xmlSAX2Characters;
2677 hdlr->cdataBlock = xmlSAX2CDataBlock;
2678 hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
Daniel Veillardfc484dd2004-10-22 14:34:23 +00002679 hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002680 hdlr->comment = xmlSAX2Comment;
2681 hdlr->warning = xmlParserWarning;
2682 hdlr->error = xmlParserError;
2683 hdlr->fatalError = xmlParserError;
2684
Daniel Veillard092643b2003-09-25 14:29:29 +00002685 hdlr->initialized = 1;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002686}
2687
2688/**
2689 * htmlDefaultSAXHandlerInit:
2690 *
2691 * Initialize the default SAX handler
2692 */
2693void
2694htmlDefaultSAXHandlerInit(void)
2695{
Daniel Veillard092643b2003-09-25 14:29:29 +00002696 xmlSAX2InitHtmlDefaultSAXHandler((xmlSAXHandlerPtr) &htmlDefaultSAXHandler);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002697}
2698
2699#endif /* LIBXML_HTML_ENABLED */
2700
2701#ifdef LIBXML_DOCB_ENABLED
2702
2703/**
2704 * xmlSAX2InitDocbDefaultSAXHandler:
2705 * @hdlr: the SAX handler
2706 *
2707 * Initialize the default DocBook SAX2 handler
2708 */
2709void
2710xmlSAX2InitDocbDefaultSAXHandler(xmlSAXHandler *hdlr)
2711{
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002712 if ((hdlr == NULL) || (hdlr->initialized != 0))
Daniel Veillard1af9a412003-08-20 22:54:39 +00002713 return;
2714
2715 hdlr->internalSubset = xmlSAX2InternalSubset;
2716 hdlr->externalSubset = NULL;
2717 hdlr->isStandalone = xmlSAX2IsStandalone;
2718 hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
2719 hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
2720 hdlr->resolveEntity = xmlSAX2ResolveEntity;
2721 hdlr->getEntity = xmlSAX2GetEntity;
2722 hdlr->getParameterEntity = NULL;
2723 hdlr->entityDecl = xmlSAX2EntityDecl;
2724 hdlr->attributeDecl = NULL;
2725 hdlr->elementDecl = NULL;
2726 hdlr->notationDecl = NULL;
2727 hdlr->unparsedEntityDecl = NULL;
2728 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2729 hdlr->startDocument = xmlSAX2StartDocument;
2730 hdlr->endDocument = xmlSAX2EndDocument;
2731 hdlr->startElement = xmlSAX2StartElement;
2732 hdlr->endElement = xmlSAX2EndElement;
2733 hdlr->reference = xmlSAX2Reference;
2734 hdlr->characters = xmlSAX2Characters;
2735 hdlr->cdataBlock = NULL;
2736 hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
2737 hdlr->processingInstruction = NULL;
2738 hdlr->comment = xmlSAX2Comment;
2739 hdlr->warning = xmlParserWarning;
2740 hdlr->error = xmlParserError;
2741 hdlr->fatalError = xmlParserError;
2742
Daniel Veillardffbbed42003-10-10 14:46:54 +00002743 hdlr->initialized = 1;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002744}
2745
2746/**
2747 * docbDefaultSAXHandlerInit:
2748 *
2749 * Initialize the default SAX handler
2750 */
2751void
2752docbDefaultSAXHandlerInit(void)
2753{
Daniel Veillard092643b2003-09-25 14:29:29 +00002754 xmlSAX2InitDocbDefaultSAXHandler((xmlSAXHandlerPtr) &docbDefaultSAXHandler);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002755}
2756
2757#endif /* LIBXML_DOCB_ENABLED */
Daniel Veillard5d4644e2005-04-01 13:11:58 +00002758#define bottom_SAX2
2759#include "elfgcchack.h"