blob: 9f7edf65d403cb7cdebfbed520ab0ffb24ce8cce [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 Veillard24505b02005-07-28 23:49:35 +0000230 if ((ctx == NULL) || (ctxt->input == NULL)) return(NULL);
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 Veillardbca3ad22005-08-23 22:14:02 +00001025#if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_DOCB_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 */
Daniel Veillard54f9a4f2005-09-03 13:28:24 +00001319 if (xmlStrEqual(fullname, BAD_CAST "xml:id")) {
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00001320 /*
1321 * Add the xml:id value
1322 *
1323 * Open issue: normalization of the value.
1324 */
Daniel Veillard68cb4b22004-04-18 20:55:39 +00001325 if (xmlValidateNCName(value, 1) != 0) {
1326 xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
1327 "xml:id : attribute value %s is not an NCName\n",
1328 (const char *) value, NULL);
1329 }
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00001330 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillard54f9a4f2005-09-03 13:28:24 +00001331 } else if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
1332 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
1333 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
1334 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001335 }
1336
1337error:
1338 if (nval != NULL)
1339 xmlFree(nval);
1340 if (ns != NULL)
1341 xmlFree(ns);
1342}
1343
Daniel Veillard1af9a412003-08-20 22:54:39 +00001344/*
1345 * xmlCheckDefaultedAttributes:
1346 *
1347 * Check defaulted attributes from the DTD
1348 */
1349static void
1350xmlCheckDefaultedAttributes(xmlParserCtxtPtr ctxt, const xmlChar *name,
1351 const xmlChar *prefix, const xmlChar **atts) {
1352 xmlElementPtr elemDecl;
1353 const xmlChar *att;
1354 int internal = 1;
1355 int i;
1356
1357 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset, name, prefix);
1358 if (elemDecl == NULL) {
1359 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset, name, prefix);
1360 internal = 0;
1361 }
1362
1363process_external_subset:
1364
1365 if (elemDecl != NULL) {
1366 xmlAttributePtr attr = elemDecl->attributes;
1367 /*
1368 * Check against defaulted attributes from the external subset
1369 * if the document is stamped as standalone
1370 */
1371 if ((ctxt->myDoc->standalone == 1) &&
1372 (ctxt->myDoc->extSubset != NULL) &&
1373 (ctxt->validate)) {
1374 while (attr != NULL) {
1375 if ((attr->defaultValue != NULL) &&
1376 (xmlGetDtdQAttrDesc(ctxt->myDoc->extSubset,
1377 attr->elem, attr->name,
1378 attr->prefix) == attr) &&
1379 (xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1380 attr->elem, attr->name,
1381 attr->prefix) == NULL)) {
1382 xmlChar *fulln;
1383
1384 if (attr->prefix != NULL) {
1385 fulln = xmlStrdup(attr->prefix);
1386 fulln = xmlStrcat(fulln, BAD_CAST ":");
1387 fulln = xmlStrcat(fulln, attr->name);
1388 } else {
1389 fulln = xmlStrdup(attr->name);
1390 }
1391
1392 /*
1393 * Check that the attribute is not declared in the
1394 * serialization
1395 */
1396 att = NULL;
1397 if (atts != NULL) {
1398 i = 0;
1399 att = atts[i];
1400 while (att != NULL) {
1401 if (xmlStrEqual(att, fulln))
1402 break;
1403 i += 2;
1404 att = atts[i];
1405 }
1406 }
1407 if (att == NULL) {
Daniel Veillardf88d8cf2003-12-08 10:25:02 +00001408 xmlErrValid(ctxt, XML_DTD_STANDALONE_DEFAULTED,
Daniel Veillard1af9a412003-08-20 22:54:39 +00001409 "standalone: attribute %s on %s defaulted from external subset\n",
Daniel Veillard427174f2003-12-10 10:42:59 +00001410 (const char *)fulln,
1411 (const char *)attr->elem);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001412 }
1413 }
1414 attr = attr->nexth;
1415 }
1416 }
1417
1418 /*
1419 * Actually insert defaulted values when needed
1420 */
1421 attr = elemDecl->attributes;
1422 while (attr != NULL) {
1423 /*
1424 * Make sure that attributes redefinition occuring in the
1425 * internal subset are not overriden by definitions in the
1426 * external subset.
1427 */
1428 if (attr->defaultValue != NULL) {
1429 /*
1430 * the element should be instantiated in the tree if:
1431 * - this is a namespace prefix
1432 * - the user required for completion in the tree
1433 * like XSLT
1434 * - there isn't already an attribute definition
1435 * in the internal subset overriding it.
1436 */
1437 if (((attr->prefix != NULL) &&
1438 (xmlStrEqual(attr->prefix, BAD_CAST "xmlns"))) ||
1439 ((attr->prefix == NULL) &&
1440 (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) ||
1441 (ctxt->loadsubset & XML_COMPLETE_ATTRS)) {
1442 xmlAttributePtr tst;
1443
1444 tst = xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1445 attr->elem, attr->name,
1446 attr->prefix);
1447 if ((tst == attr) || (tst == NULL)) {
1448 xmlChar fn[50];
1449 xmlChar *fulln;
1450
1451 fulln = xmlBuildQName(attr->name, attr->prefix, fn, 50);
1452 if (fulln == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001453 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
Daniel Veillard1af9a412003-08-20 22:54:39 +00001454 return;
1455 }
1456
1457 /*
1458 * Check that the attribute is not declared in the
1459 * serialization
1460 */
1461 att = NULL;
1462 if (atts != NULL) {
1463 i = 0;
1464 att = atts[i];
1465 while (att != NULL) {
1466 if (xmlStrEqual(att, fulln))
1467 break;
1468 i += 2;
1469 att = atts[i];
1470 }
1471 }
1472 if (att == NULL) {
1473 xmlSAX2AttributeInternal(ctxt, fulln,
1474 attr->defaultValue, prefix);
1475 }
1476 if ((fulln != fn) && (fulln != attr->name))
1477 xmlFree(fulln);
1478 }
1479 }
1480 }
1481 attr = attr->nexth;
1482 }
1483 if (internal == 1) {
1484 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset,
1485 name, prefix);
1486 internal = 0;
1487 goto process_external_subset;
1488 }
1489 }
1490}
1491
1492/**
1493 * xmlSAX2StartElement:
1494 * @ctx: the user data (XML parser context)
1495 * @fullname: The element name, including namespace prefix
1496 * @atts: An array of name/value attributes pairs, NULL terminated
1497 *
1498 * called when an opening tag has been processed.
1499 */
1500void
1501xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
1502{
1503 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1504 xmlNodePtr ret;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00001505 xmlNodePtr parent;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001506 xmlNsPtr ns;
1507 xmlChar *name;
1508 xmlChar *prefix;
1509 const xmlChar *att;
1510 const xmlChar *value;
1511 int i;
1512
Daniel Veillarda521d282004-11-09 14:59:59 +00001513 if ((ctx == NULL) || (fullname == NULL) || (ctxt->myDoc == NULL)) return;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00001514 parent = ctxt->node;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001515#ifdef DEBUG_SAX
1516 xmlGenericError(xmlGenericErrorContext,
1517 "SAX.xmlSAX2StartElement(%s)\n", fullname);
1518#endif
1519
1520 /*
1521 * First check on validity:
1522 */
1523 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
1524 ((ctxt->myDoc->intSubset == NULL) ||
1525 ((ctxt->myDoc->intSubset->notations == NULL) &&
1526 (ctxt->myDoc->intSubset->elements == NULL) &&
1527 (ctxt->myDoc->intSubset->attributes == NULL) &&
1528 (ctxt->myDoc->intSubset->entities == NULL)))) {
Daniel Veillardf88d8cf2003-12-08 10:25:02 +00001529 xmlErrValid(ctxt, XML_ERR_NO_DTD,
1530 "Validation failed: no DTD found !", NULL, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001531 ctxt->validate = 0;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001532 }
1533
1534
1535 /*
1536 * Split the full name into a namespace prefix and the tag name
1537 */
1538 name = xmlSplitQName(ctxt, fullname, &prefix);
1539
1540
1541 /*
1542 * Note : the namespace resolution is deferred until the end of the
1543 * attributes parsing, since local namespace can be defined as
1544 * an attribute at this level.
1545 */
1546 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL);
1547 if (ret == NULL) {
1548 if (prefix != NULL)
1549 xmlFree(prefix);
William M. Brack42331a92004-07-29 07:07:16 +00001550 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
Daniel Veillard1af9a412003-08-20 22:54:39 +00001551 return;
1552 }
1553 if (ctxt->myDoc->children == NULL) {
1554#ifdef DEBUG_SAX_TREE
1555 xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
1556#endif
1557 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1558 } else if (parent == NULL) {
1559 parent = ctxt->myDoc->children;
1560 }
1561 ctxt->nodemem = -1;
1562 if (ctxt->linenumbers) {
Daniel Veillard3e35f8e2003-10-21 00:05:38 +00001563 if (ctxt->input != NULL) {
1564 if (ctxt->input->line < 65535)
1565 ret->line = (short) ctxt->input->line;
1566 else
1567 ret->line = 65535;
1568 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001569 }
1570
1571 /*
1572 * We are parsing a new node.
1573 */
1574#ifdef DEBUG_SAX_TREE
1575 xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);
1576#endif
1577 nodePush(ctxt, ret);
1578
1579 /*
1580 * Link the child element
1581 */
1582 if (parent != NULL) {
1583 if (parent->type == XML_ELEMENT_NODE) {
1584#ifdef DEBUG_SAX_TREE
1585 xmlGenericError(xmlGenericErrorContext,
1586 "adding child %s to %s\n", name, parent->name);
1587#endif
1588 xmlAddChild(parent, ret);
1589 } else {
1590#ifdef DEBUG_SAX_TREE
1591 xmlGenericError(xmlGenericErrorContext,
1592 "adding sibling %s to ", name);
1593 xmlDebugDumpOneNode(stderr, parent, 0);
1594#endif
1595 xmlAddSibling(parent, ret);
1596 }
1597 }
1598
1599 /*
1600 * Insert all the defaulted attributes from the DTD especially namespaces
1601 */
1602 if ((!ctxt->html) &&
1603 ((ctxt->myDoc->intSubset != NULL) ||
1604 (ctxt->myDoc->extSubset != NULL))) {
1605 xmlCheckDefaultedAttributes(ctxt, name, prefix, atts);
1606 }
1607
1608 /*
1609 * process all the attributes whose name start with "xmlns"
1610 */
1611 if (atts != NULL) {
1612 i = 0;
1613 att = atts[i++];
1614 value = atts[i++];
1615 if (!ctxt->html) {
1616 while ((att != NULL) && (value != NULL)) {
1617 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l') &&
1618 (att[3] == 'n') && (att[4] == 's'))
1619 xmlSAX2AttributeInternal(ctxt, att, value, prefix);
1620
1621 att = atts[i++];
1622 value = atts[i++];
1623 }
1624 }
1625 }
1626
1627 /*
1628 * Search the namespace, note that since the attributes have been
1629 * processed, the local namespaces are available.
1630 */
1631 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
1632 if ((ns == NULL) && (parent != NULL))
1633 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
1634 if ((prefix != NULL) && (ns == NULL)) {
1635 ns = xmlNewNs(ret, NULL, prefix);
1636 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1637 ctxt->sax->warning(ctxt->userData,
1638 "Namespace prefix %s is not defined\n", prefix);
1639 }
1640
1641 /*
1642 * set the namespace node, making sure that if the default namspace
1643 * is unbound on a parent we simply kee it NULL
1644 */
1645 if ((ns != NULL) && (ns->href != NULL) &&
1646 ((ns->href[0] != 0) || (ns->prefix != NULL)))
1647 xmlSetNs(ret, ns);
1648
1649 /*
1650 * process all the other attributes
1651 */
1652 if (atts != NULL) {
1653 i = 0;
1654 att = atts[i++];
1655 value = atts[i++];
1656 if (ctxt->html) {
1657 while (att != NULL) {
1658 xmlSAX2AttributeInternal(ctxt, att, value, NULL);
1659 att = atts[i++];
1660 value = atts[i++];
1661 }
1662 } else {
1663 while ((att != NULL) && (value != NULL)) {
1664 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l') ||
1665 (att[3] != 'n') || (att[4] != 's'))
1666 xmlSAX2AttributeInternal(ctxt, att, value, NULL);
1667
1668 /*
1669 * Next ones
1670 */
1671 att = atts[i++];
1672 value = atts[i++];
1673 }
1674 }
1675 }
1676
Daniel Veillard4432df22003-09-28 18:58:27 +00001677#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001678 /*
1679 * If it's the Document root, finish the DTD validation and
1680 * check the document root element for validity
1681 */
Daniel Veillardeff45a92004-10-29 12:10:55 +00001682 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == XML_CTXT_FINISH_DTD_0)) {
Daniel Veillard1af9a412003-08-20 22:54:39 +00001683 int chk;
1684
1685 chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
1686 if (chk <= 0)
1687 ctxt->valid = 0;
1688 if (chk < 0)
1689 ctxt->wellFormed = 0;
1690 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
Daniel Veillardeff45a92004-10-29 12:10:55 +00001691 ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_1;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001692 }
Daniel Veillard4432df22003-09-28 18:58:27 +00001693#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001694
1695 if (prefix != NULL)
1696 xmlFree(prefix);
1697
1698}
1699
1700/**
1701 * xmlSAX2EndElement:
1702 * @ctx: the user data (XML parser context)
1703 * @name: The element name
1704 *
1705 * called when the end of an element has been detected.
1706 */
1707void
1708xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
1709{
1710 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1711 xmlParserNodeInfo node_info;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00001712 xmlNodePtr cur;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001713
Daniel Veillard34099b42004-11-04 17:34:35 +00001714 if (ctx == NULL) return;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00001715 cur = ctxt->node;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001716#ifdef DEBUG_SAX
1717 if (name == NULL)
1718 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(NULL)\n");
1719 else
1720 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(%s)\n", name);
1721#endif
1722
1723 /* Capture end position and add node */
1724 if (cur != NULL && ctxt->record_info) {
1725 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
1726 node_info.end_line = ctxt->input->line;
1727 node_info.node = cur;
1728 xmlParserAddNodeInfo(ctxt, &node_info);
1729 }
1730 ctxt->nodemem = -1;
1731
Daniel Veillard4432df22003-09-28 18:58:27 +00001732#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001733 if (ctxt->validate && ctxt->wellFormed &&
1734 ctxt->myDoc && ctxt->myDoc->intSubset)
1735 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
1736 cur);
Daniel Veillard4432df22003-09-28 18:58:27 +00001737#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001738
1739
1740 /*
1741 * end of parsing of this node.
1742 */
1743#ifdef DEBUG_SAX_TREE
1744 xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);
1745#endif
1746 nodePop(ctxt);
1747}
Daniel Veillard81273902003-09-30 00:43:48 +00001748#endif /* LIBXML_SAX1_ENABLED || LIBXML_HTML_ENABLE */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001749
Daniel Veillarde57ec792003-09-10 10:50:59 +00001750/*
Daniel Veillard19895052003-09-17 13:59:32 +00001751 * xmlSAX2TextNode:
1752 * @ctxt: the parser context
1753 * @str: the input string
1754 * @len: the string length
1755 *
1756 * Remove the entities from an attribute value
1757 *
1758 * Returns the newly allocated string or NULL if not needed or error
1759 */
1760static xmlNodePtr
1761xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
1762 xmlNodePtr ret;
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001763 const xmlChar *intern = NULL;
Daniel Veillard19895052003-09-17 13:59:32 +00001764
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001765 /*
1766 * Allocate
1767 */
Daniel Veillard19895052003-09-17 13:59:32 +00001768 if (ctxt->freeElems != NULL) {
1769 ret = ctxt->freeElems;
1770 ctxt->freeElems = ret->next;
1771 ctxt->freeElemsNr--;
Daniel Veillard19895052003-09-17 13:59:32 +00001772 } else {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001773 ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard19895052003-09-17 13:59:32 +00001774 }
1775 if (ret == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001776 xmlErrMemory(ctxt, "xmlSAX2Characters");
Daniel Veillard19895052003-09-17 13:59:32 +00001777 return(NULL);
1778 }
Daniel Veillard8874b942005-08-25 13:19:21 +00001779 memset(ret, 0, sizeof(xmlNode));
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 Veillard8874b942005-08-25 13:19:21 +00001787 if ((len < (int) (2 * sizeof(void *))) &&
1788 (ctxt->options & XML_PARSE_COMPACT)) {
1789 /* store the string in the node overrithing properties and nsDef */
1790 xmlChar *tmp = (xmlChar *) &(ret->properties);
1791 memcpy(tmp, str, len);
1792 tmp[len] = 0;
1793 intern = tmp;
1794 } else if ((len <= 3) && ((cur == '"') || (cur == '\'') ||
Daniel Veillarddca8cc72003-09-26 13:53:14 +00001795 ((cur == '<') && (str[len + 1] != '!')))) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001796 intern = xmlDictLookup(ctxt->dict, str, len);
William M. Brack76e95df2003-10-18 16:20:14 +00001797 } else if (IS_BLANK_CH(*str) && (len < 60) && (cur == '<') &&
Daniel Veillarddca8cc72003-09-26 13:53:14 +00001798 (str[len + 1] != '!')) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001799 int i;
1800
1801 for (i = 1;i < len;i++) {
Daniel Veillard1a9b7082004-01-02 10:42:01 +00001802 if (!IS_BLANK_CH(str[i])) goto skip;
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001803 }
1804 intern = xmlDictLookup(ctxt->dict, str, len);
1805 }
1806 }
1807skip:
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001808 ret->type = XML_TEXT_NODE;
1809
1810 ret->name = xmlStringText;
William M. Brack9f797ab2004-07-28 07:40:12 +00001811 if (intern == NULL) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001812 ret->content = xmlStrndup(str, len);
William M. Brack9f797ab2004-07-28 07:40:12 +00001813 if (ret->content == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001814 xmlSAX2ErrMemory(ctxt, "xmlSAX2TextNode");
1815 xmlFree(ret);
William M. Brack9f797ab2004-07-28 07:40:12 +00001816 return(NULL);
1817 }
1818 } else
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001819 ret->content = (xmlChar *) intern;
1820
1821 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1822 xmlRegisterNodeDefaultValue(ret);
Daniel Veillard19895052003-09-17 13:59:32 +00001823 return(ret);
1824}
1825
Daniel Veillard4432df22003-09-28 18:58:27 +00001826#ifdef LIBXML_VALID_ENABLED
Daniel Veillard19895052003-09-17 13:59:32 +00001827/*
Daniel Veillarde57ec792003-09-10 10:50:59 +00001828 * xmlSAX2DecodeAttrEntities:
1829 * @ctxt: the parser context
1830 * @str: the input string
1831 * @len: the string length
1832 *
1833 * Remove the entities from an attribute value
1834 *
1835 * Returns the newly allocated string or NULL if not needed or error
1836 */
1837static xmlChar *
1838xmlSAX2DecodeAttrEntities(xmlParserCtxtPtr ctxt, const xmlChar *str,
1839 const xmlChar *end) {
1840 const xmlChar *in;
1841 xmlChar *ret;
1842
1843 in = str;
1844 while (in < end)
1845 if (*in++ == '&')
1846 goto decode;
1847 return(NULL);
1848decode:
1849 ctxt->depth++;
1850 ret = xmlStringLenDecodeEntities(ctxt, str, end - str,
1851 XML_SUBSTITUTE_REF, 0,0,0);
1852 ctxt->depth--;
1853 return(ret);
1854}
Daniel Veillard4432df22003-09-28 18:58:27 +00001855#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00001856
1857/**
1858 * xmlSAX2AttributeNs:
1859 * @ctx: the user data (XML parser context)
Daniel Veillard62998c02003-09-15 12:56:36 +00001860 * @localname: the local name of the attribute
1861 * @prefix: the attribute namespace prefix if available
1862 * @URI: the attribute namespace name if available
Daniel Veillarde57ec792003-09-10 10:50:59 +00001863 * @value: Start of the attribute value
1864 * @valueend: end of the attribute value
1865 *
1866 * Handle an attribute that has been read by the parser.
1867 * The default handling is to convert the attribute into an
1868 * DOM subtree and past it in a new xmlAttr element added to
1869 * the element.
1870 */
1871static void
1872xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
1873 const xmlChar * localname,
1874 const xmlChar * prefix,
1875 const xmlChar * value,
1876 const xmlChar * valueend)
1877{
1878 xmlAttrPtr ret;
1879 xmlNsPtr namespace = NULL;
1880 xmlChar *dup = NULL;
1881
Daniel Veillarde57ec792003-09-10 10:50:59 +00001882 /*
1883 * Note: if prefix == NULL, the attribute is not in the default namespace
1884 */
1885 if (prefix != NULL)
1886 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, prefix);
1887
Daniel Veillard8a44e592003-09-15 14:50:06 +00001888 /*
1889 * allocate the node
1890 */
1891 if (ctxt->freeAttrs != NULL) {
1892 ret = ctxt->freeAttrs;
1893 ctxt->freeAttrs = ret->next;
Daniel Veillard19895052003-09-17 13:59:32 +00001894 ctxt->freeAttrsNr--;
Daniel Veillard8a44e592003-09-15 14:50:06 +00001895 memset(ret, 0, sizeof(xmlAttr));
1896 ret->type = XML_ATTRIBUTE_NODE;
Daniel Veillarde57ec792003-09-10 10:50:59 +00001897
Daniel Veillard8a44e592003-09-15 14:50:06 +00001898 ret->parent = ctxt->node;
1899 ret->doc = ctxt->myDoc;
1900 ret->ns = namespace;
Daniel Veillarde57ec792003-09-10 10:50:59 +00001901
Daniel Veillard8a44e592003-09-15 14:50:06 +00001902 if (ctxt->dictNames)
1903 ret->name = localname;
1904 else
1905 ret->name = xmlStrdup(localname);
1906
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001907 /* link at the end to preserv order, TODO speed up with a last */
1908 if (ctxt->node->properties == NULL) {
1909 ctxt->node->properties = ret;
1910 } else {
1911 xmlAttrPtr prev = ctxt->node->properties;
1912
1913 while (prev->next != NULL) prev = prev->next;
1914 prev->next = ret;
1915 ret->prev = prev;
1916 }
1917
Daniel Veillard8a44e592003-09-15 14:50:06 +00001918 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1919 xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
1920 } else {
1921 if (ctxt->dictNames)
1922 ret = xmlNewNsPropEatName(ctxt->node, namespace,
1923 (xmlChar *) localname, NULL);
1924 else
1925 ret = xmlNewNsProp(ctxt->node, namespace, localname, NULL);
1926 if (ret == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001927 xmlErrMemory(ctxt, "xmlSAX2AttributeNs");
Daniel Veillard8a44e592003-09-15 14:50:06 +00001928 return;
Daniel Veillarde57ec792003-09-10 10:50:59 +00001929 }
1930 }
1931
Daniel Veillard8a44e592003-09-15 14:50:06 +00001932 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
1933 xmlNodePtr tmp;
1934
Daniel Veillard19895052003-09-17 13:59:32 +00001935 /*
1936 * We know that if there is an entity reference, then
1937 * the string has been dup'ed and terminates with 0
1938 * otherwise with ' or "
1939 */
1940 if (*valueend != 0) {
1941 tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
1942 ret->children = tmp;
1943 ret->last = tmp;
1944 if (tmp != NULL) {
1945 tmp->doc = ret->doc;
1946 tmp->parent = (xmlNodePtr) ret;
1947 }
1948 } else {
1949 ret->children = xmlStringLenGetNodeList(ctxt->myDoc, value,
1950 valueend - value);
1951 tmp = ret->children;
1952 while (tmp != NULL) {
Daniel Veillard8de5c0b2004-10-07 13:14:19 +00001953 tmp->doc = ret->doc;
Daniel Veillard19895052003-09-17 13:59:32 +00001954 tmp->parent = (xmlNodePtr) ret;
1955 if (tmp->next == NULL)
1956 ret->last = tmp;
1957 tmp = tmp->next;
1958 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00001959 }
1960 } else if (value != NULL) {
Daniel Veillard19895052003-09-17 13:59:32 +00001961 xmlNodePtr tmp;
1962
1963 tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
1964 ret->children = tmp;
1965 ret->last = tmp;
1966 if (tmp != NULL) {
1967 tmp->doc = ret->doc;
1968 tmp->parent = (xmlNodePtr) ret;
1969 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00001970 }
1971
Daniel Veillard4432df22003-09-28 18:58:27 +00001972#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00001973 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
1974 ctxt->myDoc && ctxt->myDoc->intSubset) {
1975 /*
1976 * If we don't substitute entities, the validation should be
1977 * done on a value with replaced entities anyway.
1978 */
1979 if (!ctxt->replaceEntities) {
1980 dup = xmlSAX2DecodeAttrEntities(ctxt, value, valueend);
1981 if (dup == NULL) {
Daniel Veillard62998c02003-09-15 12:56:36 +00001982 if (*valueend == 0) {
1983 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1984 ctxt->myDoc, ctxt->node, ret, value);
1985 } else {
1986 /*
1987 * That should already be normalized.
1988 * cheaper to finally allocate here than duplicate
1989 * entry points in the full validation code
1990 */
1991 dup = xmlStrndup(value, valueend - value);
Daniel Veillarde57ec792003-09-10 10:50:59 +00001992
Daniel Veillard62998c02003-09-15 12:56:36 +00001993 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1994 ctxt->myDoc, ctxt->node, ret, dup);
1995 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00001996 } else {
Daniel Veillard62998c02003-09-15 12:56:36 +00001997 /*
1998 * dup now contains a string of the flattened attribute
1999 * content with entities substitued. Check if we need to
2000 * apply an extra layer of normalization.
Daniel Veillarde57ec792003-09-10 10:50:59 +00002001 * It need to be done twice ... it's an extra burden related
2002 * to the ability to keep references in attributes
2003 */
Daniel Veillard62998c02003-09-15 12:56:36 +00002004 if (ctxt->attsSpecial != NULL) {
2005 xmlChar *nvalnorm;
2006 xmlChar fn[50];
2007 xmlChar *fullname;
2008
2009 fullname = xmlBuildQName(localname, prefix, fn, 50);
2010 if (fullname != NULL) {
2011 ctxt->vctxt.valid = 1;
2012 nvalnorm = xmlValidCtxtNormalizeAttributeValue(
2013 &ctxt->vctxt, ctxt->myDoc,
2014 ctxt->node, fullname, dup);
2015 if (ctxt->vctxt.valid != 1)
2016 ctxt->valid = 0;
2017
2018 if ((fullname != fn) && (fullname != localname))
2019 xmlFree(fullname);
2020 if (nvalnorm != NULL) {
2021 xmlFree(dup);
2022 dup = nvalnorm;
2023 }
2024 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002025 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002026
2027 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2028 ctxt->myDoc, ctxt->node, ret, dup);
2029 }
2030 } else {
Daniel Veillard8e36e6a2003-09-10 10:50:59 +00002031 /*
2032 * if entities already have been substitued, then
2033 * the attribute as passed is already normalized
2034 */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002035 dup = xmlStrndup(value, valueend - value);
2036
2037 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2038 ctxt->myDoc, ctxt->node, ret, dup);
2039 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002040 } else
2041#endif /* LIBXML_VALID_ENABLED */
2042 if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
Daniel Veillarde57ec792003-09-10 10:50:59 +00002043 (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
2044 ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
2045 /*
2046 * when validating, the ID registration is done at the attribute
2047 * validation level. Otherwise we have to do specific handling here.
2048 */
Daniel Veillard54f9a4f2005-09-03 13:28:24 +00002049 if ((prefix == ctxt->str_xml) &&
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00002050 (localname[0] == 'i') && (localname[1] == 'd') &&
2051 (localname[2] == 0)) {
2052 /*
2053 * Add the xml:id value
2054 *
2055 * Open issue: normalization of the value.
2056 */
2057 if (dup == NULL)
2058 dup = xmlStrndup(value, valueend - value);
William M. Brack5ef2f812004-05-23 23:56:47 +00002059#ifdef LIBXML_VALID_ENABLED
Daniel Veillard68cb4b22004-04-18 20:55:39 +00002060 if (xmlValidateNCName(dup, 1) != 0) {
2061 xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
2062 "xml:id : attribute value %s is not an NCName\n",
2063 (const char *) dup, NULL);
2064 }
William M. Brack3f147372004-05-22 01:09:26 +00002065#endif
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00002066 xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
Daniel Veillard54f9a4f2005-09-03 13:28:24 +00002067 } else if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) {
2068 /* might be worth duplicate entry points and not copy */
2069 if (dup == NULL)
2070 dup = xmlStrndup(value, valueend - value);
2071 xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
2072 } else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) {
2073 if (dup == NULL)
2074 dup = xmlStrndup(value, valueend - value);
2075 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, dup, ret);
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00002076 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002077 }
2078 if (dup != NULL)
2079 xmlFree(dup);
2080}
2081
2082/**
2083 * xmlSAX2StartElementNs:
2084 * @ctx: the user data (XML parser context)
2085 * @localname: the local name of the element
2086 * @prefix: the element namespace prefix if available
2087 * @URI: the element namespace name if available
2088 * @nb_namespaces: number of namespace definitions on that node
2089 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
2090 * @nb_attributes: the number of attributes on that node
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00002091 * @nb_defaulted: the number of defaulted attributes.
Daniel Veillarde57ec792003-09-10 10:50:59 +00002092 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
2093 * attribute values.
2094 *
2095 * SAX2 callback when an element start has been detected by the parser.
2096 * It provides the namespace informations for the element, as well as
2097 * the new namespace declarations on the element.
2098 */
2099void
2100xmlSAX2StartElementNs(void *ctx,
2101 const xmlChar *localname,
2102 const xmlChar *prefix,
2103 const xmlChar *URI,
2104 int nb_namespaces,
2105 const xmlChar **namespaces,
2106 int nb_attributes,
2107 int nb_defaulted,
2108 const xmlChar **attributes)
2109{
2110 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2111 xmlNodePtr ret;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002112 xmlNodePtr parent;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002113 xmlNsPtr last = NULL, ns;
2114 const xmlChar *uri, *pref;
2115 int i, j;
2116
Daniel Veillard34099b42004-11-04 17:34:35 +00002117 if (ctx == NULL) return;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002118 parent = ctxt->node;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002119 /*
2120 * First check on validity:
2121 */
2122 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
2123 ((ctxt->myDoc->intSubset == NULL) ||
2124 ((ctxt->myDoc->intSubset->notations == NULL) &&
2125 (ctxt->myDoc->intSubset->elements == NULL) &&
2126 (ctxt->myDoc->intSubset->attributes == NULL) &&
2127 (ctxt->myDoc->intSubset->entities == NULL)))) {
Daniel Veillardf88d8cf2003-12-08 10:25:02 +00002128 xmlErrValid(ctxt, XML_ERR_NO_DTD,
2129 "Validation failed: no DTD found !", NULL, NULL);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002130 ctxt->validate = 0;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002131 }
2132
Daniel Veillard8a44e592003-09-15 14:50:06 +00002133 /*
2134 * allocate the node
2135 */
2136 if (ctxt->freeElems != NULL) {
2137 ret = ctxt->freeElems;
2138 ctxt->freeElems = ret->next;
Daniel Veillard19895052003-09-17 13:59:32 +00002139 ctxt->freeElemsNr--;
Daniel Veillard8a44e592003-09-15 14:50:06 +00002140 memset(ret, 0, sizeof(xmlNode));
2141 ret->type = XML_ELEMENT_NODE;
2142
2143 if (ctxt->dictNames)
2144 ret->name = localname;
William M. Brack9f797ab2004-07-28 07:40:12 +00002145 else {
Daniel Veillard8a44e592003-09-15 14:50:06 +00002146 ret->name = xmlStrdup(localname);
William M. Brack9f797ab2004-07-28 07:40:12 +00002147 if (ret->name == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002148 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
William M. Brack9f797ab2004-07-28 07:40:12 +00002149 return;
2150 }
2151 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00002152 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2153 xmlRegisterNodeDefaultValue(ret);
2154 } else {
2155 if (ctxt->dictNames)
2156 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
2157 (xmlChar *) localname, NULL);
2158 else
2159 ret = xmlNewDocNode(ctxt->myDoc, NULL, localname, NULL);
2160 if (ret == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002161 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
Daniel Veillard8a44e592003-09-15 14:50:06 +00002162 return;
2163 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002164 }
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002165 if (ctxt->linenumbers) {
Daniel Veillard3e35f8e2003-10-21 00:05:38 +00002166 if (ctxt->input != NULL) {
2167 if (ctxt->input->line < 65535)
2168 ret->line = (short) ctxt->input->line;
2169 else
2170 ret->line = 65535;
2171 }
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002172 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00002173
Daniel Veillard29b17482004-08-16 00:39:03 +00002174 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
Daniel Veillarde57ec792003-09-10 10:50:59 +00002175 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002176 }
2177 /*
2178 * Build the namespace list
2179 */
2180 for (i = 0,j = 0;j < nb_namespaces;j++) {
2181 pref = namespaces[i++];
2182 uri = namespaces[i++];
2183 ns = xmlNewNs(NULL, uri, pref);
2184 if (ns != NULL) {
2185 if (last == NULL) {
2186 ret->nsDef = last = ns;
2187 } else {
2188 last->next = ns;
2189 last = ns;
2190 }
2191 if ((URI != NULL) && (prefix == pref))
2192 ret->ns = ns;
2193 } else {
William M. Brack42331a92004-07-29 07:07:16 +00002194 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
Daniel Veillarde57ec792003-09-10 10:50:59 +00002195 return;
2196 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002197#ifdef LIBXML_VALID_ENABLED
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002198 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
2199 ctxt->myDoc && ctxt->myDoc->intSubset) {
2200 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
2201 ret, prefix, ns, uri);
2202 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002203#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002204 }
2205 ctxt->nodemem = -1;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002206
2207 /*
2208 * We are parsing a new node.
2209 */
2210 nodePush(ctxt, ret);
2211
2212 /*
2213 * Link the child element
2214 */
2215 if (parent != NULL) {
2216 if (parent->type == XML_ELEMENT_NODE) {
2217 xmlAddChild(parent, ret);
2218 } else {
2219 xmlAddSibling(parent, ret);
2220 }
2221 }
2222
2223 /*
2224 * Insert the defaulted attributes from the DTD only if requested:
2225 */
2226 if ((nb_defaulted != 0) &&
2227 ((ctxt->loadsubset & XML_COMPLETE_ATTRS) == 0))
2228 nb_attributes -= nb_defaulted;
2229
2230 /*
2231 * Search the namespace if it wasn't already found
William M. Brackbf5cf212004-08-31 06:47:17 +00002232 * Note that, if prefix is NULL, this searches for the default Ns
Daniel Veillarde57ec792003-09-10 10:50:59 +00002233 */
2234 if ((URI != NULL) && (ret->ns == NULL)) {
William M. Brackbf5cf212004-08-31 06:47:17 +00002235 ret->ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002236 if (ret->ns == NULL) {
2237 ns = xmlNewNs(ret, NULL, prefix);
William M. Brack9f797ab2004-07-28 07:40:12 +00002238 if (ns == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002239 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
William M. Brack9f797ab2004-07-28 07:40:12 +00002240 return;
2241 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002242 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
2243 ctxt->sax->warning(ctxt->userData,
2244 "Namespace prefix %s was not found\n", prefix);
2245 }
2246 }
2247
2248 /*
2249 * process all the other attributes
2250 */
2251 if (nb_attributes > 0) {
2252 for (j = 0,i = 0;i < nb_attributes;i++,j+=5) {
2253 xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1],
2254 attributes[j+3], attributes[j+4]);
2255 }
2256 }
2257
Daniel Veillard4432df22003-09-28 18:58:27 +00002258#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002259 /*
2260 * If it's the Document root, finish the DTD validation and
2261 * check the document root element for validity
2262 */
Daniel Veillardeff45a92004-10-29 12:10:55 +00002263 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == XML_CTXT_FINISH_DTD_0)) {
Daniel Veillarde57ec792003-09-10 10:50:59 +00002264 int chk;
2265
2266 chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
2267 if (chk <= 0)
2268 ctxt->valid = 0;
2269 if (chk < 0)
2270 ctxt->wellFormed = 0;
2271 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
Daniel Veillardeff45a92004-10-29 12:10:55 +00002272 ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_1;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002273 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002274#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002275}
2276
2277/**
2278 * xmlSAX2EndElementNs:
2279 * @ctx: the user data (XML parser context)
2280 * @localname: the local name of the element
2281 * @prefix: the element namespace prefix if available
2282 * @URI: the element namespace name if available
2283 *
2284 * SAX2 callback when an element end has been detected by the parser.
2285 * It provides the namespace informations for the element.
2286 */
2287void
2288xmlSAX2EndElementNs(void *ctx,
2289 const xmlChar * localname ATTRIBUTE_UNUSED,
2290 const xmlChar * prefix ATTRIBUTE_UNUSED,
2291 const xmlChar * URI ATTRIBUTE_UNUSED)
2292{
2293 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2294 xmlParserNodeInfo node_info;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002295 xmlNodePtr cur;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002296
Daniel Veillard34099b42004-11-04 17:34:35 +00002297 if (ctx == NULL) return;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002298 cur = ctxt->node;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002299 /* Capture end position and add node */
2300 if ((ctxt->record_info) && (cur != NULL)) {
2301 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
2302 node_info.end_line = ctxt->input->line;
2303 node_info.node = cur;
2304 xmlParserAddNodeInfo(ctxt, &node_info);
2305 }
2306 ctxt->nodemem = -1;
2307
Daniel Veillard4432df22003-09-28 18:58:27 +00002308#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002309 if (ctxt->validate && ctxt->wellFormed &&
2310 ctxt->myDoc && ctxt->myDoc->intSubset)
2311 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, cur);
Daniel Veillard4432df22003-09-28 18:58:27 +00002312#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002313
2314 /*
2315 * end of parsing of this node.
2316 */
2317 nodePop(ctxt);
2318}
2319
Daniel Veillard1af9a412003-08-20 22:54:39 +00002320/**
2321 * xmlSAX2Reference:
2322 * @ctx: the user data (XML parser context)
2323 * @name: The entity name
2324 *
2325 * called when an entity xmlSAX2Reference is detected.
2326 */
2327void
2328xmlSAX2Reference(void *ctx, const xmlChar *name)
2329{
2330 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2331 xmlNodePtr ret;
2332
Daniel Veillard34099b42004-11-04 17:34:35 +00002333 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002334#ifdef DEBUG_SAX
2335 xmlGenericError(xmlGenericErrorContext,
2336 "SAX.xmlSAX2Reference(%s)\n", name);
2337#endif
2338 if (name[0] == '#')
2339 ret = xmlNewCharRef(ctxt->myDoc, name);
2340 else
2341 ret = xmlNewReference(ctxt->myDoc, name);
2342#ifdef DEBUG_SAX_TREE
2343 xmlGenericError(xmlGenericErrorContext,
2344 "add xmlSAX2Reference %s to %s \n", name, ctxt->node->name);
2345#endif
2346 xmlAddChild(ctxt->node, ret);
2347}
2348
2349/**
2350 * xmlSAX2Characters:
2351 * @ctx: the user data (XML parser context)
2352 * @ch: a xmlChar string
2353 * @len: the number of xmlChar
2354 *
2355 * receiving some chars from the parser.
2356 */
2357void
2358xmlSAX2Characters(void *ctx, const xmlChar *ch, int len)
2359{
2360 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2361 xmlNodePtr lastChild;
2362
Daniel Veillard34099b42004-11-04 17:34:35 +00002363 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002364#ifdef DEBUG_SAX
2365 xmlGenericError(xmlGenericErrorContext,
2366 "SAX.xmlSAX2Characters(%.30s, %d)\n", ch, len);
2367#endif
2368 /*
2369 * Handle the data if any. If there is no child
2370 * add it as content, otherwise if the last child is text,
2371 * concatenate it, else create a new node of type text.
2372 */
2373
2374 if (ctxt->node == NULL) {
2375#ifdef DEBUG_SAX_TREE
2376 xmlGenericError(xmlGenericErrorContext,
2377 "add chars: ctxt->node == NULL !\n");
2378#endif
2379 return;
2380 }
Daniel Veillard19895052003-09-17 13:59:32 +00002381 lastChild = ctxt->node->last;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002382#ifdef DEBUG_SAX_TREE
2383 xmlGenericError(xmlGenericErrorContext,
2384 "add chars to %s \n", ctxt->node->name);
2385#endif
2386
2387 /*
2388 * Here we needed an accelerator mechanism in case of very large
2389 * elements. Use an attribute in the structure !!!
2390 */
2391 if (lastChild == NULL) {
Daniel Veillard19895052003-09-17 13:59:32 +00002392 lastChild = xmlSAX2TextNode(ctxt, ch, len);
2393 if (lastChild != NULL) {
2394 ctxt->node->children = lastChild;
2395 ctxt->node->last = lastChild;
2396 lastChild->parent = ctxt->node;
2397 lastChild->doc = ctxt->node->doc;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002398 ctxt->nodelen = len;
2399 ctxt->nodemem = len + 1;
William M. Bracka3215c72004-07-31 16:24:01 +00002400 } else {
2401 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
2402 return;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002403 }
2404 } else {
2405 int coalesceText = (lastChild != NULL) &&
2406 (lastChild->type == XML_TEXT_NODE) &&
2407 (lastChild->name == xmlStringText);
2408 if ((coalesceText) && (ctxt->nodemem != 0)) {
2409 /*
2410 * The whole point of maintaining nodelen and nodemem,
2411 * xmlTextConcat is too costly, i.e. compute length,
2412 * reallocate a new buffer, move data, append ch. Here
2413 * We try to minimaze realloc() uses and avoid copying
2414 * and recomputing length over and over.
2415 */
Daniel Veillard8874b942005-08-25 13:19:21 +00002416 if (lastChild->content == (xmlChar *)&(lastChild->properties)) {
2417 lastChild->content = xmlStrdup(lastChild->content);
2418 lastChild->properties = NULL;
2419 } else if ((ctxt->nodemem == ctxt->nodelen + 1) &&
2420 (xmlDictOwns(ctxt->dict, lastChild->content))) {
Daniel Veillard2b0f8792003-10-10 19:36:36 +00002421 lastChild->content = xmlStrdup(lastChild->content);
2422 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00002423 if (ctxt->nodelen + len >= ctxt->nodemem) {
2424 xmlChar *newbuf;
2425 int size;
2426
2427 size = ctxt->nodemem + len;
2428 size *= 2;
2429 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
2430 if (newbuf == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002431 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
Daniel Veillard1af9a412003-08-20 22:54:39 +00002432 return;
2433 }
2434 ctxt->nodemem = size;
2435 lastChild->content = newbuf;
2436 }
2437 memcpy(&lastChild->content[ctxt->nodelen], ch, len);
2438 ctxt->nodelen += len;
2439 lastChild->content[ctxt->nodelen] = 0;
2440 } else if (coalesceText) {
2441 if (xmlTextConcat(lastChild, ch, len)) {
William M. Brack42331a92004-07-29 07:07:16 +00002442 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
Daniel Veillard1af9a412003-08-20 22:54:39 +00002443 }
2444 if (ctxt->node->children != NULL) {
2445 ctxt->nodelen = xmlStrlen(lastChild->content);
2446 ctxt->nodemem = ctxt->nodelen + 1;
2447 }
2448 } else {
2449 /* Mixed content, first time */
Daniel Veillard19895052003-09-17 13:59:32 +00002450 lastChild = xmlSAX2TextNode(ctxt, ch, len);
2451 if (lastChild != NULL) {
Daniel Veillard1af9a412003-08-20 22:54:39 +00002452 xmlAddChild(ctxt->node, lastChild);
2453 if (ctxt->node->children != NULL) {
2454 ctxt->nodelen = len;
2455 ctxt->nodemem = len + 1;
2456 }
2457 }
2458 }
2459 }
2460}
2461
2462/**
2463 * xmlSAX2IgnorableWhitespace:
2464 * @ctx: the user data (XML parser context)
2465 * @ch: a xmlChar string
2466 * @len: the number of xmlChar
2467 *
2468 * receiving some ignorable whitespaces from the parser.
2469 * UNUSED: by default the DOM building will use xmlSAX2Characters
2470 */
2471void
2472xmlSAX2IgnorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
2473{
2474 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
2475#ifdef DEBUG_SAX
2476 xmlGenericError(xmlGenericErrorContext,
2477 "SAX.xmlSAX2IgnorableWhitespace(%.30s, %d)\n", ch, len);
2478#endif
2479}
2480
2481/**
2482 * xmlSAX2ProcessingInstruction:
2483 * @ctx: the user data (XML parser context)
2484 * @target: the target name
2485 * @data: the PI data's
2486 *
2487 * A processing instruction has been parsed.
2488 */
2489void
2490xmlSAX2ProcessingInstruction(void *ctx, const xmlChar *target,
2491 const xmlChar *data)
2492{
2493 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2494 xmlNodePtr ret;
Daniel Veillard6128c012004-11-08 17:16:15 +00002495 xmlNodePtr parent;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002496
Daniel Veillard34099b42004-11-04 17:34:35 +00002497 if (ctx == NULL) return;
Daniel Veillard6128c012004-11-08 17:16:15 +00002498 parent = ctxt->node;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002499#ifdef DEBUG_SAX
2500 xmlGenericError(xmlGenericErrorContext,
2501 "SAX.xmlSAX2ProcessingInstruction(%s, %s)\n", target, data);
2502#endif
2503
Daniel Veillard03a53c32004-10-26 16:06:51 +00002504 ret = xmlNewDocPI(ctxt->myDoc, target, data);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002505 if (ret == NULL) return;
2506 parent = ctxt->node;
2507
Daniel Veillard73da77e2005-08-24 14:05:37 +00002508 if (ctxt->linenumbers) {
2509 if (ctxt->input != NULL) {
2510 if (ctxt->input->line < 65535)
2511 ret->line = (short) ctxt->input->line;
2512 else
2513 ret->line = 65535;
2514 }
2515 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00002516 if (ctxt->inSubset == 1) {
2517 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2518 return;
2519 } else if (ctxt->inSubset == 2) {
2520 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2521 return;
2522 }
2523 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
2524#ifdef DEBUG_SAX_TREE
2525 xmlGenericError(xmlGenericErrorContext,
2526 "Setting PI %s as root\n", target);
2527#endif
2528 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2529 return;
2530 }
2531 if (parent->type == XML_ELEMENT_NODE) {
2532#ifdef DEBUG_SAX_TREE
2533 xmlGenericError(xmlGenericErrorContext,
2534 "adding PI %s child to %s\n", target, parent->name);
2535#endif
2536 xmlAddChild(parent, ret);
2537 } else {
2538#ifdef DEBUG_SAX_TREE
2539 xmlGenericError(xmlGenericErrorContext,
2540 "adding PI %s sibling to ", target);
2541 xmlDebugDumpOneNode(stderr, parent, 0);
2542#endif
2543 xmlAddSibling(parent, ret);
2544 }
2545}
2546
2547/**
2548 * xmlSAX2Comment:
2549 * @ctx: the user data (XML parser context)
2550 * @value: the xmlSAX2Comment content
2551 *
2552 * A xmlSAX2Comment has been parsed.
2553 */
2554void
2555xmlSAX2Comment(void *ctx, const xmlChar *value)
2556{
2557 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2558 xmlNodePtr ret;
Daniel Veillard34099b42004-11-04 17:34:35 +00002559 xmlNodePtr parent;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002560
Daniel Veillard34099b42004-11-04 17:34:35 +00002561 if (ctx == NULL) return;
2562 parent = ctxt->node;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002563#ifdef DEBUG_SAX
2564 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2Comment(%s)\n", value);
2565#endif
2566 ret = xmlNewDocComment(ctxt->myDoc, value);
2567 if (ret == NULL) return;
Daniel Veillard73da77e2005-08-24 14:05:37 +00002568 if (ctxt->linenumbers) {
2569 if (ctxt->input != NULL) {
2570 if (ctxt->input->line < 65535)
2571 ret->line = (short) ctxt->input->line;
2572 else
2573 ret->line = 65535;
2574 }
2575 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00002576
2577 if (ctxt->inSubset == 1) {
2578 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2579 return;
2580 } else if (ctxt->inSubset == 2) {
2581 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2582 return;
2583 }
2584 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
2585#ifdef DEBUG_SAX_TREE
2586 xmlGenericError(xmlGenericErrorContext,
2587 "Setting xmlSAX2Comment as root\n");
2588#endif
2589 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2590 return;
2591 }
2592 if (parent->type == XML_ELEMENT_NODE) {
2593#ifdef DEBUG_SAX_TREE
2594 xmlGenericError(xmlGenericErrorContext,
2595 "adding xmlSAX2Comment child to %s\n", parent->name);
2596#endif
2597 xmlAddChild(parent, ret);
2598 } else {
2599#ifdef DEBUG_SAX_TREE
2600 xmlGenericError(xmlGenericErrorContext,
2601 "adding xmlSAX2Comment sibling to ");
2602 xmlDebugDumpOneNode(stderr, parent, 0);
2603#endif
2604 xmlAddSibling(parent, ret);
2605 }
2606}
2607
2608/**
2609 * xmlSAX2CDataBlock:
2610 * @ctx: the user data (XML parser context)
2611 * @value: The pcdata content
2612 * @len: the block length
2613 *
2614 * called when a pcdata block has been parsed
2615 */
2616void
2617xmlSAX2CDataBlock(void *ctx, const xmlChar *value, int len)
2618{
2619 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2620 xmlNodePtr ret, lastChild;
2621
Daniel Veillard34099b42004-11-04 17:34:35 +00002622 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002623#ifdef DEBUG_SAX
2624 xmlGenericError(xmlGenericErrorContext,
2625 "SAX.pcdata(%.10s, %d)\n", value, len);
2626#endif
2627 lastChild = xmlGetLastChild(ctxt->node);
2628#ifdef DEBUG_SAX_TREE
2629 xmlGenericError(xmlGenericErrorContext,
2630 "add chars to %s \n", ctxt->node->name);
2631#endif
2632 if ((lastChild != NULL) &&
2633 (lastChild->type == XML_CDATA_SECTION_NODE)) {
2634 xmlTextConcat(lastChild, value, len);
2635 } else {
2636 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
2637 xmlAddChild(ctxt->node, ret);
2638 }
2639}
2640
Daniel Veillard62998c02003-09-15 12:56:36 +00002641static int xmlSAX2DefaultVersionValue = 2;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002642
Daniel Veillard81273902003-09-30 00:43:48 +00002643#ifdef LIBXML_SAX1_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002644/**
2645 * xmlSAXDefaultVersion:
2646 * @version: the version, 1 or 2
2647 *
2648 * Set the default version of SAX used globally by the library.
William M. Brack96d2eff2004-06-30 11:48:47 +00002649 * By default, during initialization the default is set to 2.
2650 * Note that it is generally a better coding style to use
2651 * xmlSAXVersion() to set up the version explicitly for a given
2652 * parsing context.
Daniel Veillarde57ec792003-09-10 10:50:59 +00002653 *
2654 * Returns the previous value in case of success and -1 in case of error.
2655 */
2656int
2657xmlSAXDefaultVersion(int version)
2658{
2659 int ret = xmlSAX2DefaultVersionValue;
2660
2661 if ((version != 1) && (version != 2))
2662 return(-1);
2663 xmlSAX2DefaultVersionValue = version;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002664 return(ret);
2665}
Daniel Veillard81273902003-09-30 00:43:48 +00002666#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002667
2668/**
2669 * xmlSAXVersion:
2670 * @hdlr: the SAX handler
2671 * @version: the version, 1 or 2
2672 *
2673 * Initialize the default XML SAX handler according to the version
2674 *
2675 * Returns 0 in case of success and -1 in case of error.
2676 */
2677int
2678xmlSAXVersion(xmlSAXHandler *hdlr, int version)
2679{
2680 if (hdlr == NULL) return(-1);
Daniel Veillard81273902003-09-30 00:43:48 +00002681 if (version == 2) {
Daniel Veillarde57ec792003-09-10 10:50:59 +00002682 hdlr->startElement = NULL;
2683 hdlr->endElement = NULL;
2684 hdlr->startElementNs = xmlSAX2StartElementNs;
2685 hdlr->endElementNs = xmlSAX2EndElementNs;
Daniel Veillardffbbed42003-10-10 14:46:54 +00002686 hdlr->serror = NULL;
Daniel Veillard092643b2003-09-25 14:29:29 +00002687 hdlr->initialized = XML_SAX2_MAGIC;
Daniel Veillard81273902003-09-30 00:43:48 +00002688#ifdef LIBXML_SAX1_ENABLED
2689 } else if (version == 1) {
2690 hdlr->startElement = xmlSAX2StartElement;
2691 hdlr->endElement = xmlSAX2EndElement;
2692 hdlr->initialized = 1;
2693#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002694 } else
2695 return(-1);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002696 hdlr->internalSubset = xmlSAX2InternalSubset;
2697 hdlr->externalSubset = xmlSAX2ExternalSubset;
2698 hdlr->isStandalone = xmlSAX2IsStandalone;
2699 hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
2700 hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
2701 hdlr->resolveEntity = xmlSAX2ResolveEntity;
2702 hdlr->getEntity = xmlSAX2GetEntity;
2703 hdlr->getParameterEntity = xmlSAX2GetParameterEntity;
2704 hdlr->entityDecl = xmlSAX2EntityDecl;
2705 hdlr->attributeDecl = xmlSAX2AttributeDecl;
2706 hdlr->elementDecl = xmlSAX2ElementDecl;
2707 hdlr->notationDecl = xmlSAX2NotationDecl;
2708 hdlr->unparsedEntityDecl = xmlSAX2UnparsedEntityDecl;
2709 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2710 hdlr->startDocument = xmlSAX2StartDocument;
2711 hdlr->endDocument = xmlSAX2EndDocument;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002712 hdlr->reference = xmlSAX2Reference;
2713 hdlr->characters = xmlSAX2Characters;
2714 hdlr->cdataBlock = xmlSAX2CDataBlock;
2715 hdlr->ignorableWhitespace = xmlSAX2Characters;
2716 hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
2717 hdlr->comment = xmlSAX2Comment;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002718 hdlr->warning = xmlParserWarning;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002719 hdlr->error = xmlParserError;
2720 hdlr->fatalError = xmlParserError;
2721
Daniel Veillarde57ec792003-09-10 10:50:59 +00002722 return(0);
2723}
2724
2725/**
2726 * xmlSAX2InitDefaultSAXHandler:
2727 * @hdlr: the SAX handler
2728 * @warning: flag if non-zero sets the handler warning procedure
2729 *
2730 * Initialize the default XML SAX2 handler
2731 */
2732void
2733xmlSAX2InitDefaultSAXHandler(xmlSAXHandler *hdlr, int warning)
2734{
2735 if ((hdlr == NULL) || (hdlr->initialized != 0))
2736 return;
2737
2738 xmlSAXVersion(hdlr, xmlSAX2DefaultVersionValue);
2739 if (warning == 0)
2740 hdlr->warning = NULL;
2741 else
2742 hdlr->warning = xmlParserWarning;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002743}
2744
2745/**
2746 * xmlDefaultSAXHandlerInit:
2747 *
2748 * Initialize the default SAX2 handler
2749 */
2750void
2751xmlDefaultSAXHandlerInit(void)
2752{
Daniel Veillard81273902003-09-30 00:43:48 +00002753#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard092643b2003-09-25 14:29:29 +00002754 xmlSAXVersion((xmlSAXHandlerPtr) &xmlDefaultSAXHandler, 1);
Daniel Veillard81273902003-09-30 00:43:48 +00002755#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00002756}
2757
2758#ifdef LIBXML_HTML_ENABLED
2759
2760/**
2761 * xmlSAX2InitHtmlDefaultSAXHandler:
2762 * @hdlr: the SAX handler
2763 *
2764 * Initialize the default HTML SAX2 handler
2765 */
2766void
2767xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr)
2768{
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002769 if ((hdlr == NULL) || (hdlr->initialized != 0))
Daniel Veillard1af9a412003-08-20 22:54:39 +00002770 return;
2771
2772 hdlr->internalSubset = xmlSAX2InternalSubset;
2773 hdlr->externalSubset = NULL;
2774 hdlr->isStandalone = NULL;
2775 hdlr->hasInternalSubset = NULL;
2776 hdlr->hasExternalSubset = NULL;
2777 hdlr->resolveEntity = NULL;
2778 hdlr->getEntity = xmlSAX2GetEntity;
2779 hdlr->getParameterEntity = NULL;
2780 hdlr->entityDecl = NULL;
2781 hdlr->attributeDecl = NULL;
2782 hdlr->elementDecl = NULL;
2783 hdlr->notationDecl = NULL;
2784 hdlr->unparsedEntityDecl = NULL;
2785 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2786 hdlr->startDocument = xmlSAX2StartDocument;
2787 hdlr->endDocument = xmlSAX2EndDocument;
2788 hdlr->startElement = xmlSAX2StartElement;
2789 hdlr->endElement = xmlSAX2EndElement;
2790 hdlr->reference = NULL;
2791 hdlr->characters = xmlSAX2Characters;
2792 hdlr->cdataBlock = xmlSAX2CDataBlock;
2793 hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
Daniel Veillardfc484dd2004-10-22 14:34:23 +00002794 hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002795 hdlr->comment = xmlSAX2Comment;
2796 hdlr->warning = xmlParserWarning;
2797 hdlr->error = xmlParserError;
2798 hdlr->fatalError = xmlParserError;
2799
Daniel Veillard092643b2003-09-25 14:29:29 +00002800 hdlr->initialized = 1;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002801}
2802
2803/**
2804 * htmlDefaultSAXHandlerInit:
2805 *
2806 * Initialize the default SAX handler
2807 */
2808void
2809htmlDefaultSAXHandlerInit(void)
2810{
Daniel Veillard092643b2003-09-25 14:29:29 +00002811 xmlSAX2InitHtmlDefaultSAXHandler((xmlSAXHandlerPtr) &htmlDefaultSAXHandler);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002812}
2813
2814#endif /* LIBXML_HTML_ENABLED */
2815
2816#ifdef LIBXML_DOCB_ENABLED
2817
2818/**
2819 * xmlSAX2InitDocbDefaultSAXHandler:
2820 * @hdlr: the SAX handler
2821 *
2822 * Initialize the default DocBook SAX2 handler
2823 */
2824void
2825xmlSAX2InitDocbDefaultSAXHandler(xmlSAXHandler *hdlr)
2826{
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002827 if ((hdlr == NULL) || (hdlr->initialized != 0))
Daniel Veillard1af9a412003-08-20 22:54:39 +00002828 return;
2829
2830 hdlr->internalSubset = xmlSAX2InternalSubset;
2831 hdlr->externalSubset = NULL;
2832 hdlr->isStandalone = xmlSAX2IsStandalone;
2833 hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
2834 hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
2835 hdlr->resolveEntity = xmlSAX2ResolveEntity;
2836 hdlr->getEntity = xmlSAX2GetEntity;
2837 hdlr->getParameterEntity = NULL;
2838 hdlr->entityDecl = xmlSAX2EntityDecl;
2839 hdlr->attributeDecl = NULL;
2840 hdlr->elementDecl = NULL;
2841 hdlr->notationDecl = NULL;
2842 hdlr->unparsedEntityDecl = NULL;
2843 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2844 hdlr->startDocument = xmlSAX2StartDocument;
2845 hdlr->endDocument = xmlSAX2EndDocument;
2846 hdlr->startElement = xmlSAX2StartElement;
2847 hdlr->endElement = xmlSAX2EndElement;
2848 hdlr->reference = xmlSAX2Reference;
2849 hdlr->characters = xmlSAX2Characters;
2850 hdlr->cdataBlock = NULL;
2851 hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
2852 hdlr->processingInstruction = NULL;
2853 hdlr->comment = xmlSAX2Comment;
2854 hdlr->warning = xmlParserWarning;
2855 hdlr->error = xmlParserError;
2856 hdlr->fatalError = xmlParserError;
2857
Daniel Veillardffbbed42003-10-10 14:46:54 +00002858 hdlr->initialized = 1;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002859}
2860
2861/**
2862 * docbDefaultSAXHandlerInit:
2863 *
2864 * Initialize the default SAX handler
2865 */
2866void
2867docbDefaultSAXHandlerInit(void)
2868{
Daniel Veillard092643b2003-09-25 14:29:29 +00002869 xmlSAX2InitDocbDefaultSAXHandler((xmlSAXHandlerPtr) &docbDefaultSAXHandler);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002870}
2871
2872#endif /* LIBXML_DOCB_ENABLED */
Daniel Veillard5d4644e2005-04-01 13:11:58 +00002873#define bottom_SAX2
2874#include "elfgcchack.h"