blob: 3a674c72289ec31b43075e2af75ca5ebf78a5bea [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
47/**
Daniel Veillardf88d8cf2003-12-08 10:25:02 +000048 * xmlValidError:
49 * @ctxt: an XML validation parser context
50 * @error: the error number
51 * @msg: the error message
52 * @str1: extra data
53 * @str2: extra data
54 *
55 * Handle a validation error
56 */
57static void
58xmlErrValid(xmlParserCtxtPtr ctxt, xmlParserErrors error,
59 const char *msg, const char *str1, const char *str2)
60{
61 xmlStructuredErrorFunc schannel = NULL;
62
63 if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
64 (ctxt->instate == XML_PARSER_EOF))
65 return;
66 ctxt->errNo = error;
67 if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
68 schannel = ctxt->sax->serror;
69 __xmlRaiseError(schannel,
70 ctxt->vctxt.error, ctxt->vctxt.userData,
71 ctxt, NULL, XML_FROM_DTD, error,
72 XML_ERR_ERROR, NULL, 0, (const char *) str1,
73 (const char *) str2, NULL, 0, 0,
74 msg, (const char *) str1, (const char *) str2);
75 ctxt->valid = 0;
76}
77
78/**
Daniel Veillard1af9a412003-08-20 22:54:39 +000079 * xmlSAX2GetPublicId:
80 * @ctx: the user data (XML parser context)
81 *
82 * Provides the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
83 *
84 * Returns a xmlChar *
85 */
86const xmlChar *
87xmlSAX2GetPublicId(void *ctx ATTRIBUTE_UNUSED)
88{
89 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
90 return(NULL);
91}
92
93/**
94 * xmlSAX2GetSystemId:
95 * @ctx: the user data (XML parser context)
96 *
97 * Provides the system ID, basically URL or filename e.g.
98 * http://www.sgmlsource.com/dtds/memo.dtd
99 *
100 * Returns a xmlChar *
101 */
102const xmlChar *
103xmlSAX2GetSystemId(void *ctx)
104{
105 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
106 return((const xmlChar *) ctxt->input->filename);
107}
108
109/**
110 * xmlSAX2GetLineNumber:
111 * @ctx: the user data (XML parser context)
112 *
113 * Provide the line number of the current parsing point.
114 *
115 * Returns an int
116 */
117int
118xmlSAX2GetLineNumber(void *ctx)
119{
120 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
121 return(ctxt->input->line);
122}
123
124/**
125 * xmlSAX2GetColumnNumber:
126 * @ctx: the user data (XML parser context)
127 *
128 * Provide the column number of the current parsing point.
129 *
130 * Returns an int
131 */
132int
133xmlSAX2GetColumnNumber(void *ctx)
134{
135 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
136 return(ctxt->input->col);
137}
138
139/**
140 * xmlSAX2IsStandalone:
141 * @ctx: the user data (XML parser context)
142 *
143 * Is this document tagged standalone ?
144 *
145 * Returns 1 if true
146 */
147int
148xmlSAX2IsStandalone(void *ctx)
149{
150 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
151 return(ctxt->myDoc->standalone == 1);
152}
153
154/**
155 * xmlSAX2HasInternalSubset:
156 * @ctx: the user data (XML parser context)
157 *
158 * Does this document has an internal subset
159 *
160 * Returns 1 if true
161 */
162int
163xmlSAX2HasInternalSubset(void *ctx)
164{
165 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
166 return(ctxt->myDoc->intSubset != NULL);
167}
168
169/**
170 * xmlSAX2HasExternalSubset:
171 * @ctx: the user data (XML parser context)
172 *
173 * Does this document has an external subset
174 *
175 * Returns 1 if true
176 */
177int
178xmlSAX2HasExternalSubset(void *ctx)
179{
180 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
181 return(ctxt->myDoc->extSubset != NULL);
182}
183
184/**
185 * xmlSAX2InternalSubset:
186 * @ctx: the user data (XML parser context)
187 * @name: the root element name
188 * @ExternalID: the external ID
189 * @SystemID: the SYSTEM ID (e.g. filename or URL)
190 *
191 * Callback on internal subset declaration.
192 */
193void
194xmlSAX2InternalSubset(void *ctx, const xmlChar *name,
195 const xmlChar *ExternalID, const xmlChar *SystemID)
196{
197 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
198 xmlDtdPtr dtd;
199#ifdef DEBUG_SAX
200 xmlGenericError(xmlGenericErrorContext,
201 "SAX.xmlSAX2InternalSubset(%s, %s, %s)\n",
202 name, ExternalID, SystemID);
203#endif
204
205 if (ctxt->myDoc == NULL)
206 return;
207 dtd = xmlGetIntSubset(ctxt->myDoc);
208 if (dtd != NULL) {
209 if (ctxt->html)
210 return;
211 xmlUnlinkNode((xmlNodePtr) dtd);
212 xmlFreeDtd(dtd);
213 ctxt->myDoc->intSubset = NULL;
214 }
215 ctxt->myDoc->intSubset =
216 xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
217}
218
219/**
220 * xmlSAX2ExternalSubset:
221 * @ctx: the user data (XML parser context)
222 * @name: the root element name
223 * @ExternalID: the external ID
224 * @SystemID: the SYSTEM ID (e.g. filename or URL)
225 *
226 * Callback on external subset declaration.
227 */
228void
229xmlSAX2ExternalSubset(void *ctx, const xmlChar *name,
230 const xmlChar *ExternalID, const xmlChar *SystemID)
231{
232 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
233#ifdef DEBUG_SAX
234 xmlGenericError(xmlGenericErrorContext,
235 "SAX.xmlSAX2ExternalSubset(%s, %s, %s)\n",
236 name, ExternalID, SystemID);
237#endif
238 if (((ExternalID != NULL) || (SystemID != NULL)) &&
239 (((ctxt->validate) || (ctxt->loadsubset != 0)) &&
240 (ctxt->wellFormed && ctxt->myDoc))) {
241 /*
242 * Try to fetch and parse the external subset.
243 */
244 xmlParserInputPtr oldinput;
245 int oldinputNr;
246 int oldinputMax;
247 xmlParserInputPtr *oldinputTab;
248 xmlParserInputPtr input = NULL;
249 xmlCharEncoding enc;
250 int oldcharset;
251
252 /*
253 * Ask the Entity resolver to load the damn thing
254 */
255 if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
256 input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
257 SystemID);
258 if (input == NULL) {
259 return;
260 }
261
262 xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
263
264 /*
265 * make sure we won't destroy the main document context
266 */
267 oldinput = ctxt->input;
268 oldinputNr = ctxt->inputNr;
269 oldinputMax = ctxt->inputMax;
270 oldinputTab = ctxt->inputTab;
271 oldcharset = ctxt->charset;
272
273 ctxt->inputTab = (xmlParserInputPtr *)
274 xmlMalloc(5 * sizeof(xmlParserInputPtr));
275 if (ctxt->inputTab == NULL) {
276 ctxt->errNo = XML_ERR_NO_MEMORY;
277 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
278 ctxt->sax->error(ctxt->userData,
279 "xmlSAX2ExternalSubset: out of memory\n");
280 ctxt->errNo = XML_ERR_NO_MEMORY;
281 ctxt->instate = XML_PARSER_EOF;
282 ctxt->disableSAX = 1;
283 ctxt->input = oldinput;
284 ctxt->inputNr = oldinputNr;
285 ctxt->inputMax = oldinputMax;
286 ctxt->inputTab = oldinputTab;
287 ctxt->charset = oldcharset;
288 return;
289 }
290 ctxt->inputNr = 0;
291 ctxt->inputMax = 5;
292 ctxt->input = NULL;
293 xmlPushInput(ctxt, input);
294
295 /*
296 * On the fly encoding conversion if needed
297 */
298 if (ctxt->input->length >= 4) {
299 enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
300 xmlSwitchEncoding(ctxt, enc);
301 }
302
303 if (input->filename == NULL)
304 input->filename = (char *) xmlCanonicPath(SystemID);
305 input->line = 1;
306 input->col = 1;
307 input->base = ctxt->input->cur;
308 input->cur = ctxt->input->cur;
309 input->free = NULL;
310
311 /*
312 * let's parse that entity knowing it's an external subset.
313 */
314 xmlParseExternalSubset(ctxt, ExternalID, SystemID);
315
316 /*
317 * Free up the external entities
318 */
319
320 while (ctxt->inputNr > 1)
321 xmlPopInput(ctxt);
322 xmlFreeInputStream(ctxt->input);
323 xmlFree(ctxt->inputTab);
324
325 /*
326 * Restore the parsing context of the main entity
327 */
328 ctxt->input = oldinput;
329 ctxt->inputNr = oldinputNr;
330 ctxt->inputMax = oldinputMax;
331 ctxt->inputTab = oldinputTab;
332 ctxt->charset = oldcharset;
333 /* ctxt->wellFormed = oldwellFormed; */
334 }
335}
336
337/**
338 * xmlSAX2ResolveEntity:
339 * @ctx: the user data (XML parser context)
340 * @publicId: The public ID of the entity
341 * @systemId: The system ID of the entity
342 *
343 * The entity loader, to control the loading of external entities,
344 * the application can either:
345 * - override this xmlSAX2ResolveEntity() callback in the SAX block
346 * - or better use the xmlSetExternalEntityLoader() function to
347 * set up it's own entity resolution routine
348 *
349 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
350 */
351xmlParserInputPtr
352xmlSAX2ResolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
353{
354 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
355 xmlParserInputPtr ret;
356 xmlChar *URI;
357 const char *base = NULL;
358
359 if (ctxt->input != NULL)
360 base = ctxt->input->filename;
361 if (base == NULL)
362 base = ctxt->directory;
363
364 URI = xmlBuildURI(systemId, (const xmlChar *) base);
365
366#ifdef DEBUG_SAX
367 xmlGenericError(xmlGenericErrorContext,
368 "SAX.xmlSAX2ResolveEntity(%s, %s)\n", publicId, systemId);
369#endif
370
371 ret = xmlLoadExternalEntity((const char *) URI,
372 (const char *) publicId, ctxt);
373 if (URI != NULL)
374 xmlFree(URI);
375 return(ret);
376}
377
378/**
379 * xmlSAX2GetEntity:
380 * @ctx: the user data (XML parser context)
381 * @name: The entity name
382 *
383 * Get an entity by name
384 *
385 * Returns the xmlEntityPtr if found.
386 */
387xmlEntityPtr
388xmlSAX2GetEntity(void *ctx, const xmlChar *name)
389{
390 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
391 xmlEntityPtr ret = NULL;
392
393#ifdef DEBUG_SAX
394 xmlGenericError(xmlGenericErrorContext,
395 "SAX.xmlSAX2GetEntity(%s)\n", name);
396#endif
397
398 if (ctxt->inSubset == 0) {
399 ret = xmlGetPredefinedEntity(name);
400 if (ret != NULL)
401 return(ret);
402 }
403 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->standalone == 1)) {
404 if (ctxt->inSubset == 2) {
405 ctxt->myDoc->standalone = 0;
406 ret = xmlGetDocEntity(ctxt->myDoc, name);
407 ctxt->myDoc->standalone = 1;
408 } else {
409 ret = xmlGetDocEntity(ctxt->myDoc, name);
410 if (ret == NULL) {
411 ctxt->myDoc->standalone = 0;
412 ret = xmlGetDocEntity(ctxt->myDoc, name);
413 if (ret != NULL) {
414 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000415 ctxt->sax->error(ctxt->userData,
416 "Entity(%s) document marked standalone but requires external subset\n",
Daniel Veillard1af9a412003-08-20 22:54:39 +0000417 name);
418 ctxt->valid = 0;
419 ctxt->wellFormed = 0;
420 }
421 ctxt->myDoc->standalone = 1;
422 }
423 }
424 } else {
425 ret = xmlGetDocEntity(ctxt->myDoc, name);
426 }
427 if ((ret != NULL) &&
428 ((ctxt->validate) || (ctxt->replaceEntities)) &&
429 (ret->children == NULL) &&
430 (ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
431 int val;
432
433 /*
434 * for validation purposes we really need to fetch and
435 * parse the external entity
436 */
437 xmlNodePtr children;
438
439 val = xmlParseCtxtExternalEntity(ctxt, ret->URI,
440 ret->ExternalID, &children);
441 if (val == 0) {
442 xmlAddChildList((xmlNodePtr) ret, children);
443 } else {
William M. Brack4811ba32003-09-06 18:02:53 +0000444 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
445 ctxt->sax->error(ctxt->userData,
446 "Failure to process entity %s\n", name);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000447 ctxt->wellFormed = 0;
448 ctxt->valid = 0;
449 ctxt->validate = 0;
450 return(NULL);
451 }
452 ret->owner = 1;
453 }
454 return(ret);
455}
456
457/**
458 * xmlSAX2GetParameterEntity:
459 * @ctx: the user data (XML parser context)
460 * @name: The entity name
461 *
462 * Get a parameter entity by name
463 *
464 * Returns the xmlEntityPtr if found.
465 */
466xmlEntityPtr
467xmlSAX2GetParameterEntity(void *ctx, const xmlChar *name)
468{
469 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
470 xmlEntityPtr ret;
471
472#ifdef DEBUG_SAX
473 xmlGenericError(xmlGenericErrorContext,
474 "SAX.xmlSAX2GetParameterEntity(%s)\n", name);
475#endif
476
477 ret = xmlGetParameterEntity(ctxt->myDoc, name);
478 return(ret);
479}
480
481
482/**
483 * xmlSAX2EntityDecl:
484 * @ctx: the user data (XML parser context)
485 * @name: the entity name
486 * @type: the entity type
487 * @publicId: The public ID of the entity
488 * @systemId: The system ID of the entity
489 * @content: the entity value (without processing).
490 *
491 * An entity definition has been parsed
492 */
493void
494xmlSAX2EntityDecl(void *ctx, const xmlChar *name, int type,
495 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
496{
497 xmlEntityPtr ent;
498 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
499
500#ifdef DEBUG_SAX
501 xmlGenericError(xmlGenericErrorContext,
502 "SAX.xmlSAX2EntityDecl(%s, %d, %s, %s, %s)\n",
503 name, type, publicId, systemId, content);
504#endif
505 if (ctxt->inSubset == 1) {
506 ent = xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
507 systemId, content);
508 if ((ent == NULL) && (ctxt->pedantic) &&
509 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000510 ctxt->sax->warning(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000511 "Entity(%s) already defined in the internal subset\n", name);
512 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
513 xmlChar *URI;
514 const char *base = NULL;
515
516 if (ctxt->input != NULL)
517 base = ctxt->input->filename;
518 if (base == NULL)
519 base = ctxt->directory;
520
521 URI = xmlBuildURI(systemId, (const xmlChar *) base);
522 ent->URI = URI;
523 }
524 } else if (ctxt->inSubset == 2) {
525 ent = xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
526 systemId, content);
527 if ((ent == NULL) && (ctxt->pedantic) &&
528 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000529 ctxt->sax->warning(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000530 "Entity(%s) already defined in the external subset\n", name);
531 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
532 xmlChar *URI;
533 const char *base = NULL;
534
535 if (ctxt->input != NULL)
536 base = ctxt->input->filename;
537 if (base == NULL)
538 base = ctxt->directory;
539
540 URI = xmlBuildURI(systemId, (const xmlChar *) base);
541 ent->URI = URI;
542 }
543 } else {
544 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000545 ctxt->sax->error(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000546 "SAX.xmlSAX2EntityDecl(%s) called while not in subset\n", name);
547 }
548}
549
550/**
551 * xmlSAX2AttributeDecl:
552 * @ctx: the user data (XML parser context)
553 * @elem: the name of the element
554 * @fullname: the attribute name
555 * @type: the attribute type
556 * @def: the type of default value
557 * @defaultValue: the attribute default value
558 * @tree: the tree of enumerated value set
559 *
560 * An attribute definition has been parsed
561 */
562void
563xmlSAX2AttributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
564 int type, int def, const xmlChar *defaultValue,
565 xmlEnumerationPtr tree)
566{
567 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
568 xmlAttributePtr attr;
569 xmlChar *name = NULL, *prefix = NULL;
570
571#ifdef DEBUG_SAX
572 xmlGenericError(xmlGenericErrorContext,
573 "SAX.xmlSAX2AttributeDecl(%s, %s, %d, %d, %s, ...)\n",
574 elem, fullname, type, def, defaultValue);
575#endif
Daniel Veillard68cb4b22004-04-18 20:55:39 +0000576 if ((xmlStrEqual(fullname, BAD_CAST "xml:id")) &&
577 (type != XML_ATTRIBUTE_ID)) {
578 /*
579 * Raise the error but keep the validity flag
580 */
581 int tmp = ctxt->valid;
582 xmlErrValid(ctxt, XML_DTD_XMLID_TYPE,
583 "xml:id : attribute type should be ID\n", NULL, NULL);
584 ctxt->valid = tmp;
585 }
Daniel Veillarde57ec792003-09-10 10:50:59 +0000586 /* TODO: optimize name/prefix allocation */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000587 name = xmlSplitQName(ctxt, fullname, &prefix);
588 ctxt->vctxt.valid = 1;
589 if (ctxt->inSubset == 1)
590 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
591 name, prefix, (xmlAttributeType) type,
592 (xmlAttributeDefault) def, defaultValue, tree);
593 else if (ctxt->inSubset == 2)
594 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
595 name, prefix, (xmlAttributeType) type,
596 (xmlAttributeDefault) def, defaultValue, tree);
597 else {
598 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000599 ctxt->sax->error(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000600 "SAX.xmlSAX2AttributeDecl(%s) called while not in subset\n", name);
Daniel Veillarde57ec792003-09-10 10:50:59 +0000601 xmlFreeEnumeration(tree);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000602 return;
603 }
Daniel Veillard4432df22003-09-28 18:58:27 +0000604#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000605 if (ctxt->vctxt.valid == 0)
606 ctxt->valid = 0;
607 if ((attr != NULL) && (ctxt->validate) && (ctxt->wellFormed) &&
608 (ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset != NULL))
609 ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
610 attr);
Daniel Veillard4432df22003-09-28 18:58:27 +0000611#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000612 if (prefix != NULL)
613 xmlFree(prefix);
614 if (name != NULL)
615 xmlFree(name);
616}
617
618/**
619 * xmlSAX2ElementDecl:
620 * @ctx: the user data (XML parser context)
621 * @name: the element name
622 * @type: the element type
623 * @content: the element value tree
624 *
625 * An element definition has been parsed
626 */
627void
628xmlSAX2ElementDecl(void *ctx, const xmlChar * name, int type,
629 xmlElementContentPtr content)
630{
631 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
632 xmlElementPtr elem = NULL;
633
634#ifdef DEBUG_SAX
635 xmlGenericError(xmlGenericErrorContext,
636 "SAX.xmlSAX2ElementDecl(%s, %d, ...)\n", name, type);
637#endif
638
639 if (ctxt->inSubset == 1)
640 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
641 name, (xmlElementTypeVal) type, content);
642 else if (ctxt->inSubset == 2)
643 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
644 name, (xmlElementTypeVal) type, content);
645 else {
646 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000647 ctxt->sax->error(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000648 "SAX.xmlSAX2ElementDecl(%s) called while not in subset\n",
649 name);
650 return;
651 }
Daniel Veillard4432df22003-09-28 18:58:27 +0000652#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000653 if (elem == NULL)
654 ctxt->valid = 0;
655 if (ctxt->validate && ctxt->wellFormed &&
656 ctxt->myDoc && ctxt->myDoc->intSubset)
657 ctxt->valid &=
658 xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
Daniel Veillard4432df22003-09-28 18:58:27 +0000659#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000660}
661
662/**
663 * xmlSAX2NotationDecl:
664 * @ctx: the user data (XML parser context)
665 * @name: The name of the notation
666 * @publicId: The public ID of the entity
667 * @systemId: The system ID of the entity
668 *
669 * What to do when a notation declaration has been parsed.
670 */
671void
672xmlSAX2NotationDecl(void *ctx, const xmlChar *name,
673 const xmlChar *publicId, const xmlChar *systemId)
674{
675 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
676 xmlNotationPtr nota = NULL;
677
678#ifdef DEBUG_SAX
679 xmlGenericError(xmlGenericErrorContext,
680 "SAX.xmlSAX2NotationDecl(%s, %s, %s)\n", name, publicId, systemId);
681#endif
682
683 if ((publicId == NULL) && (systemId == NULL)) {
684 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000685 ctxt->sax->error(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000686 "SAX.xmlSAX2NotationDecl(%s) externalID or PublicID missing\n", name);
687 ctxt->valid = 0;
688 ctxt->wellFormed = 0;
689 return;
690 } else if (ctxt->inSubset == 1)
691 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
692 publicId, systemId);
693 else if (ctxt->inSubset == 2)
694 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, name,
695 publicId, systemId);
696 else {
697 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000698 ctxt->sax->error(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000699 "SAX.xmlSAX2NotationDecl(%s) called while not in subset\n", name);
700 return;
701 }
Daniel Veillard4432df22003-09-28 18:58:27 +0000702#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000703 if (nota == NULL) ctxt->valid = 0;
704 if (ctxt->validate && ctxt->wellFormed &&
705 ctxt->myDoc && ctxt->myDoc->intSubset)
706 ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
707 nota);
Daniel Veillard4432df22003-09-28 18:58:27 +0000708#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000709}
710
711/**
712 * xmlSAX2UnparsedEntityDecl:
713 * @ctx: the user data (XML parser context)
714 * @name: The name of the entity
715 * @publicId: The public ID of the entity
716 * @systemId: The system ID of the entity
717 * @notationName: the name of the notation
718 *
719 * What to do when an unparsed entity declaration is parsed
720 */
721void
722xmlSAX2UnparsedEntityDecl(void *ctx, const xmlChar *name,
723 const xmlChar *publicId, const xmlChar *systemId,
724 const xmlChar *notationName)
725{
726 xmlEntityPtr ent;
727 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
728#ifdef DEBUG_SAX
729 xmlGenericError(xmlGenericErrorContext,
730 "SAX.xmlSAX2UnparsedEntityDecl(%s, %s, %s, %s)\n",
731 name, publicId, systemId, notationName);
732#endif
733 if (ctxt->inSubset == 1) {
734 ent = xmlAddDocEntity(ctxt->myDoc, name,
735 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
736 publicId, systemId, notationName);
737 if ((ent == NULL) && (ctxt->pedantic) &&
738 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000739 ctxt->sax->warning(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000740 "Entity(%s) already defined in the internal subset\n", name);
741 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
742 xmlChar *URI;
743 const char *base = NULL;
744
745 if (ctxt->input != NULL)
746 base = ctxt->input->filename;
747 if (base == NULL)
748 base = ctxt->directory;
749
750 URI = xmlBuildURI(systemId, (const xmlChar *) base);
751 ent->URI = URI;
752 }
753 } else if (ctxt->inSubset == 2) {
754 ent = xmlAddDtdEntity(ctxt->myDoc, name,
755 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
756 publicId, systemId, notationName);
757 if ((ent == NULL) && (ctxt->pedantic) &&
758 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000759 ctxt->sax->warning(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000760 "Entity(%s) already defined in the external subset\n", name);
761 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
762 xmlChar *URI;
763 const char *base = NULL;
764
765 if (ctxt->input != NULL)
766 base = ctxt->input->filename;
767 if (base == NULL)
768 base = ctxt->directory;
769
770 URI = xmlBuildURI(systemId, (const xmlChar *) base);
771 ent->URI = URI;
772 }
773 } else {
774 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000775 ctxt->sax->error(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000776 "SAX.xmlSAX2UnparsedEntityDecl(%s) called while not in subset\n", name);
777 }
778}
779
780/**
781 * xmlSAX2SetDocumentLocator:
782 * @ctx: the user data (XML parser context)
783 * @loc: A SAX Locator
784 *
785 * Receive the document locator at startup, actually xmlDefaultSAXLocator
786 * Everything is available on the context, so this is useless in our case.
787 */
788void
789xmlSAX2SetDocumentLocator(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
790{
791 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
792#ifdef DEBUG_SAX
793 xmlGenericError(xmlGenericErrorContext,
794 "SAX.xmlSAX2SetDocumentLocator()\n");
795#endif
796}
797
798/**
799 * xmlSAX2StartDocument:
800 * @ctx: the user data (XML parser context)
801 *
802 * called when the document start being processed.
803 */
804void
805xmlSAX2StartDocument(void *ctx)
806{
807 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
808 xmlDocPtr doc;
809
810#ifdef DEBUG_SAX
811 xmlGenericError(xmlGenericErrorContext,
812 "SAX.xmlSAX2StartDocument()\n");
813#endif
814 if (ctxt->html) {
815#ifdef LIBXML_HTML_ENABLED
816 if (ctxt->myDoc == NULL)
817 ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
818 if (ctxt->myDoc == NULL) {
819 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
820 ctxt->sax->error(ctxt->userData,
821 "SAX.xmlSAX2StartDocument(): out of memory\n");
822 ctxt->errNo = XML_ERR_NO_MEMORY;
823 ctxt->instate = XML_PARSER_EOF;
824 ctxt->disableSAX = 1;
825 return;
826 }
827#else
828 xmlGenericError(xmlGenericErrorContext,
829 "libxml2 built without HTML support\n");
830 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
831 ctxt->instate = XML_PARSER_EOF;
832 ctxt->disableSAX = 1;
833 return;
834#endif
835 } else {
836 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
837 if (doc != NULL) {
838 if (ctxt->encoding != NULL)
839 doc->encoding = xmlStrdup(ctxt->encoding);
840 else
841 doc->encoding = NULL;
842 doc->standalone = ctxt->standalone;
843 } else {
844 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
845 ctxt->sax->error(ctxt->userData,
846 "SAX.xmlSAX2StartDocument(): out of memory\n");
847 ctxt->errNo = XML_ERR_NO_MEMORY;
848 ctxt->instate = XML_PARSER_EOF;
849 ctxt->disableSAX = 1;
850 return;
851 }
Daniel Veillard500a1de2004-03-22 15:22:58 +0000852 if ((ctxt->dictNames) && (doc != NULL)) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +0000853 doc->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000854 xmlDictReference(doc->dict);
855 }
Daniel Veillard1af9a412003-08-20 22:54:39 +0000856 }
857 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
858 (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
859 ctxt->myDoc->URL = xmlCanonicPath((const xmlChar *) ctxt->input->filename);
860 if (ctxt->myDoc->URL == NULL)
861 ctxt->myDoc->URL = xmlStrdup((const xmlChar *) ctxt->input->filename);
862 }
863}
864
865/**
866 * xmlSAX2EndDocument:
867 * @ctx: the user data (XML parser context)
868 *
869 * called when the document end has been detected.
870 */
871void
872xmlSAX2EndDocument(void *ctx)
873{
874 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
875#ifdef DEBUG_SAX
876 xmlGenericError(xmlGenericErrorContext,
877 "SAX.xmlSAX2EndDocument()\n");
878#endif
Daniel Veillard4432df22003-09-28 18:58:27 +0000879#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000880 if (ctxt->validate && ctxt->wellFormed &&
881 ctxt->myDoc && ctxt->myDoc->intSubset)
882 ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
Daniel Veillard4432df22003-09-28 18:58:27 +0000883#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000884
885 /*
886 * Grab the encoding if it was added on-the-fly
887 */
888 if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
889 (ctxt->myDoc->encoding == NULL)) {
890 ctxt->myDoc->encoding = ctxt->encoding;
891 ctxt->encoding = NULL;
892 }
893 if ((ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
894 (ctxt->myDoc->encoding == NULL)) {
895 ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
896 }
897 if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
898 (ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
899 ctxt->myDoc->charset = ctxt->charset;
900 }
901}
902
Daniel Veillard81273902003-09-30 00:43:48 +0000903#if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED)
Daniel Veillard1af9a412003-08-20 22:54:39 +0000904/**
905 * xmlSAX2AttributeInternal:
906 * @ctx: the user data (XML parser context)
907 * @fullname: The attribute name, including namespace prefix
908 * @value: The attribute value
909 * @prefix: the prefix on the element node
910 *
911 * Handle an attribute that has been read by the parser.
912 * The default handling is to convert the attribute into an
913 * DOM subtree and past it in a new xmlAttr element added to
914 * the element.
915 */
916static void
917xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000918 const xmlChar *value, const xmlChar *prefix ATTRIBUTE_UNUSED)
Daniel Veillard1af9a412003-08-20 22:54:39 +0000919{
920 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
921 xmlAttrPtr ret;
922 xmlChar *name;
923 xmlChar *ns;
924 xmlChar *nval;
925 xmlNsPtr namespace;
926
927 /*
928 * Split the full name into a namespace prefix and the tag name
929 */
930 name = xmlSplitQName(ctxt, fullname, &ns);
931 if ((name != NULL) && (name[0] == 0)) {
932 if (xmlStrEqual(ns, BAD_CAST "xmlns")) {
933 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
934 ctxt->sax->error(ctxt->userData,
935 "invalid namespace declaration '%s'\n", fullname);
936 } else {
937 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
938 ctxt->sax->warning(ctxt->userData,
939 "Avoid attribute ending with ':' like '%s'\n", fullname);
940 }
941 if (ns != NULL)
942 xmlFree(ns);
943 ns = NULL;
944 xmlFree(name);
945 name = xmlStrdup(fullname);
946 }
947 if (name == NULL) {
948 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
949 ctxt->sax->error(ctxt->userData,
950 "SAX.xmlSAX2StartElement(): out of memory\n");
951 ctxt->errNo = XML_ERR_NO_MEMORY;
952 ctxt->instate = XML_PARSER_EOF;
953 ctxt->disableSAX = 1;
954 if (ns != NULL)
955 xmlFree(ns);
956 return;
957 }
958
Daniel Veillard4432df22003-09-28 18:58:27 +0000959#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000960 /*
961 * Do the last stage of the attribute normalization
962 * Needed for HTML too:
963 * http://www.w3.org/TR/html4/types.html#h-6.2
964 */
965 ctxt->vctxt.valid = 1;
966 nval = xmlValidCtxtNormalizeAttributeValue(&ctxt->vctxt,
967 ctxt->myDoc, ctxt->node,
968 fullname, value);
969 if (ctxt->vctxt.valid != 1) {
970 ctxt->valid = 0;
971 }
972 if (nval != NULL)
973 value = nval;
Daniel Veillard4432df22003-09-28 18:58:27 +0000974#else
975 nval = NULL;
976#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000977
978 /*
979 * Check whether it's a namespace definition
980 */
981 if ((!ctxt->html) && (ns == NULL) &&
982 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
983 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
984 xmlNsPtr nsret;
985 xmlChar *val;
986
987 if (!ctxt->replaceEntities) {
988 ctxt->depth++;
989 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
990 0,0,0);
991 ctxt->depth--;
992 } else {
993 val = (xmlChar *) value;
994 }
995
996 if (val[0] != 0) {
997 xmlURIPtr uri;
998
999 uri = xmlParseURI((const char *)val);
1000 if (uri == NULL) {
1001 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1002 ctxt->sax->warning(ctxt->userData,
William M. Brack4811ba32003-09-06 18:02:53 +00001003 "xmlns: %s not a valid URI\n", val);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001004 } else {
1005 if (uri->scheme == NULL) {
1006 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1007 ctxt->sax->warning(ctxt->userData,
1008 "xmlns: URI %s is not absolute\n", val);
1009 }
1010 xmlFreeURI(uri);
1011 }
1012 }
1013
1014 /* a default namespace definition */
1015 nsret = xmlNewNs(ctxt->node, val, NULL);
1016
Daniel Veillard4432df22003-09-28 18:58:27 +00001017#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001018 /*
1019 * Validate also for namespace decls, they are attributes from
1020 * an XML-1.0 perspective
1021 */
1022 if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
1023 ctxt->myDoc && ctxt->myDoc->intSubset)
1024 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
1025 ctxt->node, prefix, nsret, val);
Daniel Veillard4432df22003-09-28 18:58:27 +00001026#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001027 if (name != NULL)
1028 xmlFree(name);
1029 if (nval != NULL)
1030 xmlFree(nval);
1031 if (val != value)
1032 xmlFree(val);
1033 return;
1034 }
1035 if ((!ctxt->html) &&
1036 (ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
1037 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
1038 xmlNsPtr nsret;
1039 xmlChar *val;
1040
1041 if (!ctxt->replaceEntities) {
1042 ctxt->depth++;
1043 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1044 0,0,0);
1045 ctxt->depth--;
1046 if (val == NULL) {
1047 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1048 ctxt->sax->error(ctxt->userData,
1049 "SAX.xmlSAX2StartElement(): out of memory\n");
1050 ctxt->errNo = XML_ERR_NO_MEMORY;
1051 ctxt->instate = XML_PARSER_EOF;
1052 ctxt->disableSAX = 1;
1053 xmlFree(ns);
1054 if (name != NULL)
1055 xmlFree(name);
1056 return;
1057 }
1058 } else {
1059 val = (xmlChar *) value;
1060 }
1061
1062 if (val[0] == 0) {
1063 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1064 ctxt->sax->error(ctxt->userData,
1065 "Empty namespace name for prefix %s\n", name);
1066 }
1067 if ((ctxt->pedantic != 0) && (val[0] != 0)) {
1068 xmlURIPtr uri;
1069
1070 uri = xmlParseURI((const char *)val);
1071 if (uri == NULL) {
1072 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1073 ctxt->sax->warning(ctxt->userData,
1074 "xmlns:%s: %s not a valid URI\n", name, value);
1075 } else {
1076 if (uri->scheme == NULL) {
1077 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1078 ctxt->sax->warning(ctxt->userData,
1079 "xmlns:%s: URI %s is not absolute\n", name, value);
1080 }
1081 xmlFreeURI(uri);
1082 }
1083 }
1084
1085 /* a standard namespace definition */
1086 nsret = xmlNewNs(ctxt->node, val, name);
1087 xmlFree(ns);
Daniel Veillard4432df22003-09-28 18:58:27 +00001088#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001089 /*
1090 * Validate also for namespace decls, they are attributes from
1091 * an XML-1.0 perspective
1092 */
1093 if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
1094 ctxt->myDoc && ctxt->myDoc->intSubset)
1095 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
1096 ctxt->node, prefix, nsret, value);
Daniel Veillard4432df22003-09-28 18:58:27 +00001097#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001098 if (name != NULL)
1099 xmlFree(name);
1100 if (nval != NULL)
1101 xmlFree(nval);
1102 if (val != value)
1103 xmlFree(val);
1104 return;
1105 }
1106
1107 if (ns != NULL) {
1108 xmlAttrPtr prop;
1109 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
Daniel Veillard67906942003-08-28 21:13:25 +00001110 if (namespace == NULL) {
William M. Brack4811ba32003-09-06 18:02:53 +00001111 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1112 ctxt->sax->error(ctxt->userData,
1113 "Namespace prefix %s of attribute %s is not defined\n",
Daniel Veillard67906942003-08-28 21:13:25 +00001114 ns, name);
1115 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001116
1117 prop = ctxt->node->properties;
1118 while (prop != NULL) {
1119 if (prop->ns != NULL) {
1120 if ((xmlStrEqual(name, prop->name)) &&
1121 ((namespace == prop->ns) ||
1122 (xmlStrEqual(namespace->href, prop->ns->href)))) {
1123 ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
1124 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1125 ctxt->sax->error(ctxt->userData,
1126 "Attribute %s in %s redefined\n",
1127 name, namespace->href);
1128 ctxt->wellFormed = 0;
1129 if (ctxt->recovery == 0) ctxt->disableSAX = 1;
1130 goto error;
1131 }
1132 }
1133 prop = prop->next;
1134 }
1135 } else {
1136 namespace = NULL;
1137 }
1138
1139 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
1140 ret = xmlNewNsPropEatName(ctxt->node, namespace, name, NULL);
1141
1142 if (ret != NULL) {
1143 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
1144 xmlNodePtr tmp;
1145
1146 ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
1147 tmp = ret->children;
1148 while (tmp != NULL) {
1149 tmp->parent = (xmlNodePtr) ret;
1150 if (tmp->next == NULL)
1151 ret->last = tmp;
1152 tmp = tmp->next;
1153 }
1154 } else if (value != NULL) {
1155 ret->children = xmlNewDocText(ctxt->myDoc, value);
1156 ret->last = ret->children;
1157 if (ret->children != NULL)
1158 ret->children->parent = (xmlNodePtr) ret;
1159 }
1160 }
1161
Daniel Veillard4432df22003-09-28 18:58:27 +00001162#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001163 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
1164 ctxt->myDoc && ctxt->myDoc->intSubset) {
1165
1166 /*
1167 * If we don't substitute entities, the validation should be
1168 * done on a value with replaced entities anyway.
1169 */
1170 if (!ctxt->replaceEntities) {
1171 xmlChar *val;
1172
1173 ctxt->depth++;
1174 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1175 0,0,0);
1176 ctxt->depth--;
1177
1178 if (val == NULL)
1179 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1180 ctxt->myDoc, ctxt->node, ret, value);
1181 else {
1182 xmlChar *nvalnorm;
1183
1184 /*
1185 * Do the last stage of the attribute normalization
1186 * It need to be done twice ... it's an extra burden related
1187 * to the ability to keep xmlSAX2References in attributes
1188 */
1189 nvalnorm = xmlValidNormalizeAttributeValue(ctxt->myDoc,
1190 ctxt->node, fullname, val);
1191 if (nvalnorm != NULL) {
1192 xmlFree(val);
1193 val = nvalnorm;
1194 }
1195
1196 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1197 ctxt->myDoc, ctxt->node, ret, val);
1198 xmlFree(val);
1199 }
1200 } else {
1201 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
1202 ctxt->node, ret, value);
1203 }
Daniel Veillard4432df22003-09-28 18:58:27 +00001204 } else
1205#endif /* LIBXML_VALID_ENABLED */
1206 if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
Daniel Veillard1af9a412003-08-20 22:54:39 +00001207 (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
1208 ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
1209 /*
1210 * when validating, the ID registration is done at the attribute
1211 * validation level. Otherwise we have to do specific handling here.
1212 */
1213 if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
1214 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
1215 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
1216 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00001217 else if (xmlStrEqual(fullname, BAD_CAST "xml:id")) {
1218 /*
1219 * Add the xml:id value
1220 *
1221 * Open issue: normalization of the value.
1222 */
Daniel Veillard68cb4b22004-04-18 20:55:39 +00001223 if (xmlValidateNCName(value, 1) != 0) {
1224 xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
1225 "xml:id : attribute value %s is not an NCName\n",
1226 (const char *) value, NULL);
1227 }
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00001228 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
1229 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001230 }
1231
1232error:
1233 if (nval != NULL)
1234 xmlFree(nval);
1235 if (ns != NULL)
1236 xmlFree(ns);
1237}
1238
Daniel Veillard1af9a412003-08-20 22:54:39 +00001239/*
1240 * xmlCheckDefaultedAttributes:
1241 *
1242 * Check defaulted attributes from the DTD
1243 */
1244static void
1245xmlCheckDefaultedAttributes(xmlParserCtxtPtr ctxt, const xmlChar *name,
1246 const xmlChar *prefix, const xmlChar **atts) {
1247 xmlElementPtr elemDecl;
1248 const xmlChar *att;
1249 int internal = 1;
1250 int i;
1251
1252 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset, name, prefix);
1253 if (elemDecl == NULL) {
1254 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset, name, prefix);
1255 internal = 0;
1256 }
1257
1258process_external_subset:
1259
1260 if (elemDecl != NULL) {
1261 xmlAttributePtr attr = elemDecl->attributes;
1262 /*
1263 * Check against defaulted attributes from the external subset
1264 * if the document is stamped as standalone
1265 */
1266 if ((ctxt->myDoc->standalone == 1) &&
1267 (ctxt->myDoc->extSubset != NULL) &&
1268 (ctxt->validate)) {
1269 while (attr != NULL) {
1270 if ((attr->defaultValue != NULL) &&
1271 (xmlGetDtdQAttrDesc(ctxt->myDoc->extSubset,
1272 attr->elem, attr->name,
1273 attr->prefix) == attr) &&
1274 (xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1275 attr->elem, attr->name,
1276 attr->prefix) == NULL)) {
1277 xmlChar *fulln;
1278
1279 if (attr->prefix != NULL) {
1280 fulln = xmlStrdup(attr->prefix);
1281 fulln = xmlStrcat(fulln, BAD_CAST ":");
1282 fulln = xmlStrcat(fulln, attr->name);
1283 } else {
1284 fulln = xmlStrdup(attr->name);
1285 }
1286
1287 /*
1288 * Check that the attribute is not declared in the
1289 * serialization
1290 */
1291 att = NULL;
1292 if (atts != NULL) {
1293 i = 0;
1294 att = atts[i];
1295 while (att != NULL) {
1296 if (xmlStrEqual(att, fulln))
1297 break;
1298 i += 2;
1299 att = atts[i];
1300 }
1301 }
1302 if (att == NULL) {
Daniel Veillardf88d8cf2003-12-08 10:25:02 +00001303 xmlErrValid(ctxt, XML_DTD_STANDALONE_DEFAULTED,
Daniel Veillard1af9a412003-08-20 22:54:39 +00001304 "standalone: attribute %s on %s defaulted from external subset\n",
Daniel Veillard427174f2003-12-10 10:42:59 +00001305 (const char *)fulln,
1306 (const char *)attr->elem);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001307 }
1308 }
1309 attr = attr->nexth;
1310 }
1311 }
1312
1313 /*
1314 * Actually insert defaulted values when needed
1315 */
1316 attr = elemDecl->attributes;
1317 while (attr != NULL) {
1318 /*
1319 * Make sure that attributes redefinition occuring in the
1320 * internal subset are not overriden by definitions in the
1321 * external subset.
1322 */
1323 if (attr->defaultValue != NULL) {
1324 /*
1325 * the element should be instantiated in the tree if:
1326 * - this is a namespace prefix
1327 * - the user required for completion in the tree
1328 * like XSLT
1329 * - there isn't already an attribute definition
1330 * in the internal subset overriding it.
1331 */
1332 if (((attr->prefix != NULL) &&
1333 (xmlStrEqual(attr->prefix, BAD_CAST "xmlns"))) ||
1334 ((attr->prefix == NULL) &&
1335 (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) ||
1336 (ctxt->loadsubset & XML_COMPLETE_ATTRS)) {
1337 xmlAttributePtr tst;
1338
1339 tst = xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1340 attr->elem, attr->name,
1341 attr->prefix);
1342 if ((tst == attr) || (tst == NULL)) {
1343 xmlChar fn[50];
1344 xmlChar *fulln;
1345
1346 fulln = xmlBuildQName(attr->name, attr->prefix, fn, 50);
1347 if (fulln == NULL) {
1348 if ((ctxt->sax != NULL) &&
1349 (ctxt->sax->error != NULL))
1350 ctxt->sax->error(ctxt->userData,
1351 "SAX.xmlSAX2StartElement(): out of memory\n");
1352 ctxt->errNo = XML_ERR_NO_MEMORY;
1353 ctxt->instate = XML_PARSER_EOF;
1354 ctxt->disableSAX = 1;
1355 return;
1356 }
1357
1358 /*
1359 * Check that the attribute is not declared in the
1360 * serialization
1361 */
1362 att = NULL;
1363 if (atts != NULL) {
1364 i = 0;
1365 att = atts[i];
1366 while (att != NULL) {
1367 if (xmlStrEqual(att, fulln))
1368 break;
1369 i += 2;
1370 att = atts[i];
1371 }
1372 }
1373 if (att == NULL) {
1374 xmlSAX2AttributeInternal(ctxt, fulln,
1375 attr->defaultValue, prefix);
1376 }
1377 if ((fulln != fn) && (fulln != attr->name))
1378 xmlFree(fulln);
1379 }
1380 }
1381 }
1382 attr = attr->nexth;
1383 }
1384 if (internal == 1) {
1385 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset,
1386 name, prefix);
1387 internal = 0;
1388 goto process_external_subset;
1389 }
1390 }
1391}
1392
1393/**
1394 * xmlSAX2StartElement:
1395 * @ctx: the user data (XML parser context)
1396 * @fullname: The element name, including namespace prefix
1397 * @atts: An array of name/value attributes pairs, NULL terminated
1398 *
1399 * called when an opening tag has been processed.
1400 */
1401void
1402xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
1403{
1404 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1405 xmlNodePtr ret;
1406 xmlNodePtr parent = ctxt->node;
1407 xmlNsPtr ns;
1408 xmlChar *name;
1409 xmlChar *prefix;
1410 const xmlChar *att;
1411 const xmlChar *value;
1412 int i;
1413
1414#ifdef DEBUG_SAX
1415 xmlGenericError(xmlGenericErrorContext,
1416 "SAX.xmlSAX2StartElement(%s)\n", fullname);
1417#endif
1418
1419 /*
1420 * First check on validity:
1421 */
1422 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
1423 ((ctxt->myDoc->intSubset == NULL) ||
1424 ((ctxt->myDoc->intSubset->notations == NULL) &&
1425 (ctxt->myDoc->intSubset->elements == NULL) &&
1426 (ctxt->myDoc->intSubset->attributes == NULL) &&
1427 (ctxt->myDoc->intSubset->entities == NULL)))) {
Daniel Veillardf88d8cf2003-12-08 10:25:02 +00001428 xmlErrValid(ctxt, XML_ERR_NO_DTD,
1429 "Validation failed: no DTD found !", NULL, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001430 ctxt->validate = 0;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001431 }
1432
1433
1434 /*
1435 * Split the full name into a namespace prefix and the tag name
1436 */
1437 name = xmlSplitQName(ctxt, fullname, &prefix);
1438
1439
1440 /*
1441 * Note : the namespace resolution is deferred until the end of the
1442 * attributes parsing, since local namespace can be defined as
1443 * an attribute at this level.
1444 */
1445 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL);
1446 if (ret == NULL) {
1447 if (prefix != NULL)
1448 xmlFree(prefix);
1449 ctxt->errNo = XML_ERR_NO_MEMORY;
1450 ctxt->instate = XML_PARSER_EOF;
1451 ctxt->disableSAX = 1;
1452 return;
1453 }
1454 if (ctxt->myDoc->children == NULL) {
1455#ifdef DEBUG_SAX_TREE
1456 xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
1457#endif
1458 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1459 } else if (parent == NULL) {
1460 parent = ctxt->myDoc->children;
1461 }
1462 ctxt->nodemem = -1;
1463 if (ctxt->linenumbers) {
Daniel Veillard3e35f8e2003-10-21 00:05:38 +00001464 if (ctxt->input != NULL) {
1465 if (ctxt->input->line < 65535)
1466 ret->line = (short) ctxt->input->line;
1467 else
1468 ret->line = 65535;
1469 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001470 }
1471
1472 /*
1473 * We are parsing a new node.
1474 */
1475#ifdef DEBUG_SAX_TREE
1476 xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);
1477#endif
1478 nodePush(ctxt, ret);
1479
1480 /*
1481 * Link the child element
1482 */
1483 if (parent != NULL) {
1484 if (parent->type == XML_ELEMENT_NODE) {
1485#ifdef DEBUG_SAX_TREE
1486 xmlGenericError(xmlGenericErrorContext,
1487 "adding child %s to %s\n", name, parent->name);
1488#endif
1489 xmlAddChild(parent, ret);
1490 } else {
1491#ifdef DEBUG_SAX_TREE
1492 xmlGenericError(xmlGenericErrorContext,
1493 "adding sibling %s to ", name);
1494 xmlDebugDumpOneNode(stderr, parent, 0);
1495#endif
1496 xmlAddSibling(parent, ret);
1497 }
1498 }
1499
1500 /*
1501 * Insert all the defaulted attributes from the DTD especially namespaces
1502 */
1503 if ((!ctxt->html) &&
1504 ((ctxt->myDoc->intSubset != NULL) ||
1505 (ctxt->myDoc->extSubset != NULL))) {
1506 xmlCheckDefaultedAttributes(ctxt, name, prefix, atts);
1507 }
1508
1509 /*
1510 * process all the attributes whose name start with "xmlns"
1511 */
1512 if (atts != NULL) {
1513 i = 0;
1514 att = atts[i++];
1515 value = atts[i++];
1516 if (!ctxt->html) {
1517 while ((att != NULL) && (value != NULL)) {
1518 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l') &&
1519 (att[3] == 'n') && (att[4] == 's'))
1520 xmlSAX2AttributeInternal(ctxt, att, value, prefix);
1521
1522 att = atts[i++];
1523 value = atts[i++];
1524 }
1525 }
1526 }
1527
1528 /*
1529 * Search the namespace, note that since the attributes have been
1530 * processed, the local namespaces are available.
1531 */
1532 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
1533 if ((ns == NULL) && (parent != NULL))
1534 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
1535 if ((prefix != NULL) && (ns == NULL)) {
1536 ns = xmlNewNs(ret, NULL, prefix);
1537 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1538 ctxt->sax->warning(ctxt->userData,
1539 "Namespace prefix %s is not defined\n", prefix);
1540 }
1541
1542 /*
1543 * set the namespace node, making sure that if the default namspace
1544 * is unbound on a parent we simply kee it NULL
1545 */
1546 if ((ns != NULL) && (ns->href != NULL) &&
1547 ((ns->href[0] != 0) || (ns->prefix != NULL)))
1548 xmlSetNs(ret, ns);
1549
1550 /*
1551 * process all the other attributes
1552 */
1553 if (atts != NULL) {
1554 i = 0;
1555 att = atts[i++];
1556 value = atts[i++];
1557 if (ctxt->html) {
1558 while (att != NULL) {
1559 xmlSAX2AttributeInternal(ctxt, att, value, NULL);
1560 att = atts[i++];
1561 value = atts[i++];
1562 }
1563 } else {
1564 while ((att != NULL) && (value != NULL)) {
1565 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l') ||
1566 (att[3] != 'n') || (att[4] != 's'))
1567 xmlSAX2AttributeInternal(ctxt, att, value, NULL);
1568
1569 /*
1570 * Next ones
1571 */
1572 att = atts[i++];
1573 value = atts[i++];
1574 }
1575 }
1576 }
1577
Daniel Veillard4432df22003-09-28 18:58:27 +00001578#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001579 /*
1580 * If it's the Document root, finish the DTD validation and
1581 * check the document root element for validity
1582 */
1583 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
1584 int chk;
1585
1586 chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
1587 if (chk <= 0)
1588 ctxt->valid = 0;
1589 if (chk < 0)
1590 ctxt->wellFormed = 0;
1591 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
1592 ctxt->vctxt.finishDtd = 1;
1593 }
Daniel Veillard4432df22003-09-28 18:58:27 +00001594#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001595
1596 if (prefix != NULL)
1597 xmlFree(prefix);
1598
1599}
1600
1601/**
1602 * xmlSAX2EndElement:
1603 * @ctx: the user data (XML parser context)
1604 * @name: The element name
1605 *
1606 * called when the end of an element has been detected.
1607 */
1608void
1609xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
1610{
1611 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1612 xmlParserNodeInfo node_info;
1613 xmlNodePtr cur = ctxt->node;
1614
1615#ifdef DEBUG_SAX
1616 if (name == NULL)
1617 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(NULL)\n");
1618 else
1619 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(%s)\n", name);
1620#endif
1621
1622 /* Capture end position and add node */
1623 if (cur != NULL && ctxt->record_info) {
1624 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
1625 node_info.end_line = ctxt->input->line;
1626 node_info.node = cur;
1627 xmlParserAddNodeInfo(ctxt, &node_info);
1628 }
1629 ctxt->nodemem = -1;
1630
Daniel Veillard4432df22003-09-28 18:58:27 +00001631#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001632 if (ctxt->validate && ctxt->wellFormed &&
1633 ctxt->myDoc && ctxt->myDoc->intSubset)
1634 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
1635 cur);
Daniel Veillard4432df22003-09-28 18:58:27 +00001636#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001637
1638
1639 /*
1640 * end of parsing of this node.
1641 */
1642#ifdef DEBUG_SAX_TREE
1643 xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);
1644#endif
1645 nodePop(ctxt);
1646}
Daniel Veillard81273902003-09-30 00:43:48 +00001647#endif /* LIBXML_SAX1_ENABLED || LIBXML_HTML_ENABLE */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001648
Daniel Veillarde57ec792003-09-10 10:50:59 +00001649/*
Daniel Veillard19895052003-09-17 13:59:32 +00001650 * xmlSAX2TextNode:
1651 * @ctxt: the parser context
1652 * @str: the input string
1653 * @len: the string length
1654 *
1655 * Remove the entities from an attribute value
1656 *
1657 * Returns the newly allocated string or NULL if not needed or error
1658 */
1659static xmlNodePtr
1660xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
1661 xmlNodePtr ret;
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001662 const xmlChar *intern = NULL;
Daniel Veillard19895052003-09-17 13:59:32 +00001663
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001664 /*
1665 * Allocate
1666 */
Daniel Veillard19895052003-09-17 13:59:32 +00001667 if (ctxt->freeElems != NULL) {
1668 ret = ctxt->freeElems;
1669 ctxt->freeElems = ret->next;
1670 ctxt->freeElemsNr--;
Daniel Veillard19895052003-09-17 13:59:32 +00001671 } else {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001672 ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard19895052003-09-17 13:59:32 +00001673 }
1674 if (ret == NULL) {
1675 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1676 ctxt->sax->error(ctxt->userData,
1677 "SAX.xmlSAX2Characters(): out of memory\n");
1678 ctxt->errNo = XML_ERR_NO_MEMORY;
1679 ctxt->instate = XML_PARSER_EOF;
1680 ctxt->disableSAX = 1;
1681 return(NULL);
1682 }
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001683 /*
1684 * intern the formatting blanks found between tags, or the
1685 * very short strings
1686 */
1687 if (ctxt->dictNames) {
1688 xmlChar cur = str[len];
1689
Daniel Veillarddca8cc72003-09-26 13:53:14 +00001690 if ((len <= 3) && ((cur == '"') || (cur == '\'') ||
1691 ((cur == '<') && (str[len + 1] != '!')))) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001692 intern = xmlDictLookup(ctxt->dict, str, len);
William M. Brack76e95df2003-10-18 16:20:14 +00001693 } else if (IS_BLANK_CH(*str) && (len < 60) && (cur == '<') &&
Daniel Veillarddca8cc72003-09-26 13:53:14 +00001694 (str[len + 1] != '!')) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001695 int i;
1696
1697 for (i = 1;i < len;i++) {
Daniel Veillard1a9b7082004-01-02 10:42:01 +00001698 if (!IS_BLANK_CH(str[i])) goto skip;
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001699 }
1700 intern = xmlDictLookup(ctxt->dict, str, len);
1701 }
1702 }
1703skip:
1704 memset(ret, 0, sizeof(xmlNode));
1705 ret->type = XML_TEXT_NODE;
1706
1707 ret->name = xmlStringText;
1708 if (intern == NULL)
1709 ret->content = xmlStrndup(str, len);
1710 else
1711 ret->content = (xmlChar *) intern;
1712
1713 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1714 xmlRegisterNodeDefaultValue(ret);
Daniel Veillard19895052003-09-17 13:59:32 +00001715 return(ret);
1716}
1717
Daniel Veillard4432df22003-09-28 18:58:27 +00001718#ifdef LIBXML_VALID_ENABLED
Daniel Veillard19895052003-09-17 13:59:32 +00001719/*
Daniel Veillarde57ec792003-09-10 10:50:59 +00001720 * xmlSAX2DecodeAttrEntities:
1721 * @ctxt: the parser context
1722 * @str: the input string
1723 * @len: the string length
1724 *
1725 * Remove the entities from an attribute value
1726 *
1727 * Returns the newly allocated string or NULL if not needed or error
1728 */
1729static xmlChar *
1730xmlSAX2DecodeAttrEntities(xmlParserCtxtPtr ctxt, const xmlChar *str,
1731 const xmlChar *end) {
1732 const xmlChar *in;
1733 xmlChar *ret;
1734
1735 in = str;
1736 while (in < end)
1737 if (*in++ == '&')
1738 goto decode;
1739 return(NULL);
1740decode:
1741 ctxt->depth++;
1742 ret = xmlStringLenDecodeEntities(ctxt, str, end - str,
1743 XML_SUBSTITUTE_REF, 0,0,0);
1744 ctxt->depth--;
1745 return(ret);
1746}
Daniel Veillard4432df22003-09-28 18:58:27 +00001747#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00001748
1749/**
1750 * xmlSAX2AttributeNs:
1751 * @ctx: the user data (XML parser context)
Daniel Veillard62998c02003-09-15 12:56:36 +00001752 * @localname: the local name of the attribute
1753 * @prefix: the attribute namespace prefix if available
1754 * @URI: the attribute namespace name if available
Daniel Veillarde57ec792003-09-10 10:50:59 +00001755 * @value: Start of the attribute value
1756 * @valueend: end of the attribute value
1757 *
1758 * Handle an attribute that has been read by the parser.
1759 * The default handling is to convert the attribute into an
1760 * DOM subtree and past it in a new xmlAttr element added to
1761 * the element.
1762 */
1763static void
1764xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
1765 const xmlChar * localname,
1766 const xmlChar * prefix,
1767 const xmlChar * value,
1768 const xmlChar * valueend)
1769{
1770 xmlAttrPtr ret;
1771 xmlNsPtr namespace = NULL;
1772 xmlChar *dup = NULL;
1773
Daniel Veillarde57ec792003-09-10 10:50:59 +00001774 /*
1775 * Note: if prefix == NULL, the attribute is not in the default namespace
1776 */
1777 if (prefix != NULL)
1778 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, prefix);
1779
Daniel Veillard8a44e592003-09-15 14:50:06 +00001780 /*
1781 * allocate the node
1782 */
1783 if (ctxt->freeAttrs != NULL) {
1784 ret = ctxt->freeAttrs;
1785 ctxt->freeAttrs = ret->next;
Daniel Veillard19895052003-09-17 13:59:32 +00001786 ctxt->freeAttrsNr--;
Daniel Veillard8a44e592003-09-15 14:50:06 +00001787 memset(ret, 0, sizeof(xmlAttr));
1788 ret->type = XML_ATTRIBUTE_NODE;
Daniel Veillarde57ec792003-09-10 10:50:59 +00001789
Daniel Veillard8a44e592003-09-15 14:50:06 +00001790 ret->parent = ctxt->node;
1791 ret->doc = ctxt->myDoc;
1792 ret->ns = namespace;
Daniel Veillarde57ec792003-09-10 10:50:59 +00001793
Daniel Veillard8a44e592003-09-15 14:50:06 +00001794 if (ctxt->dictNames)
1795 ret->name = localname;
1796 else
1797 ret->name = xmlStrdup(localname);
1798
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001799 /* link at the end to preserv order, TODO speed up with a last */
1800 if (ctxt->node->properties == NULL) {
1801 ctxt->node->properties = ret;
1802 } else {
1803 xmlAttrPtr prev = ctxt->node->properties;
1804
1805 while (prev->next != NULL) prev = prev->next;
1806 prev->next = ret;
1807 ret->prev = prev;
1808 }
1809
Daniel Veillard8a44e592003-09-15 14:50:06 +00001810 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1811 xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
1812 } else {
1813 if (ctxt->dictNames)
1814 ret = xmlNewNsPropEatName(ctxt->node, namespace,
1815 (xmlChar *) localname, NULL);
1816 else
1817 ret = xmlNewNsProp(ctxt->node, namespace, localname, NULL);
1818 if (ret == NULL) {
1819 ctxt->errNo = XML_ERR_NO_MEMORY;
1820 ctxt->instate = XML_PARSER_EOF;
1821 ctxt->disableSAX = 1;
1822 return;
Daniel Veillarde57ec792003-09-10 10:50:59 +00001823 }
1824 }
1825
Daniel Veillard8a44e592003-09-15 14:50:06 +00001826 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
1827 xmlNodePtr tmp;
1828
Daniel Veillard19895052003-09-17 13:59:32 +00001829 /*
1830 * We know that if there is an entity reference, then
1831 * the string has been dup'ed and terminates with 0
1832 * otherwise with ' or "
1833 */
1834 if (*valueend != 0) {
1835 tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
1836 ret->children = tmp;
1837 ret->last = tmp;
1838 if (tmp != NULL) {
1839 tmp->doc = ret->doc;
1840 tmp->parent = (xmlNodePtr) ret;
1841 }
1842 } else {
1843 ret->children = xmlStringLenGetNodeList(ctxt->myDoc, value,
1844 valueend - value);
1845 tmp = ret->children;
1846 while (tmp != NULL) {
1847 tmp->parent = (xmlNodePtr) ret;
1848 if (tmp->next == NULL)
1849 ret->last = tmp;
1850 tmp = tmp->next;
1851 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00001852 }
1853 } else if (value != NULL) {
Daniel Veillard19895052003-09-17 13:59:32 +00001854 xmlNodePtr tmp;
1855
1856 tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
1857 ret->children = tmp;
1858 ret->last = tmp;
1859 if (tmp != NULL) {
1860 tmp->doc = ret->doc;
1861 tmp->parent = (xmlNodePtr) ret;
1862 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00001863 }
1864
Daniel Veillard4432df22003-09-28 18:58:27 +00001865#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00001866 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
1867 ctxt->myDoc && ctxt->myDoc->intSubset) {
1868 /*
1869 * If we don't substitute entities, the validation should be
1870 * done on a value with replaced entities anyway.
1871 */
1872 if (!ctxt->replaceEntities) {
1873 dup = xmlSAX2DecodeAttrEntities(ctxt, value, valueend);
1874 if (dup == NULL) {
Daniel Veillard62998c02003-09-15 12:56:36 +00001875 if (*valueend == 0) {
1876 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1877 ctxt->myDoc, ctxt->node, ret, value);
1878 } else {
1879 /*
1880 * That should already be normalized.
1881 * cheaper to finally allocate here than duplicate
1882 * entry points in the full validation code
1883 */
1884 dup = xmlStrndup(value, valueend - value);
Daniel Veillarde57ec792003-09-10 10:50:59 +00001885
Daniel Veillard62998c02003-09-15 12:56:36 +00001886 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1887 ctxt->myDoc, ctxt->node, ret, dup);
1888 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00001889 } else {
Daniel Veillard62998c02003-09-15 12:56:36 +00001890 /*
1891 * dup now contains a string of the flattened attribute
1892 * content with entities substitued. Check if we need to
1893 * apply an extra layer of normalization.
Daniel Veillarde57ec792003-09-10 10:50:59 +00001894 * It need to be done twice ... it's an extra burden related
1895 * to the ability to keep references in attributes
1896 */
Daniel Veillard62998c02003-09-15 12:56:36 +00001897 if (ctxt->attsSpecial != NULL) {
1898 xmlChar *nvalnorm;
1899 xmlChar fn[50];
1900 xmlChar *fullname;
1901
1902 fullname = xmlBuildQName(localname, prefix, fn, 50);
1903 if (fullname != NULL) {
1904 ctxt->vctxt.valid = 1;
1905 nvalnorm = xmlValidCtxtNormalizeAttributeValue(
1906 &ctxt->vctxt, ctxt->myDoc,
1907 ctxt->node, fullname, dup);
1908 if (ctxt->vctxt.valid != 1)
1909 ctxt->valid = 0;
1910
1911 if ((fullname != fn) && (fullname != localname))
1912 xmlFree(fullname);
1913 if (nvalnorm != NULL) {
1914 xmlFree(dup);
1915 dup = nvalnorm;
1916 }
1917 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00001918 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00001919
1920 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1921 ctxt->myDoc, ctxt->node, ret, dup);
1922 }
1923 } else {
Daniel Veillard8e36e6a2003-09-10 10:50:59 +00001924 /*
1925 * if entities already have been substitued, then
1926 * the attribute as passed is already normalized
1927 */
Daniel Veillarde57ec792003-09-10 10:50:59 +00001928 dup = xmlStrndup(value, valueend - value);
1929
1930 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1931 ctxt->myDoc, ctxt->node, ret, dup);
1932 }
Daniel Veillard4432df22003-09-28 18:58:27 +00001933 } else
1934#endif /* LIBXML_VALID_ENABLED */
1935 if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
Daniel Veillarde57ec792003-09-10 10:50:59 +00001936 (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
1937 ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
1938 /*
1939 * when validating, the ID registration is done at the attribute
1940 * validation level. Otherwise we have to do specific handling here.
1941 */
1942 if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) {
1943 /* might be worth duplicate entry points and not copy */
1944 if (dup == NULL)
1945 dup = xmlStrndup(value, valueend - value);
1946 xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
1947 } else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) {
1948 if (dup == NULL)
1949 dup = xmlStrndup(value, valueend - value);
1950 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, dup, ret);
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00001951 } else if ((prefix == ctxt->str_xml) &&
1952 (localname[0] == 'i') && (localname[1] == 'd') &&
1953 (localname[2] == 0)) {
1954 /*
1955 * Add the xml:id value
1956 *
1957 * Open issue: normalization of the value.
1958 */
1959 if (dup == NULL)
1960 dup = xmlStrndup(value, valueend - value);
William M. Brack3f147372004-05-22 01:09:26 +00001961#if LIBXML_VALID_ENABLED
Daniel Veillard68cb4b22004-04-18 20:55:39 +00001962 if (xmlValidateNCName(dup, 1) != 0) {
1963 xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
1964 "xml:id : attribute value %s is not an NCName\n",
1965 (const char *) dup, NULL);
1966 }
William M. Brack3f147372004-05-22 01:09:26 +00001967#endif
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00001968 xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
1969 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00001970 }
1971 if (dup != NULL)
1972 xmlFree(dup);
1973}
1974
1975/**
1976 * xmlSAX2StartElementNs:
1977 * @ctx: the user data (XML parser context)
1978 * @localname: the local name of the element
1979 * @prefix: the element namespace prefix if available
1980 * @URI: the element namespace name if available
1981 * @nb_namespaces: number of namespace definitions on that node
1982 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
1983 * @nb_attributes: the number of attributes on that node
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00001984 * @nb_defaulted: the number of defaulted attributes.
Daniel Veillarde57ec792003-09-10 10:50:59 +00001985 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
1986 * attribute values.
1987 *
1988 * SAX2 callback when an element start has been detected by the parser.
1989 * It provides the namespace informations for the element, as well as
1990 * the new namespace declarations on the element.
1991 */
1992void
1993xmlSAX2StartElementNs(void *ctx,
1994 const xmlChar *localname,
1995 const xmlChar *prefix,
1996 const xmlChar *URI,
1997 int nb_namespaces,
1998 const xmlChar **namespaces,
1999 int nb_attributes,
2000 int nb_defaulted,
2001 const xmlChar **attributes)
2002{
2003 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2004 xmlNodePtr ret;
2005 xmlNodePtr parent = ctxt->node;
2006 xmlNsPtr last = NULL, ns;
2007 const xmlChar *uri, *pref;
2008 int i, j;
2009
2010 /*
2011 * First check on validity:
2012 */
2013 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
2014 ((ctxt->myDoc->intSubset == NULL) ||
2015 ((ctxt->myDoc->intSubset->notations == NULL) &&
2016 (ctxt->myDoc->intSubset->elements == NULL) &&
2017 (ctxt->myDoc->intSubset->attributes == NULL) &&
2018 (ctxt->myDoc->intSubset->entities == NULL)))) {
Daniel Veillardf88d8cf2003-12-08 10:25:02 +00002019 xmlErrValid(ctxt, XML_ERR_NO_DTD,
2020 "Validation failed: no DTD found !", NULL, NULL);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002021 ctxt->validate = 0;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002022 }
2023
Daniel Veillard8a44e592003-09-15 14:50:06 +00002024 /*
2025 * allocate the node
2026 */
2027 if (ctxt->freeElems != NULL) {
2028 ret = ctxt->freeElems;
2029 ctxt->freeElems = ret->next;
Daniel Veillard19895052003-09-17 13:59:32 +00002030 ctxt->freeElemsNr--;
Daniel Veillard8a44e592003-09-15 14:50:06 +00002031 memset(ret, 0, sizeof(xmlNode));
2032 ret->type = XML_ELEMENT_NODE;
2033
2034 if (ctxt->dictNames)
2035 ret->name = localname;
2036 else
2037 ret->name = xmlStrdup(localname);
2038
2039 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2040 xmlRegisterNodeDefaultValue(ret);
2041 } else {
2042 if (ctxt->dictNames)
2043 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
2044 (xmlChar *) localname, NULL);
2045 else
2046 ret = xmlNewDocNode(ctxt->myDoc, NULL, localname, NULL);
2047 if (ret == NULL) {
2048 ctxt->errNo = XML_ERR_NO_MEMORY;
2049 ctxt->instate = XML_PARSER_EOF;
2050 ctxt->disableSAX = 1;
2051 return;
2052 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002053 }
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002054 if (ctxt->linenumbers) {
Daniel Veillard3e35f8e2003-10-21 00:05:38 +00002055 if (ctxt->input != NULL) {
2056 if (ctxt->input->line < 65535)
2057 ret->line = (short) ctxt->input->line;
2058 else
2059 ret->line = 65535;
2060 }
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002061 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00002062
Daniel Veillarde57ec792003-09-10 10:50:59 +00002063 if (ctxt->myDoc->children == NULL) {
2064 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2065 } else if (parent == NULL) {
2066 parent = ctxt->myDoc->children;
2067 }
2068 /*
2069 * Build the namespace list
2070 */
2071 for (i = 0,j = 0;j < nb_namespaces;j++) {
2072 pref = namespaces[i++];
2073 uri = namespaces[i++];
2074 ns = xmlNewNs(NULL, uri, pref);
2075 if (ns != NULL) {
2076 if (last == NULL) {
2077 ret->nsDef = last = ns;
2078 } else {
2079 last->next = ns;
2080 last = ns;
2081 }
2082 if ((URI != NULL) && (prefix == pref))
2083 ret->ns = ns;
2084 } else {
2085 ctxt->errNo = XML_ERR_NO_MEMORY;
2086 ctxt->instate = XML_PARSER_EOF;
2087 ctxt->disableSAX = 1;
2088 return;
2089 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002090#ifdef LIBXML_VALID_ENABLED
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002091 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
2092 ctxt->myDoc && ctxt->myDoc->intSubset) {
2093 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
2094 ret, prefix, ns, uri);
2095 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002096#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002097 }
2098 ctxt->nodemem = -1;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002099
2100 /*
2101 * We are parsing a new node.
2102 */
2103 nodePush(ctxt, ret);
2104
2105 /*
2106 * Link the child element
2107 */
2108 if (parent != NULL) {
2109 if (parent->type == XML_ELEMENT_NODE) {
2110 xmlAddChild(parent, ret);
2111 } else {
2112 xmlAddSibling(parent, ret);
2113 }
2114 }
2115
2116 /*
2117 * Insert the defaulted attributes from the DTD only if requested:
2118 */
2119 if ((nb_defaulted != 0) &&
2120 ((ctxt->loadsubset & XML_COMPLETE_ATTRS) == 0))
2121 nb_attributes -= nb_defaulted;
2122
2123 /*
2124 * Search the namespace if it wasn't already found
2125 */
2126 if ((URI != NULL) && (ret->ns == NULL)) {
2127 ret->ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
2128 if (ret->ns == NULL) {
2129 ns = xmlNewNs(ret, NULL, prefix);
2130 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
2131 ctxt->sax->warning(ctxt->userData,
2132 "Namespace prefix %s was not found\n", prefix);
2133 }
2134 }
2135
2136 /*
2137 * process all the other attributes
2138 */
2139 if (nb_attributes > 0) {
2140 for (j = 0,i = 0;i < nb_attributes;i++,j+=5) {
2141 xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1],
2142 attributes[j+3], attributes[j+4]);
2143 }
2144 }
2145
Daniel Veillard4432df22003-09-28 18:58:27 +00002146#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002147 /*
2148 * If it's the Document root, finish the DTD validation and
2149 * check the document root element for validity
2150 */
2151 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
2152 int chk;
2153
2154 chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
2155 if (chk <= 0)
2156 ctxt->valid = 0;
2157 if (chk < 0)
2158 ctxt->wellFormed = 0;
2159 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
2160 ctxt->vctxt.finishDtd = 1;
2161 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002162#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002163}
2164
2165/**
2166 * xmlSAX2EndElementNs:
2167 * @ctx: the user data (XML parser context)
2168 * @localname: the local name of the element
2169 * @prefix: the element namespace prefix if available
2170 * @URI: the element namespace name if available
2171 *
2172 * SAX2 callback when an element end has been detected by the parser.
2173 * It provides the namespace informations for the element.
2174 */
2175void
2176xmlSAX2EndElementNs(void *ctx,
2177 const xmlChar * localname ATTRIBUTE_UNUSED,
2178 const xmlChar * prefix ATTRIBUTE_UNUSED,
2179 const xmlChar * URI ATTRIBUTE_UNUSED)
2180{
2181 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2182 xmlParserNodeInfo node_info;
2183 xmlNodePtr cur = ctxt->node;
2184
2185 /* Capture end position and add node */
2186 if ((ctxt->record_info) && (cur != NULL)) {
2187 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
2188 node_info.end_line = ctxt->input->line;
2189 node_info.node = cur;
2190 xmlParserAddNodeInfo(ctxt, &node_info);
2191 }
2192 ctxt->nodemem = -1;
2193
Daniel Veillard4432df22003-09-28 18:58:27 +00002194#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002195 if (ctxt->validate && ctxt->wellFormed &&
2196 ctxt->myDoc && ctxt->myDoc->intSubset)
2197 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, cur);
Daniel Veillard4432df22003-09-28 18:58:27 +00002198#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002199
2200 /*
2201 * end of parsing of this node.
2202 */
2203 nodePop(ctxt);
2204}
2205
Daniel Veillard1af9a412003-08-20 22:54:39 +00002206/**
2207 * xmlSAX2Reference:
2208 * @ctx: the user data (XML parser context)
2209 * @name: The entity name
2210 *
2211 * called when an entity xmlSAX2Reference is detected.
2212 */
2213void
2214xmlSAX2Reference(void *ctx, const xmlChar *name)
2215{
2216 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2217 xmlNodePtr ret;
2218
2219#ifdef DEBUG_SAX
2220 xmlGenericError(xmlGenericErrorContext,
2221 "SAX.xmlSAX2Reference(%s)\n", name);
2222#endif
2223 if (name[0] == '#')
2224 ret = xmlNewCharRef(ctxt->myDoc, name);
2225 else
2226 ret = xmlNewReference(ctxt->myDoc, name);
2227#ifdef DEBUG_SAX_TREE
2228 xmlGenericError(xmlGenericErrorContext,
2229 "add xmlSAX2Reference %s to %s \n", name, ctxt->node->name);
2230#endif
2231 xmlAddChild(ctxt->node, ret);
2232}
2233
2234/**
2235 * xmlSAX2Characters:
2236 * @ctx: the user data (XML parser context)
2237 * @ch: a xmlChar string
2238 * @len: the number of xmlChar
2239 *
2240 * receiving some chars from the parser.
2241 */
2242void
2243xmlSAX2Characters(void *ctx, const xmlChar *ch, int len)
2244{
2245 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2246 xmlNodePtr lastChild;
2247
2248#ifdef DEBUG_SAX
2249 xmlGenericError(xmlGenericErrorContext,
2250 "SAX.xmlSAX2Characters(%.30s, %d)\n", ch, len);
2251#endif
2252 /*
2253 * Handle the data if any. If there is no child
2254 * add it as content, otherwise if the last child is text,
2255 * concatenate it, else create a new node of type text.
2256 */
2257
2258 if (ctxt->node == NULL) {
2259#ifdef DEBUG_SAX_TREE
2260 xmlGenericError(xmlGenericErrorContext,
2261 "add chars: ctxt->node == NULL !\n");
2262#endif
2263 return;
2264 }
Daniel Veillard19895052003-09-17 13:59:32 +00002265 lastChild = ctxt->node->last;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002266#ifdef DEBUG_SAX_TREE
2267 xmlGenericError(xmlGenericErrorContext,
2268 "add chars to %s \n", ctxt->node->name);
2269#endif
2270
2271 /*
2272 * Here we needed an accelerator mechanism in case of very large
2273 * elements. Use an attribute in the structure !!!
2274 */
2275 if (lastChild == NULL) {
Daniel Veillard19895052003-09-17 13:59:32 +00002276 lastChild = xmlSAX2TextNode(ctxt, ch, len);
2277 if (lastChild != NULL) {
2278 ctxt->node->children = lastChild;
2279 ctxt->node->last = lastChild;
2280 lastChild->parent = ctxt->node;
2281 lastChild->doc = ctxt->node->doc;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002282 ctxt->nodelen = len;
2283 ctxt->nodemem = len + 1;
2284 }
2285 } else {
2286 int coalesceText = (lastChild != NULL) &&
2287 (lastChild->type == XML_TEXT_NODE) &&
2288 (lastChild->name == xmlStringText);
2289 if ((coalesceText) && (ctxt->nodemem != 0)) {
2290 /*
2291 * The whole point of maintaining nodelen and nodemem,
2292 * xmlTextConcat is too costly, i.e. compute length,
2293 * reallocate a new buffer, move data, append ch. Here
2294 * We try to minimaze realloc() uses and avoid copying
2295 * and recomputing length over and over.
2296 */
Daniel Veillard2b0f8792003-10-10 19:36:36 +00002297 if ((ctxt->nodemem == ctxt->nodelen + 1) &&
2298 (xmlDictOwns(ctxt->dict, lastChild->content))) {
2299 lastChild->content = xmlStrdup(lastChild->content);
2300 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00002301 if (ctxt->nodelen + len >= ctxt->nodemem) {
2302 xmlChar *newbuf;
2303 int size;
2304
2305 size = ctxt->nodemem + len;
2306 size *= 2;
2307 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
2308 if (newbuf == NULL) {
2309 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2310 ctxt->sax->error(ctxt->userData,
2311 "SAX.xmlSAX2Characters(): out of memory\n");
2312 ctxt->errNo = XML_ERR_NO_MEMORY;
2313 ctxt->instate = XML_PARSER_EOF;
2314 ctxt->disableSAX = 1;
2315 return;
2316 }
2317 ctxt->nodemem = size;
2318 lastChild->content = newbuf;
2319 }
2320 memcpy(&lastChild->content[ctxt->nodelen], ch, len);
2321 ctxt->nodelen += len;
2322 lastChild->content[ctxt->nodelen] = 0;
2323 } else if (coalesceText) {
2324 if (xmlTextConcat(lastChild, ch, len)) {
2325 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2326 ctxt->sax->error(ctxt->userData,
2327 "SAX.xmlSAX2Characters(): out of memory\n");
2328 ctxt->errNo = XML_ERR_NO_MEMORY;
2329 ctxt->instate = XML_PARSER_EOF;
2330 ctxt->disableSAX = 1;
2331 }
2332 if (ctxt->node->children != NULL) {
2333 ctxt->nodelen = xmlStrlen(lastChild->content);
2334 ctxt->nodemem = ctxt->nodelen + 1;
2335 }
2336 } else {
2337 /* Mixed content, first time */
Daniel Veillard19895052003-09-17 13:59:32 +00002338 lastChild = xmlSAX2TextNode(ctxt, ch, len);
2339 if (lastChild != NULL) {
Daniel Veillard1af9a412003-08-20 22:54:39 +00002340 xmlAddChild(ctxt->node, lastChild);
2341 if (ctxt->node->children != NULL) {
2342 ctxt->nodelen = len;
2343 ctxt->nodemem = len + 1;
2344 }
2345 }
2346 }
2347 }
2348}
2349
2350/**
2351 * xmlSAX2IgnorableWhitespace:
2352 * @ctx: the user data (XML parser context)
2353 * @ch: a xmlChar string
2354 * @len: the number of xmlChar
2355 *
2356 * receiving some ignorable whitespaces from the parser.
2357 * UNUSED: by default the DOM building will use xmlSAX2Characters
2358 */
2359void
2360xmlSAX2IgnorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
2361{
2362 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
2363#ifdef DEBUG_SAX
2364 xmlGenericError(xmlGenericErrorContext,
2365 "SAX.xmlSAX2IgnorableWhitespace(%.30s, %d)\n", ch, len);
2366#endif
2367}
2368
2369/**
2370 * xmlSAX2ProcessingInstruction:
2371 * @ctx: the user data (XML parser context)
2372 * @target: the target name
2373 * @data: the PI data's
2374 *
2375 * A processing instruction has been parsed.
2376 */
2377void
2378xmlSAX2ProcessingInstruction(void *ctx, const xmlChar *target,
2379 const xmlChar *data)
2380{
2381 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2382 xmlNodePtr ret;
2383 xmlNodePtr parent = ctxt->node;
2384
2385#ifdef DEBUG_SAX
2386 xmlGenericError(xmlGenericErrorContext,
2387 "SAX.xmlSAX2ProcessingInstruction(%s, %s)\n", target, data);
2388#endif
2389
2390 ret = xmlNewPI(target, data);
2391 if (ret == NULL) return;
2392 parent = ctxt->node;
2393
2394 if (ctxt->inSubset == 1) {
2395 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2396 return;
2397 } else if (ctxt->inSubset == 2) {
2398 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2399 return;
2400 }
2401 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
2402#ifdef DEBUG_SAX_TREE
2403 xmlGenericError(xmlGenericErrorContext,
2404 "Setting PI %s as root\n", target);
2405#endif
2406 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2407 return;
2408 }
2409 if (parent->type == XML_ELEMENT_NODE) {
2410#ifdef DEBUG_SAX_TREE
2411 xmlGenericError(xmlGenericErrorContext,
2412 "adding PI %s child to %s\n", target, parent->name);
2413#endif
2414 xmlAddChild(parent, ret);
2415 } else {
2416#ifdef DEBUG_SAX_TREE
2417 xmlGenericError(xmlGenericErrorContext,
2418 "adding PI %s sibling to ", target);
2419 xmlDebugDumpOneNode(stderr, parent, 0);
2420#endif
2421 xmlAddSibling(parent, ret);
2422 }
2423}
2424
2425/**
2426 * xmlSAX2Comment:
2427 * @ctx: the user data (XML parser context)
2428 * @value: the xmlSAX2Comment content
2429 *
2430 * A xmlSAX2Comment has been parsed.
2431 */
2432void
2433xmlSAX2Comment(void *ctx, const xmlChar *value)
2434{
2435 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2436 xmlNodePtr ret;
2437 xmlNodePtr parent = ctxt->node;
2438
2439#ifdef DEBUG_SAX
2440 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2Comment(%s)\n", value);
2441#endif
2442 ret = xmlNewDocComment(ctxt->myDoc, value);
2443 if (ret == NULL) return;
2444
2445 if (ctxt->inSubset == 1) {
2446 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2447 return;
2448 } else if (ctxt->inSubset == 2) {
2449 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2450 return;
2451 }
2452 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
2453#ifdef DEBUG_SAX_TREE
2454 xmlGenericError(xmlGenericErrorContext,
2455 "Setting xmlSAX2Comment as root\n");
2456#endif
2457 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2458 return;
2459 }
2460 if (parent->type == XML_ELEMENT_NODE) {
2461#ifdef DEBUG_SAX_TREE
2462 xmlGenericError(xmlGenericErrorContext,
2463 "adding xmlSAX2Comment child to %s\n", parent->name);
2464#endif
2465 xmlAddChild(parent, ret);
2466 } else {
2467#ifdef DEBUG_SAX_TREE
2468 xmlGenericError(xmlGenericErrorContext,
2469 "adding xmlSAX2Comment sibling to ");
2470 xmlDebugDumpOneNode(stderr, parent, 0);
2471#endif
2472 xmlAddSibling(parent, ret);
2473 }
2474}
2475
2476/**
2477 * xmlSAX2CDataBlock:
2478 * @ctx: the user data (XML parser context)
2479 * @value: The pcdata content
2480 * @len: the block length
2481 *
2482 * called when a pcdata block has been parsed
2483 */
2484void
2485xmlSAX2CDataBlock(void *ctx, const xmlChar *value, int len)
2486{
2487 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2488 xmlNodePtr ret, lastChild;
2489
2490#ifdef DEBUG_SAX
2491 xmlGenericError(xmlGenericErrorContext,
2492 "SAX.pcdata(%.10s, %d)\n", value, len);
2493#endif
2494 lastChild = xmlGetLastChild(ctxt->node);
2495#ifdef DEBUG_SAX_TREE
2496 xmlGenericError(xmlGenericErrorContext,
2497 "add chars to %s \n", ctxt->node->name);
2498#endif
2499 if ((lastChild != NULL) &&
2500 (lastChild->type == XML_CDATA_SECTION_NODE)) {
2501 xmlTextConcat(lastChild, value, len);
2502 } else {
2503 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
2504 xmlAddChild(ctxt->node, ret);
2505 }
2506}
2507
Daniel Veillard62998c02003-09-15 12:56:36 +00002508static int xmlSAX2DefaultVersionValue = 2;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002509
Daniel Veillard81273902003-09-30 00:43:48 +00002510#ifdef LIBXML_SAX1_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002511/**
2512 * xmlSAXDefaultVersion:
2513 * @version: the version, 1 or 2
2514 *
2515 * Set the default version of SAX used globally by the library.
2516 * Note that this may not be a good thing to do from a library
2517 * it is better to use xmlSAXVersion() to set up specifically the
2518 * version for a given parsing context.
2519 *
2520 * Returns the previous value in case of success and -1 in case of error.
2521 */
2522int
2523xmlSAXDefaultVersion(int version)
2524{
2525 int ret = xmlSAX2DefaultVersionValue;
2526
2527 if ((version != 1) && (version != 2))
2528 return(-1);
2529 xmlSAX2DefaultVersionValue = version;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002530 return(ret);
2531}
Daniel Veillard81273902003-09-30 00:43:48 +00002532#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002533
2534/**
2535 * xmlSAXVersion:
2536 * @hdlr: the SAX handler
2537 * @version: the version, 1 or 2
2538 *
2539 * Initialize the default XML SAX handler according to the version
2540 *
2541 * Returns 0 in case of success and -1 in case of error.
2542 */
2543int
2544xmlSAXVersion(xmlSAXHandler *hdlr, int version)
2545{
2546 if (hdlr == NULL) return(-1);
Daniel Veillard81273902003-09-30 00:43:48 +00002547 if (version == 2) {
Daniel Veillarde57ec792003-09-10 10:50:59 +00002548 hdlr->startElement = NULL;
2549 hdlr->endElement = NULL;
2550 hdlr->startElementNs = xmlSAX2StartElementNs;
2551 hdlr->endElementNs = xmlSAX2EndElementNs;
Daniel Veillardffbbed42003-10-10 14:46:54 +00002552 hdlr->serror = NULL;
Daniel Veillard092643b2003-09-25 14:29:29 +00002553 hdlr->initialized = XML_SAX2_MAGIC;
Daniel Veillard81273902003-09-30 00:43:48 +00002554#ifdef LIBXML_SAX1_ENABLED
2555 } else if (version == 1) {
2556 hdlr->startElement = xmlSAX2StartElement;
2557 hdlr->endElement = xmlSAX2EndElement;
2558 hdlr->initialized = 1;
2559#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002560 } else
2561 return(-1);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002562 hdlr->internalSubset = xmlSAX2InternalSubset;
2563 hdlr->externalSubset = xmlSAX2ExternalSubset;
2564 hdlr->isStandalone = xmlSAX2IsStandalone;
2565 hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
2566 hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
2567 hdlr->resolveEntity = xmlSAX2ResolveEntity;
2568 hdlr->getEntity = xmlSAX2GetEntity;
2569 hdlr->getParameterEntity = xmlSAX2GetParameterEntity;
2570 hdlr->entityDecl = xmlSAX2EntityDecl;
2571 hdlr->attributeDecl = xmlSAX2AttributeDecl;
2572 hdlr->elementDecl = xmlSAX2ElementDecl;
2573 hdlr->notationDecl = xmlSAX2NotationDecl;
2574 hdlr->unparsedEntityDecl = xmlSAX2UnparsedEntityDecl;
2575 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2576 hdlr->startDocument = xmlSAX2StartDocument;
2577 hdlr->endDocument = xmlSAX2EndDocument;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002578 hdlr->reference = xmlSAX2Reference;
2579 hdlr->characters = xmlSAX2Characters;
2580 hdlr->cdataBlock = xmlSAX2CDataBlock;
2581 hdlr->ignorableWhitespace = xmlSAX2Characters;
2582 hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
2583 hdlr->comment = xmlSAX2Comment;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002584 hdlr->warning = xmlParserWarning;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002585 hdlr->error = xmlParserError;
2586 hdlr->fatalError = xmlParserError;
2587
Daniel Veillarde57ec792003-09-10 10:50:59 +00002588 return(0);
2589}
2590
2591/**
2592 * xmlSAX2InitDefaultSAXHandler:
2593 * @hdlr: the SAX handler
2594 * @warning: flag if non-zero sets the handler warning procedure
2595 *
2596 * Initialize the default XML SAX2 handler
2597 */
2598void
2599xmlSAX2InitDefaultSAXHandler(xmlSAXHandler *hdlr, int warning)
2600{
2601 if ((hdlr == NULL) || (hdlr->initialized != 0))
2602 return;
2603
2604 xmlSAXVersion(hdlr, xmlSAX2DefaultVersionValue);
2605 if (warning == 0)
2606 hdlr->warning = NULL;
2607 else
2608 hdlr->warning = xmlParserWarning;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002609}
2610
2611/**
2612 * xmlDefaultSAXHandlerInit:
2613 *
2614 * Initialize the default SAX2 handler
2615 */
2616void
2617xmlDefaultSAXHandlerInit(void)
2618{
Daniel Veillard81273902003-09-30 00:43:48 +00002619#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard092643b2003-09-25 14:29:29 +00002620 xmlSAXVersion((xmlSAXHandlerPtr) &xmlDefaultSAXHandler, 1);
Daniel Veillard81273902003-09-30 00:43:48 +00002621#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00002622}
2623
2624#ifdef LIBXML_HTML_ENABLED
2625
2626/**
2627 * xmlSAX2InitHtmlDefaultSAXHandler:
2628 * @hdlr: the SAX handler
2629 *
2630 * Initialize the default HTML SAX2 handler
2631 */
2632void
2633xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr)
2634{
2635 if(hdlr->initialized != 0)
2636 return;
2637
2638 hdlr->internalSubset = xmlSAX2InternalSubset;
2639 hdlr->externalSubset = NULL;
2640 hdlr->isStandalone = NULL;
2641 hdlr->hasInternalSubset = NULL;
2642 hdlr->hasExternalSubset = NULL;
2643 hdlr->resolveEntity = NULL;
2644 hdlr->getEntity = xmlSAX2GetEntity;
2645 hdlr->getParameterEntity = NULL;
2646 hdlr->entityDecl = NULL;
2647 hdlr->attributeDecl = NULL;
2648 hdlr->elementDecl = NULL;
2649 hdlr->notationDecl = NULL;
2650 hdlr->unparsedEntityDecl = NULL;
2651 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2652 hdlr->startDocument = xmlSAX2StartDocument;
2653 hdlr->endDocument = xmlSAX2EndDocument;
2654 hdlr->startElement = xmlSAX2StartElement;
2655 hdlr->endElement = xmlSAX2EndElement;
2656 hdlr->reference = NULL;
2657 hdlr->characters = xmlSAX2Characters;
2658 hdlr->cdataBlock = xmlSAX2CDataBlock;
2659 hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
2660 hdlr->processingInstruction = NULL;
2661 hdlr->comment = xmlSAX2Comment;
2662 hdlr->warning = xmlParserWarning;
2663 hdlr->error = xmlParserError;
2664 hdlr->fatalError = xmlParserError;
2665
Daniel Veillard092643b2003-09-25 14:29:29 +00002666 hdlr->initialized = 1;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002667}
2668
2669/**
2670 * htmlDefaultSAXHandlerInit:
2671 *
2672 * Initialize the default SAX handler
2673 */
2674void
2675htmlDefaultSAXHandlerInit(void)
2676{
Daniel Veillard092643b2003-09-25 14:29:29 +00002677 xmlSAX2InitHtmlDefaultSAXHandler((xmlSAXHandlerPtr) &htmlDefaultSAXHandler);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002678}
2679
2680#endif /* LIBXML_HTML_ENABLED */
2681
2682#ifdef LIBXML_DOCB_ENABLED
2683
2684/**
2685 * xmlSAX2InitDocbDefaultSAXHandler:
2686 * @hdlr: the SAX handler
2687 *
2688 * Initialize the default DocBook SAX2 handler
2689 */
2690void
2691xmlSAX2InitDocbDefaultSAXHandler(xmlSAXHandler *hdlr)
2692{
2693 if(hdlr->initialized != 0)
2694 return;
2695
2696 hdlr->internalSubset = xmlSAX2InternalSubset;
2697 hdlr->externalSubset = NULL;
2698 hdlr->isStandalone = xmlSAX2IsStandalone;
2699 hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
2700 hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
2701 hdlr->resolveEntity = xmlSAX2ResolveEntity;
2702 hdlr->getEntity = xmlSAX2GetEntity;
2703 hdlr->getParameterEntity = NULL;
2704 hdlr->entityDecl = xmlSAX2EntityDecl;
2705 hdlr->attributeDecl = NULL;
2706 hdlr->elementDecl = NULL;
2707 hdlr->notationDecl = NULL;
2708 hdlr->unparsedEntityDecl = NULL;
2709 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2710 hdlr->startDocument = xmlSAX2StartDocument;
2711 hdlr->endDocument = xmlSAX2EndDocument;
2712 hdlr->startElement = xmlSAX2StartElement;
2713 hdlr->endElement = xmlSAX2EndElement;
2714 hdlr->reference = xmlSAX2Reference;
2715 hdlr->characters = xmlSAX2Characters;
2716 hdlr->cdataBlock = NULL;
2717 hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
2718 hdlr->processingInstruction = NULL;
2719 hdlr->comment = xmlSAX2Comment;
2720 hdlr->warning = xmlParserWarning;
2721 hdlr->error = xmlParserError;
2722 hdlr->fatalError = xmlParserError;
2723
Daniel Veillardffbbed42003-10-10 14:46:54 +00002724 hdlr->initialized = 1;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002725}
2726
2727/**
2728 * docbDefaultSAXHandlerInit:
2729 *
2730 * Initialize the default SAX handler
2731 */
2732void
2733docbDefaultSAXHandlerInit(void)
2734{
Daniel Veillard092643b2003-09-25 14:29:29 +00002735 xmlSAX2InitDocbDefaultSAXHandler((xmlSAXHandlerPtr) &docbDefaultSAXHandler);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002736}
2737
2738#endif /* LIBXML_DOCB_ENABLED */