blob: 16e361f9137f891cbd974505597867a4ddedb7a8 [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 Veillard87b30462005-07-05 14:04:36 +000098 * xmlFatalErrMsg:
99 * @ctxt: an XML parser context
100 * @error: the error number
101 * @msg: the error message
102 * @str1: an error string
103 * @str2: an error string
104 *
105 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
106 */
107static void
108xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
109 const char *msg, const xmlChar *str1, const xmlChar *str2)
110{
111 if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
112 (ctxt->instate == XML_PARSER_EOF))
113 return;
114 if (ctxt != NULL)
115 ctxt->errNo = error;
116 __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
117 XML_ERR_FATAL, NULL, 0,
118 (const char *) str1, (const char *) str2,
119 NULL, 0, 0, msg, str1, str2);
120 if (ctxt != NULL) {
121 ctxt->wellFormed = 0;
122 ctxt->valid = 0;
123 if (ctxt->recovery == 0)
124 ctxt->disableSAX = 1;
125 }
126}
127
128/**
129 * xmlWarnMsg:
130 * @ctxt: an XML parser context
131 * @error: the error number
132 * @msg: the error message
133 * @str1: an error string
134 * @str2: an error string
135 *
136 * Handle a parser warning
137 */
138static void
139xmlWarnMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
140 const char *msg, const xmlChar *str1)
141{
142 if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
143 (ctxt->instate == XML_PARSER_EOF))
144 return;
145 if (ctxt != NULL)
146 ctxt->errNo = error;
147 __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
148 XML_ERR_WARNING, NULL, 0,
149 (const char *) str1, NULL,
150 NULL, 0, 0, msg, str1);
151}
152
153/**
154 * xmlNsErrMsg:
155 * @ctxt: an XML parser context
156 * @error: the error number
157 * @msg: the error message
158 * @str1: an error string
159 * @str2: an error string
160 *
161 * Handle a namespace error
162 */
163static void
164xmlNsErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
165 const char *msg, const xmlChar *str1, const xmlChar *str2)
166{
167 if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
168 (ctxt->instate == XML_PARSER_EOF))
169 return;
170 if (ctxt != NULL)
171 ctxt->errNo = error;
172 __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
173 XML_ERR_ERROR, NULL, 0,
174 (const char *) str1, (const char *) str2,
175 NULL, 0, 0, msg, str1, str2);
176}
177
178/**
179 * xmlNsWarnMsg:
180 * @ctxt: an XML parser context
181 * @error: the error number
182 * @msg: the error message
183 * @str1: an error string
184 *
185 * Handle a namespace warning
186 */
187static void
188xmlNsWarnMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
189 const char *msg, const xmlChar *str1, const xmlChar *str2)
190{
191 if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
192 (ctxt->instate == XML_PARSER_EOF))
193 return;
194 if (ctxt != NULL)
195 ctxt->errNo = error;
196 __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
197 XML_ERR_WARNING, NULL, 0,
198 (const char *) str1, (const char *) str2,
199 NULL, 0, 0, msg, str1, str2);
200}
201
202/**
Daniel Veillard1af9a412003-08-20 22:54:39 +0000203 * xmlSAX2GetPublicId:
204 * @ctx: the user data (XML parser context)
205 *
206 * Provides the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
207 *
208 * Returns a xmlChar *
209 */
210const xmlChar *
211xmlSAX2GetPublicId(void *ctx ATTRIBUTE_UNUSED)
212{
213 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
214 return(NULL);
215}
216
217/**
218 * xmlSAX2GetSystemId:
219 * @ctx: the user data (XML parser context)
220 *
221 * Provides the system ID, basically URL or filename e.g.
222 * http://www.sgmlsource.com/dtds/memo.dtd
223 *
224 * Returns a xmlChar *
225 */
226const xmlChar *
227xmlSAX2GetSystemId(void *ctx)
228{
229 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard34099b42004-11-04 17:34:35 +0000230 if ((ctx == NULL) || (ctxt->input == NULL)) return(0);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000231 return((const xmlChar *) ctxt->input->filename);
232}
233
234/**
235 * xmlSAX2GetLineNumber:
236 * @ctx: the user data (XML parser context)
237 *
238 * Provide the line number of the current parsing point.
239 *
240 * Returns an int
241 */
242int
243xmlSAX2GetLineNumber(void *ctx)
244{
245 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard34099b42004-11-04 17:34:35 +0000246 if ((ctx == NULL) || (ctxt->input == NULL)) return(0);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000247 return(ctxt->input->line);
248}
249
250/**
251 * xmlSAX2GetColumnNumber:
252 * @ctx: the user data (XML parser context)
253 *
254 * Provide the column number of the current parsing point.
255 *
256 * Returns an int
257 */
258int
259xmlSAX2GetColumnNumber(void *ctx)
260{
261 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard34099b42004-11-04 17:34:35 +0000262 if ((ctx == NULL) || (ctxt->input == NULL)) return(0);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000263 return(ctxt->input->col);
264}
265
266/**
267 * xmlSAX2IsStandalone:
268 * @ctx: the user data (XML parser context)
269 *
270 * Is this document tagged standalone ?
271 *
272 * Returns 1 if true
273 */
274int
275xmlSAX2IsStandalone(void *ctx)
276{
277 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard34099b42004-11-04 17:34:35 +0000278 if ((ctx == NULL) || (ctxt->myDoc == NULL)) return(0);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000279 return(ctxt->myDoc->standalone == 1);
280}
281
282/**
283 * xmlSAX2HasInternalSubset:
284 * @ctx: the user data (XML parser context)
285 *
286 * Does this document has an internal subset
287 *
288 * Returns 1 if true
289 */
290int
291xmlSAX2HasInternalSubset(void *ctx)
292{
293 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +0000294 if ((ctxt == NULL) || (ctxt->myDoc == NULL)) return(0);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000295 return(ctxt->myDoc->intSubset != NULL);
296}
297
298/**
299 * xmlSAX2HasExternalSubset:
300 * @ctx: the user data (XML parser context)
301 *
302 * Does this document has an external subset
303 *
304 * Returns 1 if true
305 */
306int
307xmlSAX2HasExternalSubset(void *ctx)
308{
309 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +0000310 if ((ctxt == NULL) || (ctxt->myDoc == NULL)) return(0);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000311 return(ctxt->myDoc->extSubset != NULL);
312}
313
314/**
315 * xmlSAX2InternalSubset:
316 * @ctx: the user data (XML parser context)
317 * @name: the root element name
318 * @ExternalID: the external ID
319 * @SystemID: the SYSTEM ID (e.g. filename or URL)
320 *
321 * Callback on internal subset declaration.
322 */
323void
324xmlSAX2InternalSubset(void *ctx, const xmlChar *name,
325 const xmlChar *ExternalID, const xmlChar *SystemID)
326{
327 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
328 xmlDtdPtr dtd;
Daniel Veillard34099b42004-11-04 17:34:35 +0000329 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000330#ifdef DEBUG_SAX
331 xmlGenericError(xmlGenericErrorContext,
332 "SAX.xmlSAX2InternalSubset(%s, %s, %s)\n",
333 name, ExternalID, SystemID);
334#endif
335
336 if (ctxt->myDoc == NULL)
337 return;
338 dtd = xmlGetIntSubset(ctxt->myDoc);
339 if (dtd != NULL) {
340 if (ctxt->html)
341 return;
342 xmlUnlinkNode((xmlNodePtr) dtd);
343 xmlFreeDtd(dtd);
344 ctxt->myDoc->intSubset = NULL;
345 }
346 ctxt->myDoc->intSubset =
347 xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
William M. Brack42331a92004-07-29 07:07:16 +0000348 if (ctxt->myDoc->intSubset == NULL)
349 xmlSAX2ErrMemory(ctxt, "xmlSAX2InternalSubset");
Daniel Veillard1af9a412003-08-20 22:54:39 +0000350}
351
352/**
353 * xmlSAX2ExternalSubset:
354 * @ctx: the user data (XML parser context)
355 * @name: the root element name
356 * @ExternalID: the external ID
357 * @SystemID: the SYSTEM ID (e.g. filename or URL)
358 *
359 * Callback on external subset declaration.
360 */
361void
362xmlSAX2ExternalSubset(void *ctx, const xmlChar *name,
363 const xmlChar *ExternalID, const xmlChar *SystemID)
364{
365 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard34099b42004-11-04 17:34:35 +0000366 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000367#ifdef DEBUG_SAX
368 xmlGenericError(xmlGenericErrorContext,
369 "SAX.xmlSAX2ExternalSubset(%s, %s, %s)\n",
370 name, ExternalID, SystemID);
371#endif
372 if (((ExternalID != NULL) || (SystemID != NULL)) &&
373 (((ctxt->validate) || (ctxt->loadsubset != 0)) &&
374 (ctxt->wellFormed && ctxt->myDoc))) {
375 /*
376 * Try to fetch and parse the external subset.
377 */
378 xmlParserInputPtr oldinput;
379 int oldinputNr;
380 int oldinputMax;
381 xmlParserInputPtr *oldinputTab;
382 xmlParserInputPtr input = NULL;
383 xmlCharEncoding enc;
384 int oldcharset;
385
386 /*
387 * Ask the Entity resolver to load the damn thing
388 */
389 if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
390 input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
391 SystemID);
392 if (input == NULL) {
393 return;
394 }
395
396 xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
397
398 /*
399 * make sure we won't destroy the main document context
400 */
401 oldinput = ctxt->input;
402 oldinputNr = ctxt->inputNr;
403 oldinputMax = ctxt->inputMax;
404 oldinputTab = ctxt->inputTab;
405 oldcharset = ctxt->charset;
406
407 ctxt->inputTab = (xmlParserInputPtr *)
408 xmlMalloc(5 * sizeof(xmlParserInputPtr));
409 if (ctxt->inputTab == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +0000410 xmlSAX2ErrMemory(ctxt, "xmlSAX2ExternalSubset");
Daniel Veillard1af9a412003-08-20 22:54:39 +0000411 ctxt->input = oldinput;
412 ctxt->inputNr = oldinputNr;
413 ctxt->inputMax = oldinputMax;
414 ctxt->inputTab = oldinputTab;
415 ctxt->charset = oldcharset;
416 return;
417 }
418 ctxt->inputNr = 0;
419 ctxt->inputMax = 5;
420 ctxt->input = NULL;
421 xmlPushInput(ctxt, input);
422
423 /*
424 * On the fly encoding conversion if needed
425 */
426 if (ctxt->input->length >= 4) {
427 enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
428 xmlSwitchEncoding(ctxt, enc);
429 }
430
431 if (input->filename == NULL)
432 input->filename = (char *) xmlCanonicPath(SystemID);
433 input->line = 1;
434 input->col = 1;
435 input->base = ctxt->input->cur;
436 input->cur = ctxt->input->cur;
437 input->free = NULL;
438
439 /*
440 * let's parse that entity knowing it's an external subset.
441 */
442 xmlParseExternalSubset(ctxt, ExternalID, SystemID);
443
444 /*
445 * Free up the external entities
446 */
447
448 while (ctxt->inputNr > 1)
449 xmlPopInput(ctxt);
450 xmlFreeInputStream(ctxt->input);
451 xmlFree(ctxt->inputTab);
452
453 /*
454 * Restore the parsing context of the main entity
455 */
456 ctxt->input = oldinput;
457 ctxt->inputNr = oldinputNr;
458 ctxt->inputMax = oldinputMax;
459 ctxt->inputTab = oldinputTab;
460 ctxt->charset = oldcharset;
461 /* ctxt->wellFormed = oldwellFormed; */
462 }
463}
464
465/**
466 * xmlSAX2ResolveEntity:
467 * @ctx: the user data (XML parser context)
468 * @publicId: The public ID of the entity
469 * @systemId: The system ID of the entity
470 *
471 * The entity loader, to control the loading of external entities,
472 * the application can either:
473 * - override this xmlSAX2ResolveEntity() callback in the SAX block
474 * - or better use the xmlSetExternalEntityLoader() function to
475 * set up it's own entity resolution routine
476 *
477 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
478 */
479xmlParserInputPtr
480xmlSAX2ResolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
481{
482 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
483 xmlParserInputPtr ret;
484 xmlChar *URI;
485 const char *base = NULL;
486
Daniel Veillard34099b42004-11-04 17:34:35 +0000487 if (ctx == NULL) return(NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000488 if (ctxt->input != NULL)
489 base = ctxt->input->filename;
490 if (base == NULL)
491 base = ctxt->directory;
492
493 URI = xmlBuildURI(systemId, (const xmlChar *) base);
494
495#ifdef DEBUG_SAX
496 xmlGenericError(xmlGenericErrorContext,
497 "SAX.xmlSAX2ResolveEntity(%s, %s)\n", publicId, systemId);
498#endif
499
500 ret = xmlLoadExternalEntity((const char *) URI,
501 (const char *) publicId, ctxt);
502 if (URI != NULL)
503 xmlFree(URI);
504 return(ret);
505}
506
507/**
508 * xmlSAX2GetEntity:
509 * @ctx: the user data (XML parser context)
510 * @name: The entity name
511 *
512 * Get an entity by name
513 *
514 * Returns the xmlEntityPtr if found.
515 */
516xmlEntityPtr
517xmlSAX2GetEntity(void *ctx, const xmlChar *name)
518{
519 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
520 xmlEntityPtr ret = NULL;
521
Daniel Veillard34099b42004-11-04 17:34:35 +0000522 if (ctx == NULL) return(NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000523#ifdef DEBUG_SAX
524 xmlGenericError(xmlGenericErrorContext,
525 "SAX.xmlSAX2GetEntity(%s)\n", name);
526#endif
527
528 if (ctxt->inSubset == 0) {
529 ret = xmlGetPredefinedEntity(name);
530 if (ret != NULL)
531 return(ret);
532 }
533 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->standalone == 1)) {
534 if (ctxt->inSubset == 2) {
535 ctxt->myDoc->standalone = 0;
536 ret = xmlGetDocEntity(ctxt->myDoc, name);
537 ctxt->myDoc->standalone = 1;
538 } else {
539 ret = xmlGetDocEntity(ctxt->myDoc, name);
540 if (ret == NULL) {
541 ctxt->myDoc->standalone = 0;
542 ret = xmlGetDocEntity(ctxt->myDoc, name);
543 if (ret != NULL) {
Daniel Veillard87b30462005-07-05 14:04:36 +0000544 xmlFatalErrMsg(ctxt, XML_ERR_NOT_STANDALONE,
545 "Entity(%s) document marked standalone but requires external subset\n",
546 name, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000547 }
548 ctxt->myDoc->standalone = 1;
549 }
550 }
551 } else {
552 ret = xmlGetDocEntity(ctxt->myDoc, name);
553 }
554 if ((ret != NULL) &&
555 ((ctxt->validate) || (ctxt->replaceEntities)) &&
556 (ret->children == NULL) &&
557 (ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
558 int val;
559
560 /*
561 * for validation purposes we really need to fetch and
562 * parse the external entity
563 */
564 xmlNodePtr children;
565
566 val = xmlParseCtxtExternalEntity(ctxt, ret->URI,
567 ret->ExternalID, &children);
568 if (val == 0) {
569 xmlAddChildList((xmlNodePtr) ret, children);
570 } else {
Daniel Veillard87b30462005-07-05 14:04:36 +0000571 xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_PROCESSING,
572 "Failure to process entity %s\n", name, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000573 ctxt->validate = 0;
574 return(NULL);
575 }
576 ret->owner = 1;
577 }
578 return(ret);
579}
580
581/**
582 * xmlSAX2GetParameterEntity:
583 * @ctx: the user data (XML parser context)
584 * @name: The entity name
585 *
586 * Get a parameter entity by name
587 *
588 * Returns the xmlEntityPtr if found.
589 */
590xmlEntityPtr
591xmlSAX2GetParameterEntity(void *ctx, const xmlChar *name)
592{
593 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
594 xmlEntityPtr ret;
595
Daniel Veillard34099b42004-11-04 17:34:35 +0000596 if (ctx == NULL) return(NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000597#ifdef DEBUG_SAX
598 xmlGenericError(xmlGenericErrorContext,
599 "SAX.xmlSAX2GetParameterEntity(%s)\n", name);
600#endif
601
602 ret = xmlGetParameterEntity(ctxt->myDoc, name);
603 return(ret);
604}
605
606
607/**
608 * xmlSAX2EntityDecl:
609 * @ctx: the user data (XML parser context)
610 * @name: the entity name
611 * @type: the entity type
612 * @publicId: The public ID of the entity
613 * @systemId: The system ID of the entity
614 * @content: the entity value (without processing).
615 *
616 * An entity definition has been parsed
617 */
618void
619xmlSAX2EntityDecl(void *ctx, const xmlChar *name, int type,
620 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
621{
622 xmlEntityPtr ent;
623 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
624
Daniel Veillard34099b42004-11-04 17:34:35 +0000625 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000626#ifdef DEBUG_SAX
627 xmlGenericError(xmlGenericErrorContext,
628 "SAX.xmlSAX2EntityDecl(%s, %d, %s, %s, %s)\n",
629 name, type, publicId, systemId, content);
630#endif
631 if (ctxt->inSubset == 1) {
632 ent = xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
633 systemId, content);
Daniel Veillard87b30462005-07-05 14:04:36 +0000634 if ((ent == NULL) && (ctxt->pedantic))
635 xmlWarnMsg(ctxt, XML_WAR_ENTITY_REDEFINED,
636 "Entity(%s) already defined in the internal subset\n",
637 name);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000638 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
639 xmlChar *URI;
640 const char *base = NULL;
641
642 if (ctxt->input != NULL)
643 base = ctxt->input->filename;
644 if (base == NULL)
645 base = ctxt->directory;
646
647 URI = xmlBuildURI(systemId, (const xmlChar *) base);
648 ent->URI = URI;
649 }
650 } else if (ctxt->inSubset == 2) {
651 ent = xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
652 systemId, content);
653 if ((ent == NULL) && (ctxt->pedantic) &&
654 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000655 ctxt->sax->warning(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000656 "Entity(%s) already defined in the external subset\n", name);
657 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
658 xmlChar *URI;
659 const char *base = NULL;
660
661 if (ctxt->input != NULL)
662 base = ctxt->input->filename;
663 if (base == NULL)
664 base = ctxt->directory;
665
666 URI = xmlBuildURI(systemId, (const xmlChar *) base);
667 ent->URI = URI;
668 }
669 } else {
Daniel Veillard87b30462005-07-05 14:04:36 +0000670 xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_PROCESSING,
671 "SAX.xmlSAX2EntityDecl(%s) called while not in subset\n",
672 name, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000673 }
674}
675
676/**
677 * xmlSAX2AttributeDecl:
678 * @ctx: the user data (XML parser context)
679 * @elem: the name of the element
680 * @fullname: the attribute name
681 * @type: the attribute type
682 * @def: the type of default value
683 * @defaultValue: the attribute default value
684 * @tree: the tree of enumerated value set
685 *
686 * An attribute definition has been parsed
687 */
688void
689xmlSAX2AttributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
690 int type, int def, const xmlChar *defaultValue,
691 xmlEnumerationPtr tree)
692{
693 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
694 xmlAttributePtr attr;
695 xmlChar *name = NULL, *prefix = NULL;
696
Daniel Veillard34099b42004-11-04 17:34:35 +0000697 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000698#ifdef DEBUG_SAX
699 xmlGenericError(xmlGenericErrorContext,
700 "SAX.xmlSAX2AttributeDecl(%s, %s, %d, %d, %s, ...)\n",
701 elem, fullname, type, def, defaultValue);
702#endif
Daniel Veillard68cb4b22004-04-18 20:55:39 +0000703 if ((xmlStrEqual(fullname, BAD_CAST "xml:id")) &&
704 (type != XML_ATTRIBUTE_ID)) {
705 /*
706 * Raise the error but keep the validity flag
707 */
708 int tmp = ctxt->valid;
709 xmlErrValid(ctxt, XML_DTD_XMLID_TYPE,
710 "xml:id : attribute type should be ID\n", NULL, NULL);
711 ctxt->valid = tmp;
712 }
Daniel Veillarde57ec792003-09-10 10:50:59 +0000713 /* TODO: optimize name/prefix allocation */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000714 name = xmlSplitQName(ctxt, fullname, &prefix);
715 ctxt->vctxt.valid = 1;
716 if (ctxt->inSubset == 1)
717 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
718 name, prefix, (xmlAttributeType) type,
719 (xmlAttributeDefault) def, defaultValue, tree);
720 else if (ctxt->inSubset == 2)
721 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
722 name, prefix, (xmlAttributeType) type,
723 (xmlAttributeDefault) def, defaultValue, tree);
724 else {
Daniel Veillard87b30462005-07-05 14:04:36 +0000725 xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
726 "SAX.xmlSAX2AttributeDecl(%s) called while not in subset\n",
727 name, NULL);
Daniel Veillarde57ec792003-09-10 10:50:59 +0000728 xmlFreeEnumeration(tree);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000729 return;
730 }
Daniel Veillard4432df22003-09-28 18:58:27 +0000731#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000732 if (ctxt->vctxt.valid == 0)
733 ctxt->valid = 0;
734 if ((attr != NULL) && (ctxt->validate) && (ctxt->wellFormed) &&
735 (ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset != NULL))
736 ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
737 attr);
Daniel Veillard4432df22003-09-28 18:58:27 +0000738#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000739 if (prefix != NULL)
740 xmlFree(prefix);
741 if (name != NULL)
742 xmlFree(name);
743}
744
745/**
746 * xmlSAX2ElementDecl:
747 * @ctx: the user data (XML parser context)
748 * @name: the element name
749 * @type: the element type
750 * @content: the element value tree
751 *
752 * An element definition has been parsed
753 */
754void
755xmlSAX2ElementDecl(void *ctx, const xmlChar * name, int type,
756 xmlElementContentPtr content)
757{
758 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
759 xmlElementPtr elem = NULL;
760
Daniel Veillard34099b42004-11-04 17:34:35 +0000761 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000762#ifdef DEBUG_SAX
763 xmlGenericError(xmlGenericErrorContext,
764 "SAX.xmlSAX2ElementDecl(%s, %d, ...)\n", name, type);
765#endif
766
767 if (ctxt->inSubset == 1)
768 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
769 name, (xmlElementTypeVal) type, content);
770 else if (ctxt->inSubset == 2)
771 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
772 name, (xmlElementTypeVal) type, content);
773 else {
Daniel Veillard87b30462005-07-05 14:04:36 +0000774 xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
775 "SAX.xmlSAX2ElementDecl(%s) called while not in subset\n",
776 name, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000777 return;
778 }
Daniel Veillard4432df22003-09-28 18:58:27 +0000779#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000780 if (elem == NULL)
781 ctxt->valid = 0;
782 if (ctxt->validate && ctxt->wellFormed &&
783 ctxt->myDoc && ctxt->myDoc->intSubset)
784 ctxt->valid &=
785 xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
Daniel Veillard4432df22003-09-28 18:58:27 +0000786#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000787}
788
789/**
790 * xmlSAX2NotationDecl:
791 * @ctx: the user data (XML parser context)
792 * @name: The name of the notation
793 * @publicId: The public ID of the entity
794 * @systemId: The system ID of the entity
795 *
796 * What to do when a notation declaration has been parsed.
797 */
798void
799xmlSAX2NotationDecl(void *ctx, const xmlChar *name,
800 const xmlChar *publicId, const xmlChar *systemId)
801{
802 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
803 xmlNotationPtr nota = NULL;
804
Daniel Veillard34099b42004-11-04 17:34:35 +0000805 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000806#ifdef DEBUG_SAX
807 xmlGenericError(xmlGenericErrorContext,
808 "SAX.xmlSAX2NotationDecl(%s, %s, %s)\n", name, publicId, systemId);
809#endif
810
811 if ((publicId == NULL) && (systemId == NULL)) {
Daniel Veillard87b30462005-07-05 14:04:36 +0000812 xmlFatalErrMsg(ctxt, XML_ERR_NOTATION_PROCESSING,
813 "SAX.xmlSAX2NotationDecl(%s) externalID or PublicID missing\n",
814 name, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000815 return;
816 } else if (ctxt->inSubset == 1)
817 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
818 publicId, systemId);
819 else if (ctxt->inSubset == 2)
820 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, name,
821 publicId, systemId);
822 else {
Daniel Veillard87b30462005-07-05 14:04:36 +0000823 xmlFatalErrMsg(ctxt, XML_ERR_NOTATION_PROCESSING,
824 "SAX.xmlSAX2NotationDecl(%s) called while not in subset\n",
825 name, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000826 return;
827 }
Daniel Veillard4432df22003-09-28 18:58:27 +0000828#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000829 if (nota == NULL) ctxt->valid = 0;
830 if (ctxt->validate && ctxt->wellFormed &&
831 ctxt->myDoc && ctxt->myDoc->intSubset)
832 ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
833 nota);
Daniel Veillard4432df22003-09-28 18:58:27 +0000834#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000835}
836
837/**
838 * xmlSAX2UnparsedEntityDecl:
839 * @ctx: the user data (XML parser context)
840 * @name: The name of the entity
841 * @publicId: The public ID of the entity
842 * @systemId: The system ID of the entity
843 * @notationName: the name of the notation
844 *
845 * What to do when an unparsed entity declaration is parsed
846 */
847void
848xmlSAX2UnparsedEntityDecl(void *ctx, const xmlChar *name,
849 const xmlChar *publicId, const xmlChar *systemId,
850 const xmlChar *notationName)
851{
852 xmlEntityPtr ent;
853 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard34099b42004-11-04 17:34:35 +0000854 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000855#ifdef DEBUG_SAX
856 xmlGenericError(xmlGenericErrorContext,
857 "SAX.xmlSAX2UnparsedEntityDecl(%s, %s, %s, %s)\n",
858 name, publicId, systemId, notationName);
859#endif
860 if (ctxt->inSubset == 1) {
861 ent = xmlAddDocEntity(ctxt->myDoc, name,
862 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
863 publicId, systemId, notationName);
864 if ((ent == NULL) && (ctxt->pedantic) &&
865 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000866 ctxt->sax->warning(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000867 "Entity(%s) already defined in the internal subset\n", name);
868 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
869 xmlChar *URI;
870 const char *base = NULL;
871
872 if (ctxt->input != NULL)
873 base = ctxt->input->filename;
874 if (base == NULL)
875 base = ctxt->directory;
876
877 URI = xmlBuildURI(systemId, (const xmlChar *) base);
878 ent->URI = URI;
879 }
880 } else if (ctxt->inSubset == 2) {
881 ent = xmlAddDtdEntity(ctxt->myDoc, name,
882 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
883 publicId, systemId, notationName);
884 if ((ent == NULL) && (ctxt->pedantic) &&
885 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000886 ctxt->sax->warning(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000887 "Entity(%s) already defined in the external subset\n", name);
888 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
889 xmlChar *URI;
890 const char *base = NULL;
891
892 if (ctxt->input != NULL)
893 base = ctxt->input->filename;
894 if (base == NULL)
895 base = ctxt->directory;
896
897 URI = xmlBuildURI(systemId, (const xmlChar *) base);
898 ent->URI = URI;
899 }
900 } else {
Daniel Veillard87b30462005-07-05 14:04:36 +0000901 xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
902 "SAX.xmlSAX2UnparsedEntityDecl(%s) called while not in subset\n",
903 name, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000904 }
905}
906
907/**
908 * xmlSAX2SetDocumentLocator:
909 * @ctx: the user data (XML parser context)
910 * @loc: A SAX Locator
911 *
912 * Receive the document locator at startup, actually xmlDefaultSAXLocator
913 * Everything is available on the context, so this is useless in our case.
914 */
915void
916xmlSAX2SetDocumentLocator(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
917{
918 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
919#ifdef DEBUG_SAX
920 xmlGenericError(xmlGenericErrorContext,
921 "SAX.xmlSAX2SetDocumentLocator()\n");
922#endif
923}
924
925/**
926 * xmlSAX2StartDocument:
927 * @ctx: the user data (XML parser context)
928 *
929 * called when the document start being processed.
930 */
931void
932xmlSAX2StartDocument(void *ctx)
933{
934 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
935 xmlDocPtr doc;
936
Daniel Veillard34099b42004-11-04 17:34:35 +0000937 if (ctx == NULL) return;
938
Daniel Veillard1af9a412003-08-20 22:54:39 +0000939#ifdef DEBUG_SAX
940 xmlGenericError(xmlGenericErrorContext,
941 "SAX.xmlSAX2StartDocument()\n");
942#endif
943 if (ctxt->html) {
944#ifdef LIBXML_HTML_ENABLED
945 if (ctxt->myDoc == NULL)
946 ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
947 if (ctxt->myDoc == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +0000948 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
Daniel Veillard1af9a412003-08-20 22:54:39 +0000949 return;
950 }
951#else
952 xmlGenericError(xmlGenericErrorContext,
953 "libxml2 built without HTML support\n");
954 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
955 ctxt->instate = XML_PARSER_EOF;
956 ctxt->disableSAX = 1;
957 return;
958#endif
959 } else {
960 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
961 if (doc != NULL) {
962 if (ctxt->encoding != NULL)
963 doc->encoding = xmlStrdup(ctxt->encoding);
964 else
965 doc->encoding = NULL;
966 doc->standalone = ctxt->standalone;
967 } else {
William M. Brack42331a92004-07-29 07:07:16 +0000968 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
Daniel Veillard1af9a412003-08-20 22:54:39 +0000969 return;
970 }
Daniel Veillard500a1de2004-03-22 15:22:58 +0000971 if ((ctxt->dictNames) && (doc != NULL)) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +0000972 doc->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000973 xmlDictReference(doc->dict);
974 }
Daniel Veillard1af9a412003-08-20 22:54:39 +0000975 }
976 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
977 (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
978 ctxt->myDoc->URL = xmlCanonicPath((const xmlChar *) ctxt->input->filename);
979 if (ctxt->myDoc->URL == NULL)
William M. Bracka3215c72004-07-31 16:24:01 +0000980 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
Daniel Veillard1af9a412003-08-20 22:54:39 +0000981 }
982}
983
984/**
985 * xmlSAX2EndDocument:
986 * @ctx: the user data (XML parser context)
987 *
988 * called when the document end has been detected.
989 */
990void
991xmlSAX2EndDocument(void *ctx)
992{
993 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
994#ifdef DEBUG_SAX
995 xmlGenericError(xmlGenericErrorContext,
996 "SAX.xmlSAX2EndDocument()\n");
997#endif
Daniel Veillard34099b42004-11-04 17:34:35 +0000998 if (ctx == NULL) return;
Daniel Veillard4432df22003-09-28 18:58:27 +0000999#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001000 if (ctxt->validate && ctxt->wellFormed &&
1001 ctxt->myDoc && ctxt->myDoc->intSubset)
1002 ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
Daniel Veillard4432df22003-09-28 18:58:27 +00001003#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001004
1005 /*
1006 * Grab the encoding if it was added on-the-fly
1007 */
1008 if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
1009 (ctxt->myDoc->encoding == NULL)) {
1010 ctxt->myDoc->encoding = ctxt->encoding;
1011 ctxt->encoding = NULL;
1012 }
Daniel Veillard36e5cd52004-11-02 14:52:23 +00001013 if ((ctxt->inputTab != NULL) &&
1014 (ctxt->inputNr > 0) && (ctxt->inputTab[0] != NULL) &&
1015 (ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
Daniel Veillard1af9a412003-08-20 22:54:39 +00001016 (ctxt->myDoc->encoding == NULL)) {
1017 ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
1018 }
1019 if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
1020 (ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
1021 ctxt->myDoc->charset = ctxt->charset;
1022 }
1023}
1024
Daniel Veillard81273902003-09-30 00:43:48 +00001025#if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED)
Daniel Veillard1af9a412003-08-20 22:54:39 +00001026/**
1027 * xmlSAX2AttributeInternal:
1028 * @ctx: the user data (XML parser context)
1029 * @fullname: The attribute name, including namespace prefix
1030 * @value: The attribute value
1031 * @prefix: the prefix on the element node
1032 *
1033 * Handle an attribute that has been read by the parser.
1034 * The default handling is to convert the attribute into an
1035 * DOM subtree and past it in a new xmlAttr element added to
1036 * the element.
1037 */
1038static void
1039xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001040 const xmlChar *value, const xmlChar *prefix ATTRIBUTE_UNUSED)
Daniel Veillard1af9a412003-08-20 22:54:39 +00001041{
1042 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1043 xmlAttrPtr ret;
1044 xmlChar *name;
1045 xmlChar *ns;
1046 xmlChar *nval;
1047 xmlNsPtr namespace;
1048
1049 /*
1050 * Split the full name into a namespace prefix and the tag name
1051 */
1052 name = xmlSplitQName(ctxt, fullname, &ns);
1053 if ((name != NULL) && (name[0] == 0)) {
1054 if (xmlStrEqual(ns, BAD_CAST "xmlns")) {
Daniel Veillard87b30462005-07-05 14:04:36 +00001055 xmlNsErrMsg(ctxt, XML_ERR_NS_DECL_ERROR,
1056 "invalid namespace declaration '%s'\n",
1057 fullname, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001058 } else {
Daniel Veillard87b30462005-07-05 14:04:36 +00001059 xmlNsWarnMsg(ctxt, XML_WAR_NS_COLUMN,
1060 "Avoid attribute ending with ':' like '%s'\n",
1061 fullname, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001062 }
1063 if (ns != NULL)
1064 xmlFree(ns);
1065 ns = NULL;
1066 xmlFree(name);
1067 name = xmlStrdup(fullname);
1068 }
1069 if (name == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001070 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
Daniel Veillard1af9a412003-08-20 22:54:39 +00001071 if (ns != NULL)
1072 xmlFree(ns);
1073 return;
1074 }
1075
Daniel Veillard4432df22003-09-28 18:58:27 +00001076#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001077 /*
1078 * Do the last stage of the attribute normalization
1079 * Needed for HTML too:
1080 * http://www.w3.org/TR/html4/types.html#h-6.2
1081 */
1082 ctxt->vctxt.valid = 1;
1083 nval = xmlValidCtxtNormalizeAttributeValue(&ctxt->vctxt,
1084 ctxt->myDoc, ctxt->node,
1085 fullname, value);
1086 if (ctxt->vctxt.valid != 1) {
1087 ctxt->valid = 0;
1088 }
1089 if (nval != NULL)
1090 value = nval;
Daniel Veillard4432df22003-09-28 18:58:27 +00001091#else
1092 nval = NULL;
1093#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001094
1095 /*
1096 * Check whether it's a namespace definition
1097 */
1098 if ((!ctxt->html) && (ns == NULL) &&
1099 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
1100 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
1101 xmlNsPtr nsret;
1102 xmlChar *val;
1103
1104 if (!ctxt->replaceEntities) {
1105 ctxt->depth++;
1106 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1107 0,0,0);
1108 ctxt->depth--;
1109 } else {
1110 val = (xmlChar *) value;
1111 }
1112
1113 if (val[0] != 0) {
1114 xmlURIPtr uri;
1115
1116 uri = xmlParseURI((const char *)val);
1117 if (uri == NULL) {
1118 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1119 ctxt->sax->warning(ctxt->userData,
William M. Brack4811ba32003-09-06 18:02:53 +00001120 "xmlns: %s not a valid URI\n", val);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001121 } else {
1122 if (uri->scheme == NULL) {
1123 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1124 ctxt->sax->warning(ctxt->userData,
1125 "xmlns: URI %s is not absolute\n", val);
1126 }
1127 xmlFreeURI(uri);
1128 }
1129 }
1130
1131 /* a default namespace definition */
1132 nsret = xmlNewNs(ctxt->node, val, NULL);
1133
Daniel Veillard4432df22003-09-28 18:58:27 +00001134#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001135 /*
1136 * Validate also for namespace decls, they are attributes from
1137 * an XML-1.0 perspective
1138 */
1139 if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
1140 ctxt->myDoc && ctxt->myDoc->intSubset)
1141 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
1142 ctxt->node, prefix, nsret, val);
Daniel Veillard4432df22003-09-28 18:58:27 +00001143#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001144 if (name != NULL)
1145 xmlFree(name);
1146 if (nval != NULL)
1147 xmlFree(nval);
1148 if (val != value)
1149 xmlFree(val);
1150 return;
1151 }
1152 if ((!ctxt->html) &&
1153 (ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
1154 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
1155 xmlNsPtr nsret;
1156 xmlChar *val;
1157
1158 if (!ctxt->replaceEntities) {
1159 ctxt->depth++;
1160 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1161 0,0,0);
1162 ctxt->depth--;
1163 if (val == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001164 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
Daniel Veillard1af9a412003-08-20 22:54:39 +00001165 xmlFree(ns);
1166 if (name != NULL)
1167 xmlFree(name);
1168 return;
1169 }
1170 } else {
1171 val = (xmlChar *) value;
1172 }
1173
1174 if (val[0] == 0) {
Daniel Veillard87b30462005-07-05 14:04:36 +00001175 xmlNsErrMsg(ctxt, XML_NS_ERR_EMPTY,
1176 "Empty namespace name for prefix %s\n", name, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001177 }
1178 if ((ctxt->pedantic != 0) && (val[0] != 0)) {
1179 xmlURIPtr uri;
1180
1181 uri = xmlParseURI((const char *)val);
1182 if (uri == NULL) {
Daniel Veillard87b30462005-07-05 14:04:36 +00001183 xmlNsWarnMsg(ctxt, XML_WAR_NS_URI,
Daniel Veillard1af9a412003-08-20 22:54:39 +00001184 "xmlns:%s: %s not a valid URI\n", name, value);
1185 } else {
1186 if (uri->scheme == NULL) {
Daniel Veillard87b30462005-07-05 14:04:36 +00001187 xmlNsWarnMsg(ctxt, XML_WAR_NS_URI_RELATIVE,
Daniel Veillard1af9a412003-08-20 22:54:39 +00001188 "xmlns:%s: URI %s is not absolute\n", name, value);
1189 }
1190 xmlFreeURI(uri);
1191 }
1192 }
1193
1194 /* a standard namespace definition */
1195 nsret = xmlNewNs(ctxt->node, val, name);
1196 xmlFree(ns);
Daniel Veillard4432df22003-09-28 18:58:27 +00001197#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001198 /*
1199 * Validate also for namespace decls, they are attributes from
1200 * an XML-1.0 perspective
1201 */
1202 if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
1203 ctxt->myDoc && ctxt->myDoc->intSubset)
1204 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
1205 ctxt->node, prefix, nsret, value);
Daniel Veillard4432df22003-09-28 18:58:27 +00001206#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001207 if (name != NULL)
1208 xmlFree(name);
1209 if (nval != NULL)
1210 xmlFree(nval);
1211 if (val != value)
1212 xmlFree(val);
1213 return;
1214 }
1215
1216 if (ns != NULL) {
1217 xmlAttrPtr prop;
1218 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
Daniel Veillard67906942003-08-28 21:13:25 +00001219 if (namespace == NULL) {
Daniel Veillard87b30462005-07-05 14:04:36 +00001220 xmlNsErrMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
William M. Brack4811ba32003-09-06 18:02:53 +00001221 "Namespace prefix %s of attribute %s is not defined\n",
Daniel Veillard67906942003-08-28 21:13:25 +00001222 ns, name);
1223 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001224
1225 prop = ctxt->node->properties;
1226 while (prop != NULL) {
1227 if (prop->ns != NULL) {
1228 if ((xmlStrEqual(name, prop->name)) &&
1229 ((namespace == prop->ns) ||
1230 (xmlStrEqual(namespace->href, prop->ns->href)))) {
Daniel Veillard87b30462005-07-05 14:04:36 +00001231 xmlNsErrMsg(ctxt, XML_ERR_ATTRIBUTE_REDEFINED,
Daniel Veillard1af9a412003-08-20 22:54:39 +00001232 "Attribute %s in %s redefined\n",
1233 name, namespace->href);
1234 ctxt->wellFormed = 0;
1235 if (ctxt->recovery == 0) ctxt->disableSAX = 1;
1236 goto error;
1237 }
1238 }
1239 prop = prop->next;
1240 }
1241 } else {
1242 namespace = NULL;
1243 }
1244
1245 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
1246 ret = xmlNewNsPropEatName(ctxt->node, namespace, name, NULL);
1247
1248 if (ret != NULL) {
1249 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
1250 xmlNodePtr tmp;
1251
1252 ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
1253 tmp = ret->children;
1254 while (tmp != NULL) {
1255 tmp->parent = (xmlNodePtr) ret;
1256 if (tmp->next == NULL)
1257 ret->last = tmp;
1258 tmp = tmp->next;
1259 }
1260 } else if (value != NULL) {
1261 ret->children = xmlNewDocText(ctxt->myDoc, value);
1262 ret->last = ret->children;
1263 if (ret->children != NULL)
1264 ret->children->parent = (xmlNodePtr) ret;
1265 }
1266 }
1267
Daniel Veillard4432df22003-09-28 18:58:27 +00001268#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001269 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
1270 ctxt->myDoc && ctxt->myDoc->intSubset) {
1271
1272 /*
1273 * If we don't substitute entities, the validation should be
1274 * done on a value with replaced entities anyway.
1275 */
1276 if (!ctxt->replaceEntities) {
1277 xmlChar *val;
1278
1279 ctxt->depth++;
1280 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1281 0,0,0);
1282 ctxt->depth--;
1283
1284 if (val == NULL)
1285 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1286 ctxt->myDoc, ctxt->node, ret, value);
1287 else {
1288 xmlChar *nvalnorm;
1289
1290 /*
1291 * Do the last stage of the attribute normalization
1292 * It need to be done twice ... it's an extra burden related
1293 * to the ability to keep xmlSAX2References in attributes
1294 */
1295 nvalnorm = xmlValidNormalizeAttributeValue(ctxt->myDoc,
1296 ctxt->node, fullname, val);
1297 if (nvalnorm != NULL) {
1298 xmlFree(val);
1299 val = nvalnorm;
1300 }
1301
1302 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1303 ctxt->myDoc, ctxt->node, ret, val);
1304 xmlFree(val);
1305 }
1306 } else {
1307 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
1308 ctxt->node, ret, value);
1309 }
Daniel Veillard4432df22003-09-28 18:58:27 +00001310 } else
1311#endif /* LIBXML_VALID_ENABLED */
1312 if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
Daniel Veillard1af9a412003-08-20 22:54:39 +00001313 (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
1314 ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
1315 /*
1316 * when validating, the ID registration is done at the attribute
1317 * validation level. Otherwise we have to do specific handling here.
1318 */
1319 if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
1320 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
1321 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
1322 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00001323 else if (xmlStrEqual(fullname, BAD_CAST "xml:id")) {
1324 /*
1325 * Add the xml:id value
1326 *
1327 * Open issue: normalization of the value.
1328 */
Daniel Veillard68cb4b22004-04-18 20:55:39 +00001329 if (xmlValidateNCName(value, 1) != 0) {
1330 xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
1331 "xml:id : attribute value %s is not an NCName\n",
1332 (const char *) value, NULL);
1333 }
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00001334 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
1335 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001336 }
1337
1338error:
1339 if (nval != NULL)
1340 xmlFree(nval);
1341 if (ns != NULL)
1342 xmlFree(ns);
1343}
1344
Daniel Veillard1af9a412003-08-20 22:54:39 +00001345/*
1346 * xmlCheckDefaultedAttributes:
1347 *
1348 * Check defaulted attributes from the DTD
1349 */
1350static void
1351xmlCheckDefaultedAttributes(xmlParserCtxtPtr ctxt, const xmlChar *name,
1352 const xmlChar *prefix, const xmlChar **atts) {
1353 xmlElementPtr elemDecl;
1354 const xmlChar *att;
1355 int internal = 1;
1356 int i;
1357
1358 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset, name, prefix);
1359 if (elemDecl == NULL) {
1360 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset, name, prefix);
1361 internal = 0;
1362 }
1363
1364process_external_subset:
1365
1366 if (elemDecl != NULL) {
1367 xmlAttributePtr attr = elemDecl->attributes;
1368 /*
1369 * Check against defaulted attributes from the external subset
1370 * if the document is stamped as standalone
1371 */
1372 if ((ctxt->myDoc->standalone == 1) &&
1373 (ctxt->myDoc->extSubset != NULL) &&
1374 (ctxt->validate)) {
1375 while (attr != NULL) {
1376 if ((attr->defaultValue != NULL) &&
1377 (xmlGetDtdQAttrDesc(ctxt->myDoc->extSubset,
1378 attr->elem, attr->name,
1379 attr->prefix) == attr) &&
1380 (xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1381 attr->elem, attr->name,
1382 attr->prefix) == NULL)) {
1383 xmlChar *fulln;
1384
1385 if (attr->prefix != NULL) {
1386 fulln = xmlStrdup(attr->prefix);
1387 fulln = xmlStrcat(fulln, BAD_CAST ":");
1388 fulln = xmlStrcat(fulln, attr->name);
1389 } else {
1390 fulln = xmlStrdup(attr->name);
1391 }
1392
1393 /*
1394 * Check that the attribute is not declared in the
1395 * serialization
1396 */
1397 att = NULL;
1398 if (atts != NULL) {
1399 i = 0;
1400 att = atts[i];
1401 while (att != NULL) {
1402 if (xmlStrEqual(att, fulln))
1403 break;
1404 i += 2;
1405 att = atts[i];
1406 }
1407 }
1408 if (att == NULL) {
Daniel Veillardf88d8cf2003-12-08 10:25:02 +00001409 xmlErrValid(ctxt, XML_DTD_STANDALONE_DEFAULTED,
Daniel Veillard1af9a412003-08-20 22:54:39 +00001410 "standalone: attribute %s on %s defaulted from external subset\n",
Daniel Veillard427174f2003-12-10 10:42:59 +00001411 (const char *)fulln,
1412 (const char *)attr->elem);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001413 }
1414 }
1415 attr = attr->nexth;
1416 }
1417 }
1418
1419 /*
1420 * Actually insert defaulted values when needed
1421 */
1422 attr = elemDecl->attributes;
1423 while (attr != NULL) {
1424 /*
1425 * Make sure that attributes redefinition occuring in the
1426 * internal subset are not overriden by definitions in the
1427 * external subset.
1428 */
1429 if (attr->defaultValue != NULL) {
1430 /*
1431 * the element should be instantiated in the tree if:
1432 * - this is a namespace prefix
1433 * - the user required for completion in the tree
1434 * like XSLT
1435 * - there isn't already an attribute definition
1436 * in the internal subset overriding it.
1437 */
1438 if (((attr->prefix != NULL) &&
1439 (xmlStrEqual(attr->prefix, BAD_CAST "xmlns"))) ||
1440 ((attr->prefix == NULL) &&
1441 (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) ||
1442 (ctxt->loadsubset & XML_COMPLETE_ATTRS)) {
1443 xmlAttributePtr tst;
1444
1445 tst = xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1446 attr->elem, attr->name,
1447 attr->prefix);
1448 if ((tst == attr) || (tst == NULL)) {
1449 xmlChar fn[50];
1450 xmlChar *fulln;
1451
1452 fulln = xmlBuildQName(attr->name, attr->prefix, fn, 50);
1453 if (fulln == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001454 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
Daniel Veillard1af9a412003-08-20 22:54:39 +00001455 return;
1456 }
1457
1458 /*
1459 * Check that the attribute is not declared in the
1460 * serialization
1461 */
1462 att = NULL;
1463 if (atts != NULL) {
1464 i = 0;
1465 att = atts[i];
1466 while (att != NULL) {
1467 if (xmlStrEqual(att, fulln))
1468 break;
1469 i += 2;
1470 att = atts[i];
1471 }
1472 }
1473 if (att == NULL) {
1474 xmlSAX2AttributeInternal(ctxt, fulln,
1475 attr->defaultValue, prefix);
1476 }
1477 if ((fulln != fn) && (fulln != attr->name))
1478 xmlFree(fulln);
1479 }
1480 }
1481 }
1482 attr = attr->nexth;
1483 }
1484 if (internal == 1) {
1485 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset,
1486 name, prefix);
1487 internal = 0;
1488 goto process_external_subset;
1489 }
1490 }
1491}
1492
1493/**
1494 * xmlSAX2StartElement:
1495 * @ctx: the user data (XML parser context)
1496 * @fullname: The element name, including namespace prefix
1497 * @atts: An array of name/value attributes pairs, NULL terminated
1498 *
1499 * called when an opening tag has been processed.
1500 */
1501void
1502xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
1503{
1504 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1505 xmlNodePtr ret;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00001506 xmlNodePtr parent;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001507 xmlNsPtr ns;
1508 xmlChar *name;
1509 xmlChar *prefix;
1510 const xmlChar *att;
1511 const xmlChar *value;
1512 int i;
1513
Daniel Veillarda521d282004-11-09 14:59:59 +00001514 if ((ctx == NULL) || (fullname == NULL) || (ctxt->myDoc == NULL)) return;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00001515 parent = ctxt->node;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001516#ifdef DEBUG_SAX
1517 xmlGenericError(xmlGenericErrorContext,
1518 "SAX.xmlSAX2StartElement(%s)\n", fullname);
1519#endif
1520
1521 /*
1522 * First check on validity:
1523 */
1524 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
1525 ((ctxt->myDoc->intSubset == NULL) ||
1526 ((ctxt->myDoc->intSubset->notations == NULL) &&
1527 (ctxt->myDoc->intSubset->elements == NULL) &&
1528 (ctxt->myDoc->intSubset->attributes == NULL) &&
1529 (ctxt->myDoc->intSubset->entities == NULL)))) {
Daniel Veillardf88d8cf2003-12-08 10:25:02 +00001530 xmlErrValid(ctxt, XML_ERR_NO_DTD,
1531 "Validation failed: no DTD found !", NULL, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001532 ctxt->validate = 0;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001533 }
1534
1535
1536 /*
1537 * Split the full name into a namespace prefix and the tag name
1538 */
1539 name = xmlSplitQName(ctxt, fullname, &prefix);
1540
1541
1542 /*
1543 * Note : the namespace resolution is deferred until the end of the
1544 * attributes parsing, since local namespace can be defined as
1545 * an attribute at this level.
1546 */
1547 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL);
1548 if (ret == NULL) {
1549 if (prefix != NULL)
1550 xmlFree(prefix);
William M. Brack42331a92004-07-29 07:07:16 +00001551 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
Daniel Veillard1af9a412003-08-20 22:54:39 +00001552 return;
1553 }
1554 if (ctxt->myDoc->children == NULL) {
1555#ifdef DEBUG_SAX_TREE
1556 xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
1557#endif
1558 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1559 } else if (parent == NULL) {
1560 parent = ctxt->myDoc->children;
1561 }
1562 ctxt->nodemem = -1;
1563 if (ctxt->linenumbers) {
Daniel Veillard3e35f8e2003-10-21 00:05:38 +00001564 if (ctxt->input != NULL) {
1565 if (ctxt->input->line < 65535)
1566 ret->line = (short) ctxt->input->line;
1567 else
1568 ret->line = 65535;
1569 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001570 }
1571
1572 /*
1573 * We are parsing a new node.
1574 */
1575#ifdef DEBUG_SAX_TREE
1576 xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);
1577#endif
1578 nodePush(ctxt, ret);
1579
1580 /*
1581 * Link the child element
1582 */
1583 if (parent != NULL) {
1584 if (parent->type == XML_ELEMENT_NODE) {
1585#ifdef DEBUG_SAX_TREE
1586 xmlGenericError(xmlGenericErrorContext,
1587 "adding child %s to %s\n", name, parent->name);
1588#endif
1589 xmlAddChild(parent, ret);
1590 } else {
1591#ifdef DEBUG_SAX_TREE
1592 xmlGenericError(xmlGenericErrorContext,
1593 "adding sibling %s to ", name);
1594 xmlDebugDumpOneNode(stderr, parent, 0);
1595#endif
1596 xmlAddSibling(parent, ret);
1597 }
1598 }
1599
1600 /*
1601 * Insert all the defaulted attributes from the DTD especially namespaces
1602 */
1603 if ((!ctxt->html) &&
1604 ((ctxt->myDoc->intSubset != NULL) ||
1605 (ctxt->myDoc->extSubset != NULL))) {
1606 xmlCheckDefaultedAttributes(ctxt, name, prefix, atts);
1607 }
1608
1609 /*
1610 * process all the attributes whose name start with "xmlns"
1611 */
1612 if (atts != NULL) {
1613 i = 0;
1614 att = atts[i++];
1615 value = atts[i++];
1616 if (!ctxt->html) {
1617 while ((att != NULL) && (value != NULL)) {
1618 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l') &&
1619 (att[3] == 'n') && (att[4] == 's'))
1620 xmlSAX2AttributeInternal(ctxt, att, value, prefix);
1621
1622 att = atts[i++];
1623 value = atts[i++];
1624 }
1625 }
1626 }
1627
1628 /*
1629 * Search the namespace, note that since the attributes have been
1630 * processed, the local namespaces are available.
1631 */
1632 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
1633 if ((ns == NULL) && (parent != NULL))
1634 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
1635 if ((prefix != NULL) && (ns == NULL)) {
1636 ns = xmlNewNs(ret, NULL, prefix);
1637 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1638 ctxt->sax->warning(ctxt->userData,
1639 "Namespace prefix %s is not defined\n", prefix);
1640 }
1641
1642 /*
1643 * set the namespace node, making sure that if the default namspace
1644 * is unbound on a parent we simply kee it NULL
1645 */
1646 if ((ns != NULL) && (ns->href != NULL) &&
1647 ((ns->href[0] != 0) || (ns->prefix != NULL)))
1648 xmlSetNs(ret, ns);
1649
1650 /*
1651 * process all the other attributes
1652 */
1653 if (atts != NULL) {
1654 i = 0;
1655 att = atts[i++];
1656 value = atts[i++];
1657 if (ctxt->html) {
1658 while (att != NULL) {
1659 xmlSAX2AttributeInternal(ctxt, att, value, NULL);
1660 att = atts[i++];
1661 value = atts[i++];
1662 }
1663 } else {
1664 while ((att != NULL) && (value != NULL)) {
1665 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l') ||
1666 (att[3] != 'n') || (att[4] != 's'))
1667 xmlSAX2AttributeInternal(ctxt, att, value, NULL);
1668
1669 /*
1670 * Next ones
1671 */
1672 att = atts[i++];
1673 value = atts[i++];
1674 }
1675 }
1676 }
1677
Daniel Veillard4432df22003-09-28 18:58:27 +00001678#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001679 /*
1680 * If it's the Document root, finish the DTD validation and
1681 * check the document root element for validity
1682 */
Daniel Veillardeff45a92004-10-29 12:10:55 +00001683 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == XML_CTXT_FINISH_DTD_0)) {
Daniel Veillard1af9a412003-08-20 22:54:39 +00001684 int chk;
1685
1686 chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
1687 if (chk <= 0)
1688 ctxt->valid = 0;
1689 if (chk < 0)
1690 ctxt->wellFormed = 0;
1691 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
Daniel Veillardeff45a92004-10-29 12:10:55 +00001692 ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_1;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001693 }
Daniel Veillard4432df22003-09-28 18:58:27 +00001694#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001695
1696 if (prefix != NULL)
1697 xmlFree(prefix);
1698
1699}
1700
1701/**
1702 * xmlSAX2EndElement:
1703 * @ctx: the user data (XML parser context)
1704 * @name: The element name
1705 *
1706 * called when the end of an element has been detected.
1707 */
1708void
1709xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
1710{
1711 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1712 xmlParserNodeInfo node_info;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00001713 xmlNodePtr cur;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001714
Daniel Veillard34099b42004-11-04 17:34:35 +00001715 if (ctx == NULL) return;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00001716 cur = ctxt->node;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001717#ifdef DEBUG_SAX
1718 if (name == NULL)
1719 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(NULL)\n");
1720 else
1721 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(%s)\n", name);
1722#endif
1723
1724 /* Capture end position and add node */
1725 if (cur != NULL && ctxt->record_info) {
1726 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
1727 node_info.end_line = ctxt->input->line;
1728 node_info.node = cur;
1729 xmlParserAddNodeInfo(ctxt, &node_info);
1730 }
1731 ctxt->nodemem = -1;
1732
Daniel Veillard4432df22003-09-28 18:58:27 +00001733#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001734 if (ctxt->validate && ctxt->wellFormed &&
1735 ctxt->myDoc && ctxt->myDoc->intSubset)
1736 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
1737 cur);
Daniel Veillard4432df22003-09-28 18:58:27 +00001738#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001739
1740
1741 /*
1742 * end of parsing of this node.
1743 */
1744#ifdef DEBUG_SAX_TREE
1745 xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);
1746#endif
1747 nodePop(ctxt);
1748}
Daniel Veillard81273902003-09-30 00:43:48 +00001749#endif /* LIBXML_SAX1_ENABLED || LIBXML_HTML_ENABLE */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001750
Daniel Veillarde57ec792003-09-10 10:50:59 +00001751/*
Daniel Veillard19895052003-09-17 13:59:32 +00001752 * xmlSAX2TextNode:
1753 * @ctxt: the parser context
1754 * @str: the input string
1755 * @len: the string length
1756 *
1757 * Remove the entities from an attribute value
1758 *
1759 * Returns the newly allocated string or NULL if not needed or error
1760 */
1761static xmlNodePtr
1762xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
1763 xmlNodePtr ret;
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001764 const xmlChar *intern = NULL;
Daniel Veillard19895052003-09-17 13:59:32 +00001765
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001766 /*
1767 * Allocate
1768 */
Daniel Veillard19895052003-09-17 13:59:32 +00001769 if (ctxt->freeElems != NULL) {
1770 ret = ctxt->freeElems;
1771 ctxt->freeElems = ret->next;
1772 ctxt->freeElemsNr--;
Daniel Veillard19895052003-09-17 13:59:32 +00001773 } else {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001774 ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard19895052003-09-17 13:59:32 +00001775 }
1776 if (ret == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001777 xmlErrMemory(ctxt, "xmlSAX2Characters");
Daniel Veillard19895052003-09-17 13:59:32 +00001778 return(NULL);
1779 }
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001780 /*
1781 * intern the formatting blanks found between tags, or the
1782 * very short strings
1783 */
1784 if (ctxt->dictNames) {
1785 xmlChar cur = str[len];
1786
Daniel Veillarddca8cc72003-09-26 13:53:14 +00001787 if ((len <= 3) && ((cur == '"') || (cur == '\'') ||
1788 ((cur == '<') && (str[len + 1] != '!')))) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001789 intern = xmlDictLookup(ctxt->dict, str, len);
William M. Brack76e95df2003-10-18 16:20:14 +00001790 } else if (IS_BLANK_CH(*str) && (len < 60) && (cur == '<') &&
Daniel Veillarddca8cc72003-09-26 13:53:14 +00001791 (str[len + 1] != '!')) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001792 int i;
1793
1794 for (i = 1;i < len;i++) {
Daniel Veillard1a9b7082004-01-02 10:42:01 +00001795 if (!IS_BLANK_CH(str[i])) goto skip;
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001796 }
1797 intern = xmlDictLookup(ctxt->dict, str, len);
1798 }
1799 }
1800skip:
1801 memset(ret, 0, sizeof(xmlNode));
1802 ret->type = XML_TEXT_NODE;
1803
1804 ret->name = xmlStringText;
William M. Brack9f797ab2004-07-28 07:40:12 +00001805 if (intern == NULL) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001806 ret->content = xmlStrndup(str, len);
William M. Brack9f797ab2004-07-28 07:40:12 +00001807 if (ret->content == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001808 xmlSAX2ErrMemory(ctxt, "xmlSAX2TextNode");
1809 xmlFree(ret);
William M. Brack9f797ab2004-07-28 07:40:12 +00001810 return(NULL);
1811 }
1812 } else
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001813 ret->content = (xmlChar *) intern;
1814
1815 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1816 xmlRegisterNodeDefaultValue(ret);
Daniel Veillard19895052003-09-17 13:59:32 +00001817 return(ret);
1818}
1819
Daniel Veillard4432df22003-09-28 18:58:27 +00001820#ifdef LIBXML_VALID_ENABLED
Daniel Veillard19895052003-09-17 13:59:32 +00001821/*
Daniel Veillarde57ec792003-09-10 10:50:59 +00001822 * xmlSAX2DecodeAttrEntities:
1823 * @ctxt: the parser context
1824 * @str: the input string
1825 * @len: the string length
1826 *
1827 * Remove the entities from an attribute value
1828 *
1829 * Returns the newly allocated string or NULL if not needed or error
1830 */
1831static xmlChar *
1832xmlSAX2DecodeAttrEntities(xmlParserCtxtPtr ctxt, const xmlChar *str,
1833 const xmlChar *end) {
1834 const xmlChar *in;
1835 xmlChar *ret;
1836
1837 in = str;
1838 while (in < end)
1839 if (*in++ == '&')
1840 goto decode;
1841 return(NULL);
1842decode:
1843 ctxt->depth++;
1844 ret = xmlStringLenDecodeEntities(ctxt, str, end - str,
1845 XML_SUBSTITUTE_REF, 0,0,0);
1846 ctxt->depth--;
1847 return(ret);
1848}
Daniel Veillard4432df22003-09-28 18:58:27 +00001849#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00001850
1851/**
1852 * xmlSAX2AttributeNs:
1853 * @ctx: the user data (XML parser context)
Daniel Veillard62998c02003-09-15 12:56:36 +00001854 * @localname: the local name of the attribute
1855 * @prefix: the attribute namespace prefix if available
1856 * @URI: the attribute namespace name if available
Daniel Veillarde57ec792003-09-10 10:50:59 +00001857 * @value: Start of the attribute value
1858 * @valueend: end of the attribute value
1859 *
1860 * Handle an attribute that has been read by the parser.
1861 * The default handling is to convert the attribute into an
1862 * DOM subtree and past it in a new xmlAttr element added to
1863 * the element.
1864 */
1865static void
1866xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
1867 const xmlChar * localname,
1868 const xmlChar * prefix,
1869 const xmlChar * value,
1870 const xmlChar * valueend)
1871{
1872 xmlAttrPtr ret;
1873 xmlNsPtr namespace = NULL;
1874 xmlChar *dup = NULL;
1875
Daniel Veillarde57ec792003-09-10 10:50:59 +00001876 /*
1877 * Note: if prefix == NULL, the attribute is not in the default namespace
1878 */
1879 if (prefix != NULL)
1880 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, prefix);
1881
Daniel Veillard8a44e592003-09-15 14:50:06 +00001882 /*
1883 * allocate the node
1884 */
1885 if (ctxt->freeAttrs != NULL) {
1886 ret = ctxt->freeAttrs;
1887 ctxt->freeAttrs = ret->next;
Daniel Veillard19895052003-09-17 13:59:32 +00001888 ctxt->freeAttrsNr--;
Daniel Veillard8a44e592003-09-15 14:50:06 +00001889 memset(ret, 0, sizeof(xmlAttr));
1890 ret->type = XML_ATTRIBUTE_NODE;
Daniel Veillarde57ec792003-09-10 10:50:59 +00001891
Daniel Veillard8a44e592003-09-15 14:50:06 +00001892 ret->parent = ctxt->node;
1893 ret->doc = ctxt->myDoc;
1894 ret->ns = namespace;
Daniel Veillarde57ec792003-09-10 10:50:59 +00001895
Daniel Veillard8a44e592003-09-15 14:50:06 +00001896 if (ctxt->dictNames)
1897 ret->name = localname;
1898 else
1899 ret->name = xmlStrdup(localname);
1900
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001901 /* link at the end to preserv order, TODO speed up with a last */
1902 if (ctxt->node->properties == NULL) {
1903 ctxt->node->properties = ret;
1904 } else {
1905 xmlAttrPtr prev = ctxt->node->properties;
1906
1907 while (prev->next != NULL) prev = prev->next;
1908 prev->next = ret;
1909 ret->prev = prev;
1910 }
1911
Daniel Veillard8a44e592003-09-15 14:50:06 +00001912 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1913 xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
1914 } else {
1915 if (ctxt->dictNames)
1916 ret = xmlNewNsPropEatName(ctxt->node, namespace,
1917 (xmlChar *) localname, NULL);
1918 else
1919 ret = xmlNewNsProp(ctxt->node, namespace, localname, NULL);
1920 if (ret == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001921 xmlErrMemory(ctxt, "xmlSAX2AttributeNs");
Daniel Veillard8a44e592003-09-15 14:50:06 +00001922 return;
Daniel Veillarde57ec792003-09-10 10:50:59 +00001923 }
1924 }
1925
Daniel Veillard8a44e592003-09-15 14:50:06 +00001926 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
1927 xmlNodePtr tmp;
1928
Daniel Veillard19895052003-09-17 13:59:32 +00001929 /*
1930 * We know that if there is an entity reference, then
1931 * the string has been dup'ed and terminates with 0
1932 * otherwise with ' or "
1933 */
1934 if (*valueend != 0) {
1935 tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
1936 ret->children = tmp;
1937 ret->last = tmp;
1938 if (tmp != NULL) {
1939 tmp->doc = ret->doc;
1940 tmp->parent = (xmlNodePtr) ret;
1941 }
1942 } else {
1943 ret->children = xmlStringLenGetNodeList(ctxt->myDoc, value,
1944 valueend - value);
1945 tmp = ret->children;
1946 while (tmp != NULL) {
Daniel Veillard8de5c0b2004-10-07 13:14:19 +00001947 tmp->doc = ret->doc;
Daniel Veillard19895052003-09-17 13:59:32 +00001948 tmp->parent = (xmlNodePtr) ret;
1949 if (tmp->next == NULL)
1950 ret->last = tmp;
1951 tmp = tmp->next;
1952 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00001953 }
1954 } else if (value != NULL) {
Daniel Veillard19895052003-09-17 13:59:32 +00001955 xmlNodePtr tmp;
1956
1957 tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
1958 ret->children = tmp;
1959 ret->last = tmp;
1960 if (tmp != NULL) {
1961 tmp->doc = ret->doc;
1962 tmp->parent = (xmlNodePtr) ret;
1963 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00001964 }
1965
Daniel Veillard4432df22003-09-28 18:58:27 +00001966#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00001967 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
1968 ctxt->myDoc && ctxt->myDoc->intSubset) {
1969 /*
1970 * If we don't substitute entities, the validation should be
1971 * done on a value with replaced entities anyway.
1972 */
1973 if (!ctxt->replaceEntities) {
1974 dup = xmlSAX2DecodeAttrEntities(ctxt, value, valueend);
1975 if (dup == NULL) {
Daniel Veillard62998c02003-09-15 12:56:36 +00001976 if (*valueend == 0) {
1977 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1978 ctxt->myDoc, ctxt->node, ret, value);
1979 } else {
1980 /*
1981 * That should already be normalized.
1982 * cheaper to finally allocate here than duplicate
1983 * entry points in the full validation code
1984 */
1985 dup = xmlStrndup(value, valueend - value);
Daniel Veillarde57ec792003-09-10 10:50:59 +00001986
Daniel Veillard62998c02003-09-15 12:56:36 +00001987 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1988 ctxt->myDoc, ctxt->node, ret, dup);
1989 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00001990 } else {
Daniel Veillard62998c02003-09-15 12:56:36 +00001991 /*
1992 * dup now contains a string of the flattened attribute
1993 * content with entities substitued. Check if we need to
1994 * apply an extra layer of normalization.
Daniel Veillarde57ec792003-09-10 10:50:59 +00001995 * It need to be done twice ... it's an extra burden related
1996 * to the ability to keep references in attributes
1997 */
Daniel Veillard62998c02003-09-15 12:56:36 +00001998 if (ctxt->attsSpecial != NULL) {
1999 xmlChar *nvalnorm;
2000 xmlChar fn[50];
2001 xmlChar *fullname;
2002
2003 fullname = xmlBuildQName(localname, prefix, fn, 50);
2004 if (fullname != NULL) {
2005 ctxt->vctxt.valid = 1;
2006 nvalnorm = xmlValidCtxtNormalizeAttributeValue(
2007 &ctxt->vctxt, ctxt->myDoc,
2008 ctxt->node, fullname, dup);
2009 if (ctxt->vctxt.valid != 1)
2010 ctxt->valid = 0;
2011
2012 if ((fullname != fn) && (fullname != localname))
2013 xmlFree(fullname);
2014 if (nvalnorm != NULL) {
2015 xmlFree(dup);
2016 dup = nvalnorm;
2017 }
2018 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002019 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002020
2021 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2022 ctxt->myDoc, ctxt->node, ret, dup);
2023 }
2024 } else {
Daniel Veillard8e36e6a2003-09-10 10:50:59 +00002025 /*
2026 * if entities already have been substitued, then
2027 * the attribute as passed is already normalized
2028 */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002029 dup = xmlStrndup(value, valueend - value);
2030
2031 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2032 ctxt->myDoc, ctxt->node, ret, dup);
2033 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002034 } else
2035#endif /* LIBXML_VALID_ENABLED */
2036 if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
Daniel Veillarde57ec792003-09-10 10:50:59 +00002037 (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
2038 ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
2039 /*
2040 * when validating, the ID registration is done at the attribute
2041 * validation level. Otherwise we have to do specific handling here.
2042 */
2043 if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) {
2044 /* might be worth duplicate entry points and not copy */
2045 if (dup == NULL)
2046 dup = xmlStrndup(value, valueend - value);
2047 xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
2048 } else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) {
2049 if (dup == NULL)
2050 dup = xmlStrndup(value, valueend - value);
2051 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, dup, ret);
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00002052 } else if ((prefix == ctxt->str_xml) &&
2053 (localname[0] == 'i') && (localname[1] == 'd') &&
2054 (localname[2] == 0)) {
2055 /*
2056 * Add the xml:id value
2057 *
2058 * Open issue: normalization of the value.
2059 */
2060 if (dup == NULL)
2061 dup = xmlStrndup(value, valueend - value);
William M. Brack5ef2f812004-05-23 23:56:47 +00002062#ifdef LIBXML_VALID_ENABLED
Daniel Veillard68cb4b22004-04-18 20:55:39 +00002063 if (xmlValidateNCName(dup, 1) != 0) {
2064 xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
2065 "xml:id : attribute value %s is not an NCName\n",
2066 (const char *) dup, NULL);
2067 }
William M. Brack3f147372004-05-22 01:09:26 +00002068#endif
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00002069 xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
2070 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002071 }
2072 if (dup != NULL)
2073 xmlFree(dup);
2074}
2075
2076/**
2077 * xmlSAX2StartElementNs:
2078 * @ctx: the user data (XML parser context)
2079 * @localname: the local name of the element
2080 * @prefix: the element namespace prefix if available
2081 * @URI: the element namespace name if available
2082 * @nb_namespaces: number of namespace definitions on that node
2083 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
2084 * @nb_attributes: the number of attributes on that node
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00002085 * @nb_defaulted: the number of defaulted attributes.
Daniel Veillarde57ec792003-09-10 10:50:59 +00002086 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
2087 * attribute values.
2088 *
2089 * SAX2 callback when an element start has been detected by the parser.
2090 * It provides the namespace informations for the element, as well as
2091 * the new namespace declarations on the element.
2092 */
2093void
2094xmlSAX2StartElementNs(void *ctx,
2095 const xmlChar *localname,
2096 const xmlChar *prefix,
2097 const xmlChar *URI,
2098 int nb_namespaces,
2099 const xmlChar **namespaces,
2100 int nb_attributes,
2101 int nb_defaulted,
2102 const xmlChar **attributes)
2103{
2104 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2105 xmlNodePtr ret;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002106 xmlNodePtr parent;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002107 xmlNsPtr last = NULL, ns;
2108 const xmlChar *uri, *pref;
2109 int i, j;
2110
Daniel Veillard34099b42004-11-04 17:34:35 +00002111 if (ctx == NULL) return;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002112 parent = ctxt->node;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002113 /*
2114 * First check on validity:
2115 */
2116 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
2117 ((ctxt->myDoc->intSubset == NULL) ||
2118 ((ctxt->myDoc->intSubset->notations == NULL) &&
2119 (ctxt->myDoc->intSubset->elements == NULL) &&
2120 (ctxt->myDoc->intSubset->attributes == NULL) &&
2121 (ctxt->myDoc->intSubset->entities == NULL)))) {
Daniel Veillardf88d8cf2003-12-08 10:25:02 +00002122 xmlErrValid(ctxt, XML_ERR_NO_DTD,
2123 "Validation failed: no DTD found !", NULL, NULL);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002124 ctxt->validate = 0;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002125 }
2126
Daniel Veillard8a44e592003-09-15 14:50:06 +00002127 /*
2128 * allocate the node
2129 */
2130 if (ctxt->freeElems != NULL) {
2131 ret = ctxt->freeElems;
2132 ctxt->freeElems = ret->next;
Daniel Veillard19895052003-09-17 13:59:32 +00002133 ctxt->freeElemsNr--;
Daniel Veillard8a44e592003-09-15 14:50:06 +00002134 memset(ret, 0, sizeof(xmlNode));
2135 ret->type = XML_ELEMENT_NODE;
2136
2137 if (ctxt->dictNames)
2138 ret->name = localname;
William M. Brack9f797ab2004-07-28 07:40:12 +00002139 else {
Daniel Veillard8a44e592003-09-15 14:50:06 +00002140 ret->name = xmlStrdup(localname);
William M. Brack9f797ab2004-07-28 07:40:12 +00002141 if (ret->name == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002142 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
William M. Brack9f797ab2004-07-28 07:40:12 +00002143 return;
2144 }
2145 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00002146 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2147 xmlRegisterNodeDefaultValue(ret);
2148 } else {
2149 if (ctxt->dictNames)
2150 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
2151 (xmlChar *) localname, NULL);
2152 else
2153 ret = xmlNewDocNode(ctxt->myDoc, NULL, localname, NULL);
2154 if (ret == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002155 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
Daniel Veillard8a44e592003-09-15 14:50:06 +00002156 return;
2157 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002158 }
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002159 if (ctxt->linenumbers) {
Daniel Veillard3e35f8e2003-10-21 00:05:38 +00002160 if (ctxt->input != NULL) {
2161 if (ctxt->input->line < 65535)
2162 ret->line = (short) ctxt->input->line;
2163 else
2164 ret->line = 65535;
2165 }
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002166 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00002167
Daniel Veillard29b17482004-08-16 00:39:03 +00002168 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
Daniel Veillarde57ec792003-09-10 10:50:59 +00002169 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002170 }
2171 /*
2172 * Build the namespace list
2173 */
2174 for (i = 0,j = 0;j < nb_namespaces;j++) {
2175 pref = namespaces[i++];
2176 uri = namespaces[i++];
2177 ns = xmlNewNs(NULL, uri, pref);
2178 if (ns != NULL) {
2179 if (last == NULL) {
2180 ret->nsDef = last = ns;
2181 } else {
2182 last->next = ns;
2183 last = ns;
2184 }
2185 if ((URI != NULL) && (prefix == pref))
2186 ret->ns = ns;
2187 } else {
William M. Brack42331a92004-07-29 07:07:16 +00002188 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
Daniel Veillarde57ec792003-09-10 10:50:59 +00002189 return;
2190 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002191#ifdef LIBXML_VALID_ENABLED
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002192 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
2193 ctxt->myDoc && ctxt->myDoc->intSubset) {
2194 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
2195 ret, prefix, ns, uri);
2196 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002197#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002198 }
2199 ctxt->nodemem = -1;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002200
2201 /*
2202 * We are parsing a new node.
2203 */
2204 nodePush(ctxt, ret);
2205
2206 /*
2207 * Link the child element
2208 */
2209 if (parent != NULL) {
2210 if (parent->type == XML_ELEMENT_NODE) {
2211 xmlAddChild(parent, ret);
2212 } else {
2213 xmlAddSibling(parent, ret);
2214 }
2215 }
2216
2217 /*
2218 * Insert the defaulted attributes from the DTD only if requested:
2219 */
2220 if ((nb_defaulted != 0) &&
2221 ((ctxt->loadsubset & XML_COMPLETE_ATTRS) == 0))
2222 nb_attributes -= nb_defaulted;
2223
2224 /*
2225 * Search the namespace if it wasn't already found
William M. Brackbf5cf212004-08-31 06:47:17 +00002226 * Note that, if prefix is NULL, this searches for the default Ns
Daniel Veillarde57ec792003-09-10 10:50:59 +00002227 */
2228 if ((URI != NULL) && (ret->ns == NULL)) {
William M. Brackbf5cf212004-08-31 06:47:17 +00002229 ret->ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002230 if (ret->ns == NULL) {
2231 ns = xmlNewNs(ret, NULL, prefix);
William M. Brack9f797ab2004-07-28 07:40:12 +00002232 if (ns == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002233 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
William M. Brack9f797ab2004-07-28 07:40:12 +00002234 return;
2235 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002236 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
2237 ctxt->sax->warning(ctxt->userData,
2238 "Namespace prefix %s was not found\n", prefix);
2239 }
2240 }
2241
2242 /*
2243 * process all the other attributes
2244 */
2245 if (nb_attributes > 0) {
2246 for (j = 0,i = 0;i < nb_attributes;i++,j+=5) {
2247 xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1],
2248 attributes[j+3], attributes[j+4]);
2249 }
2250 }
2251
Daniel Veillard4432df22003-09-28 18:58:27 +00002252#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002253 /*
2254 * If it's the Document root, finish the DTD validation and
2255 * check the document root element for validity
2256 */
Daniel Veillardeff45a92004-10-29 12:10:55 +00002257 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == XML_CTXT_FINISH_DTD_0)) {
Daniel Veillarde57ec792003-09-10 10:50:59 +00002258 int chk;
2259
2260 chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
2261 if (chk <= 0)
2262 ctxt->valid = 0;
2263 if (chk < 0)
2264 ctxt->wellFormed = 0;
2265 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
Daniel Veillardeff45a92004-10-29 12:10:55 +00002266 ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_1;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002267 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002268#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002269}
2270
2271/**
2272 * xmlSAX2EndElementNs:
2273 * @ctx: the user data (XML parser context)
2274 * @localname: the local name of the element
2275 * @prefix: the element namespace prefix if available
2276 * @URI: the element namespace name if available
2277 *
2278 * SAX2 callback when an element end has been detected by the parser.
2279 * It provides the namespace informations for the element.
2280 */
2281void
2282xmlSAX2EndElementNs(void *ctx,
2283 const xmlChar * localname ATTRIBUTE_UNUSED,
2284 const xmlChar * prefix ATTRIBUTE_UNUSED,
2285 const xmlChar * URI ATTRIBUTE_UNUSED)
2286{
2287 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2288 xmlParserNodeInfo node_info;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002289 xmlNodePtr cur;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002290
Daniel Veillard34099b42004-11-04 17:34:35 +00002291 if (ctx == NULL) return;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002292 cur = ctxt->node;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002293 /* Capture end position and add node */
2294 if ((ctxt->record_info) && (cur != NULL)) {
2295 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
2296 node_info.end_line = ctxt->input->line;
2297 node_info.node = cur;
2298 xmlParserAddNodeInfo(ctxt, &node_info);
2299 }
2300 ctxt->nodemem = -1;
2301
Daniel Veillard4432df22003-09-28 18:58:27 +00002302#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002303 if (ctxt->validate && ctxt->wellFormed &&
2304 ctxt->myDoc && ctxt->myDoc->intSubset)
2305 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, cur);
Daniel Veillard4432df22003-09-28 18:58:27 +00002306#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002307
2308 /*
2309 * end of parsing of this node.
2310 */
2311 nodePop(ctxt);
2312}
2313
Daniel Veillard1af9a412003-08-20 22:54:39 +00002314/**
2315 * xmlSAX2Reference:
2316 * @ctx: the user data (XML parser context)
2317 * @name: The entity name
2318 *
2319 * called when an entity xmlSAX2Reference is detected.
2320 */
2321void
2322xmlSAX2Reference(void *ctx, const xmlChar *name)
2323{
2324 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2325 xmlNodePtr ret;
2326
Daniel Veillard34099b42004-11-04 17:34:35 +00002327 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002328#ifdef DEBUG_SAX
2329 xmlGenericError(xmlGenericErrorContext,
2330 "SAX.xmlSAX2Reference(%s)\n", name);
2331#endif
2332 if (name[0] == '#')
2333 ret = xmlNewCharRef(ctxt->myDoc, name);
2334 else
2335 ret = xmlNewReference(ctxt->myDoc, name);
2336#ifdef DEBUG_SAX_TREE
2337 xmlGenericError(xmlGenericErrorContext,
2338 "add xmlSAX2Reference %s to %s \n", name, ctxt->node->name);
2339#endif
2340 xmlAddChild(ctxt->node, ret);
2341}
2342
2343/**
2344 * xmlSAX2Characters:
2345 * @ctx: the user data (XML parser context)
2346 * @ch: a xmlChar string
2347 * @len: the number of xmlChar
2348 *
2349 * receiving some chars from the parser.
2350 */
2351void
2352xmlSAX2Characters(void *ctx, const xmlChar *ch, int len)
2353{
2354 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2355 xmlNodePtr lastChild;
2356
Daniel Veillard34099b42004-11-04 17:34:35 +00002357 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002358#ifdef DEBUG_SAX
2359 xmlGenericError(xmlGenericErrorContext,
2360 "SAX.xmlSAX2Characters(%.30s, %d)\n", ch, len);
2361#endif
2362 /*
2363 * Handle the data if any. If there is no child
2364 * add it as content, otherwise if the last child is text,
2365 * concatenate it, else create a new node of type text.
2366 */
2367
2368 if (ctxt->node == NULL) {
2369#ifdef DEBUG_SAX_TREE
2370 xmlGenericError(xmlGenericErrorContext,
2371 "add chars: ctxt->node == NULL !\n");
2372#endif
2373 return;
2374 }
Daniel Veillard19895052003-09-17 13:59:32 +00002375 lastChild = ctxt->node->last;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002376#ifdef DEBUG_SAX_TREE
2377 xmlGenericError(xmlGenericErrorContext,
2378 "add chars to %s \n", ctxt->node->name);
2379#endif
2380
2381 /*
2382 * Here we needed an accelerator mechanism in case of very large
2383 * elements. Use an attribute in the structure !!!
2384 */
2385 if (lastChild == NULL) {
Daniel Veillard19895052003-09-17 13:59:32 +00002386 lastChild = xmlSAX2TextNode(ctxt, ch, len);
2387 if (lastChild != NULL) {
2388 ctxt->node->children = lastChild;
2389 ctxt->node->last = lastChild;
2390 lastChild->parent = ctxt->node;
2391 lastChild->doc = ctxt->node->doc;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002392 ctxt->nodelen = len;
2393 ctxt->nodemem = len + 1;
William M. Bracka3215c72004-07-31 16:24:01 +00002394 } else {
2395 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
2396 return;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002397 }
2398 } else {
2399 int coalesceText = (lastChild != NULL) &&
2400 (lastChild->type == XML_TEXT_NODE) &&
2401 (lastChild->name == xmlStringText);
2402 if ((coalesceText) && (ctxt->nodemem != 0)) {
2403 /*
2404 * The whole point of maintaining nodelen and nodemem,
2405 * xmlTextConcat is too costly, i.e. compute length,
2406 * reallocate a new buffer, move data, append ch. Here
2407 * We try to minimaze realloc() uses and avoid copying
2408 * and recomputing length over and over.
2409 */
Daniel Veillard2b0f8792003-10-10 19:36:36 +00002410 if ((ctxt->nodemem == ctxt->nodelen + 1) &&
2411 (xmlDictOwns(ctxt->dict, lastChild->content))) {
2412 lastChild->content = xmlStrdup(lastChild->content);
2413 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00002414 if (ctxt->nodelen + len >= ctxt->nodemem) {
2415 xmlChar *newbuf;
2416 int size;
2417
2418 size = ctxt->nodemem + len;
2419 size *= 2;
2420 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
2421 if (newbuf == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002422 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
Daniel Veillard1af9a412003-08-20 22:54:39 +00002423 return;
2424 }
2425 ctxt->nodemem = size;
2426 lastChild->content = newbuf;
2427 }
2428 memcpy(&lastChild->content[ctxt->nodelen], ch, len);
2429 ctxt->nodelen += len;
2430 lastChild->content[ctxt->nodelen] = 0;
2431 } else if (coalesceText) {
2432 if (xmlTextConcat(lastChild, ch, len)) {
William M. Brack42331a92004-07-29 07:07:16 +00002433 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
Daniel Veillard1af9a412003-08-20 22:54:39 +00002434 }
2435 if (ctxt->node->children != NULL) {
2436 ctxt->nodelen = xmlStrlen(lastChild->content);
2437 ctxt->nodemem = ctxt->nodelen + 1;
2438 }
2439 } else {
2440 /* Mixed content, first time */
Daniel Veillard19895052003-09-17 13:59:32 +00002441 lastChild = xmlSAX2TextNode(ctxt, ch, len);
2442 if (lastChild != NULL) {
Daniel Veillard1af9a412003-08-20 22:54:39 +00002443 xmlAddChild(ctxt->node, lastChild);
2444 if (ctxt->node->children != NULL) {
2445 ctxt->nodelen = len;
2446 ctxt->nodemem = len + 1;
2447 }
2448 }
2449 }
2450 }
2451}
2452
2453/**
2454 * xmlSAX2IgnorableWhitespace:
2455 * @ctx: the user data (XML parser context)
2456 * @ch: a xmlChar string
2457 * @len: the number of xmlChar
2458 *
2459 * receiving some ignorable whitespaces from the parser.
2460 * UNUSED: by default the DOM building will use xmlSAX2Characters
2461 */
2462void
2463xmlSAX2IgnorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
2464{
2465 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
2466#ifdef DEBUG_SAX
2467 xmlGenericError(xmlGenericErrorContext,
2468 "SAX.xmlSAX2IgnorableWhitespace(%.30s, %d)\n", ch, len);
2469#endif
2470}
2471
2472/**
2473 * xmlSAX2ProcessingInstruction:
2474 * @ctx: the user data (XML parser context)
2475 * @target: the target name
2476 * @data: the PI data's
2477 *
2478 * A processing instruction has been parsed.
2479 */
2480void
2481xmlSAX2ProcessingInstruction(void *ctx, const xmlChar *target,
2482 const xmlChar *data)
2483{
2484 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2485 xmlNodePtr ret;
Daniel Veillard6128c012004-11-08 17:16:15 +00002486 xmlNodePtr parent;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002487
Daniel Veillard34099b42004-11-04 17:34:35 +00002488 if (ctx == NULL) return;
Daniel Veillard6128c012004-11-08 17:16:15 +00002489 parent = ctxt->node;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002490#ifdef DEBUG_SAX
2491 xmlGenericError(xmlGenericErrorContext,
2492 "SAX.xmlSAX2ProcessingInstruction(%s, %s)\n", target, data);
2493#endif
2494
Daniel Veillard03a53c32004-10-26 16:06:51 +00002495 ret = xmlNewDocPI(ctxt->myDoc, target, data);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002496 if (ret == NULL) return;
2497 parent = ctxt->node;
2498
2499 if (ctxt->inSubset == 1) {
2500 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2501 return;
2502 } else if (ctxt->inSubset == 2) {
2503 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2504 return;
2505 }
2506 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
2507#ifdef DEBUG_SAX_TREE
2508 xmlGenericError(xmlGenericErrorContext,
2509 "Setting PI %s as root\n", target);
2510#endif
2511 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2512 return;
2513 }
2514 if (parent->type == XML_ELEMENT_NODE) {
2515#ifdef DEBUG_SAX_TREE
2516 xmlGenericError(xmlGenericErrorContext,
2517 "adding PI %s child to %s\n", target, parent->name);
2518#endif
2519 xmlAddChild(parent, ret);
2520 } else {
2521#ifdef DEBUG_SAX_TREE
2522 xmlGenericError(xmlGenericErrorContext,
2523 "adding PI %s sibling to ", target);
2524 xmlDebugDumpOneNode(stderr, parent, 0);
2525#endif
2526 xmlAddSibling(parent, ret);
2527 }
2528}
2529
2530/**
2531 * xmlSAX2Comment:
2532 * @ctx: the user data (XML parser context)
2533 * @value: the xmlSAX2Comment content
2534 *
2535 * A xmlSAX2Comment has been parsed.
2536 */
2537void
2538xmlSAX2Comment(void *ctx, const xmlChar *value)
2539{
2540 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2541 xmlNodePtr ret;
Daniel Veillard34099b42004-11-04 17:34:35 +00002542 xmlNodePtr parent;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002543
Daniel Veillard34099b42004-11-04 17:34:35 +00002544 if (ctx == NULL) return;
2545 parent = ctxt->node;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002546#ifdef DEBUG_SAX
2547 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2Comment(%s)\n", value);
2548#endif
2549 ret = xmlNewDocComment(ctxt->myDoc, value);
2550 if (ret == NULL) return;
2551
2552 if (ctxt->inSubset == 1) {
2553 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2554 return;
2555 } else if (ctxt->inSubset == 2) {
2556 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2557 return;
2558 }
2559 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
2560#ifdef DEBUG_SAX_TREE
2561 xmlGenericError(xmlGenericErrorContext,
2562 "Setting xmlSAX2Comment as root\n");
2563#endif
2564 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2565 return;
2566 }
2567 if (parent->type == XML_ELEMENT_NODE) {
2568#ifdef DEBUG_SAX_TREE
2569 xmlGenericError(xmlGenericErrorContext,
2570 "adding xmlSAX2Comment child to %s\n", parent->name);
2571#endif
2572 xmlAddChild(parent, ret);
2573 } else {
2574#ifdef DEBUG_SAX_TREE
2575 xmlGenericError(xmlGenericErrorContext,
2576 "adding xmlSAX2Comment sibling to ");
2577 xmlDebugDumpOneNode(stderr, parent, 0);
2578#endif
2579 xmlAddSibling(parent, ret);
2580 }
2581}
2582
2583/**
2584 * xmlSAX2CDataBlock:
2585 * @ctx: the user data (XML parser context)
2586 * @value: The pcdata content
2587 * @len: the block length
2588 *
2589 * called when a pcdata block has been parsed
2590 */
2591void
2592xmlSAX2CDataBlock(void *ctx, const xmlChar *value, int len)
2593{
2594 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2595 xmlNodePtr ret, lastChild;
2596
Daniel Veillard34099b42004-11-04 17:34:35 +00002597 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002598#ifdef DEBUG_SAX
2599 xmlGenericError(xmlGenericErrorContext,
2600 "SAX.pcdata(%.10s, %d)\n", value, len);
2601#endif
2602 lastChild = xmlGetLastChild(ctxt->node);
2603#ifdef DEBUG_SAX_TREE
2604 xmlGenericError(xmlGenericErrorContext,
2605 "add chars to %s \n", ctxt->node->name);
2606#endif
2607 if ((lastChild != NULL) &&
2608 (lastChild->type == XML_CDATA_SECTION_NODE)) {
2609 xmlTextConcat(lastChild, value, len);
2610 } else {
2611 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
2612 xmlAddChild(ctxt->node, ret);
2613 }
2614}
2615
Daniel Veillard62998c02003-09-15 12:56:36 +00002616static int xmlSAX2DefaultVersionValue = 2;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002617
Daniel Veillard81273902003-09-30 00:43:48 +00002618#ifdef LIBXML_SAX1_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002619/**
2620 * xmlSAXDefaultVersion:
2621 * @version: the version, 1 or 2
2622 *
2623 * Set the default version of SAX used globally by the library.
William M. Brack96d2eff2004-06-30 11:48:47 +00002624 * By default, during initialization the default is set to 2.
2625 * Note that it is generally a better coding style to use
2626 * xmlSAXVersion() to set up the version explicitly for a given
2627 * parsing context.
Daniel Veillarde57ec792003-09-10 10:50:59 +00002628 *
2629 * Returns the previous value in case of success and -1 in case of error.
2630 */
2631int
2632xmlSAXDefaultVersion(int version)
2633{
2634 int ret = xmlSAX2DefaultVersionValue;
2635
2636 if ((version != 1) && (version != 2))
2637 return(-1);
2638 xmlSAX2DefaultVersionValue = version;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002639 return(ret);
2640}
Daniel Veillard81273902003-09-30 00:43:48 +00002641#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002642
2643/**
2644 * xmlSAXVersion:
2645 * @hdlr: the SAX handler
2646 * @version: the version, 1 or 2
2647 *
2648 * Initialize the default XML SAX handler according to the version
2649 *
2650 * Returns 0 in case of success and -1 in case of error.
2651 */
2652int
2653xmlSAXVersion(xmlSAXHandler *hdlr, int version)
2654{
2655 if (hdlr == NULL) return(-1);
Daniel Veillard81273902003-09-30 00:43:48 +00002656 if (version == 2) {
Daniel Veillarde57ec792003-09-10 10:50:59 +00002657 hdlr->startElement = NULL;
2658 hdlr->endElement = NULL;
2659 hdlr->startElementNs = xmlSAX2StartElementNs;
2660 hdlr->endElementNs = xmlSAX2EndElementNs;
Daniel Veillardffbbed42003-10-10 14:46:54 +00002661 hdlr->serror = NULL;
Daniel Veillard092643b2003-09-25 14:29:29 +00002662 hdlr->initialized = XML_SAX2_MAGIC;
Daniel Veillard81273902003-09-30 00:43:48 +00002663#ifdef LIBXML_SAX1_ENABLED
2664 } else if (version == 1) {
2665 hdlr->startElement = xmlSAX2StartElement;
2666 hdlr->endElement = xmlSAX2EndElement;
2667 hdlr->initialized = 1;
2668#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002669 } else
2670 return(-1);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002671 hdlr->internalSubset = xmlSAX2InternalSubset;
2672 hdlr->externalSubset = xmlSAX2ExternalSubset;
2673 hdlr->isStandalone = xmlSAX2IsStandalone;
2674 hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
2675 hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
2676 hdlr->resolveEntity = xmlSAX2ResolveEntity;
2677 hdlr->getEntity = xmlSAX2GetEntity;
2678 hdlr->getParameterEntity = xmlSAX2GetParameterEntity;
2679 hdlr->entityDecl = xmlSAX2EntityDecl;
2680 hdlr->attributeDecl = xmlSAX2AttributeDecl;
2681 hdlr->elementDecl = xmlSAX2ElementDecl;
2682 hdlr->notationDecl = xmlSAX2NotationDecl;
2683 hdlr->unparsedEntityDecl = xmlSAX2UnparsedEntityDecl;
2684 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2685 hdlr->startDocument = xmlSAX2StartDocument;
2686 hdlr->endDocument = xmlSAX2EndDocument;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002687 hdlr->reference = xmlSAX2Reference;
2688 hdlr->characters = xmlSAX2Characters;
2689 hdlr->cdataBlock = xmlSAX2CDataBlock;
2690 hdlr->ignorableWhitespace = xmlSAX2Characters;
2691 hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
2692 hdlr->comment = xmlSAX2Comment;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002693 hdlr->warning = xmlParserWarning;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002694 hdlr->error = xmlParserError;
2695 hdlr->fatalError = xmlParserError;
2696
Daniel Veillarde57ec792003-09-10 10:50:59 +00002697 return(0);
2698}
2699
2700/**
2701 * xmlSAX2InitDefaultSAXHandler:
2702 * @hdlr: the SAX handler
2703 * @warning: flag if non-zero sets the handler warning procedure
2704 *
2705 * Initialize the default XML SAX2 handler
2706 */
2707void
2708xmlSAX2InitDefaultSAXHandler(xmlSAXHandler *hdlr, int warning)
2709{
2710 if ((hdlr == NULL) || (hdlr->initialized != 0))
2711 return;
2712
2713 xmlSAXVersion(hdlr, xmlSAX2DefaultVersionValue);
2714 if (warning == 0)
2715 hdlr->warning = NULL;
2716 else
2717 hdlr->warning = xmlParserWarning;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002718}
2719
2720/**
2721 * xmlDefaultSAXHandlerInit:
2722 *
2723 * Initialize the default SAX2 handler
2724 */
2725void
2726xmlDefaultSAXHandlerInit(void)
2727{
Daniel Veillard81273902003-09-30 00:43:48 +00002728#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard092643b2003-09-25 14:29:29 +00002729 xmlSAXVersion((xmlSAXHandlerPtr) &xmlDefaultSAXHandler, 1);
Daniel Veillard81273902003-09-30 00:43:48 +00002730#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00002731}
2732
2733#ifdef LIBXML_HTML_ENABLED
2734
2735/**
2736 * xmlSAX2InitHtmlDefaultSAXHandler:
2737 * @hdlr: the SAX handler
2738 *
2739 * Initialize the default HTML SAX2 handler
2740 */
2741void
2742xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr)
2743{
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002744 if ((hdlr == NULL) || (hdlr->initialized != 0))
Daniel Veillard1af9a412003-08-20 22:54:39 +00002745 return;
2746
2747 hdlr->internalSubset = xmlSAX2InternalSubset;
2748 hdlr->externalSubset = NULL;
2749 hdlr->isStandalone = NULL;
2750 hdlr->hasInternalSubset = NULL;
2751 hdlr->hasExternalSubset = NULL;
2752 hdlr->resolveEntity = NULL;
2753 hdlr->getEntity = xmlSAX2GetEntity;
2754 hdlr->getParameterEntity = NULL;
2755 hdlr->entityDecl = NULL;
2756 hdlr->attributeDecl = NULL;
2757 hdlr->elementDecl = NULL;
2758 hdlr->notationDecl = NULL;
2759 hdlr->unparsedEntityDecl = NULL;
2760 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2761 hdlr->startDocument = xmlSAX2StartDocument;
2762 hdlr->endDocument = xmlSAX2EndDocument;
2763 hdlr->startElement = xmlSAX2StartElement;
2764 hdlr->endElement = xmlSAX2EndElement;
2765 hdlr->reference = NULL;
2766 hdlr->characters = xmlSAX2Characters;
2767 hdlr->cdataBlock = xmlSAX2CDataBlock;
2768 hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
Daniel Veillardfc484dd2004-10-22 14:34:23 +00002769 hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002770 hdlr->comment = xmlSAX2Comment;
2771 hdlr->warning = xmlParserWarning;
2772 hdlr->error = xmlParserError;
2773 hdlr->fatalError = xmlParserError;
2774
Daniel Veillard092643b2003-09-25 14:29:29 +00002775 hdlr->initialized = 1;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002776}
2777
2778/**
2779 * htmlDefaultSAXHandlerInit:
2780 *
2781 * Initialize the default SAX handler
2782 */
2783void
2784htmlDefaultSAXHandlerInit(void)
2785{
Daniel Veillard092643b2003-09-25 14:29:29 +00002786 xmlSAX2InitHtmlDefaultSAXHandler((xmlSAXHandlerPtr) &htmlDefaultSAXHandler);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002787}
2788
2789#endif /* LIBXML_HTML_ENABLED */
2790
2791#ifdef LIBXML_DOCB_ENABLED
2792
2793/**
2794 * xmlSAX2InitDocbDefaultSAXHandler:
2795 * @hdlr: the SAX handler
2796 *
2797 * Initialize the default DocBook SAX2 handler
2798 */
2799void
2800xmlSAX2InitDocbDefaultSAXHandler(xmlSAXHandler *hdlr)
2801{
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002802 if ((hdlr == NULL) || (hdlr->initialized != 0))
Daniel Veillard1af9a412003-08-20 22:54:39 +00002803 return;
2804
2805 hdlr->internalSubset = xmlSAX2InternalSubset;
2806 hdlr->externalSubset = NULL;
2807 hdlr->isStandalone = xmlSAX2IsStandalone;
2808 hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
2809 hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
2810 hdlr->resolveEntity = xmlSAX2ResolveEntity;
2811 hdlr->getEntity = xmlSAX2GetEntity;
2812 hdlr->getParameterEntity = NULL;
2813 hdlr->entityDecl = xmlSAX2EntityDecl;
2814 hdlr->attributeDecl = NULL;
2815 hdlr->elementDecl = NULL;
2816 hdlr->notationDecl = NULL;
2817 hdlr->unparsedEntityDecl = NULL;
2818 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2819 hdlr->startDocument = xmlSAX2StartDocument;
2820 hdlr->endDocument = xmlSAX2EndDocument;
2821 hdlr->startElement = xmlSAX2StartElement;
2822 hdlr->endElement = xmlSAX2EndElement;
2823 hdlr->reference = xmlSAX2Reference;
2824 hdlr->characters = xmlSAX2Characters;
2825 hdlr->cdataBlock = NULL;
2826 hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
2827 hdlr->processingInstruction = NULL;
2828 hdlr->comment = xmlSAX2Comment;
2829 hdlr->warning = xmlParserWarning;
2830 hdlr->error = xmlParserError;
2831 hdlr->fatalError = xmlParserError;
2832
Daniel Veillardffbbed42003-10-10 14:46:54 +00002833 hdlr->initialized = 1;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002834}
2835
2836/**
2837 * docbDefaultSAXHandlerInit:
2838 *
2839 * Initialize the default SAX handler
2840 */
2841void
2842docbDefaultSAXHandlerInit(void)
2843{
Daniel Veillard092643b2003-09-25 14:29:29 +00002844 xmlSAX2InitDocbDefaultSAXHandler((xmlSAXHandlerPtr) &docbDefaultSAXHandler);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002845}
2846
2847#endif /* LIBXML_DOCB_ENABLED */
Daniel Veillard5d4644e2005-04-01 13:11:58 +00002848#define bottom_SAX2
2849#include "elfgcchack.h"