blob: d27d5748045e3cbf740f53dcafda9feaff37f7ec [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 Veillarde57ec792003-09-10 10:50:59 +0000576 /* TODO: optimize name/prefix allocation */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000577 name = xmlSplitQName(ctxt, fullname, &prefix);
578 ctxt->vctxt.valid = 1;
579 if (ctxt->inSubset == 1)
580 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
581 name, prefix, (xmlAttributeType) type,
582 (xmlAttributeDefault) def, defaultValue, tree);
583 else if (ctxt->inSubset == 2)
584 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
585 name, prefix, (xmlAttributeType) type,
586 (xmlAttributeDefault) def, defaultValue, tree);
587 else {
588 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000589 ctxt->sax->error(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000590 "SAX.xmlSAX2AttributeDecl(%s) called while not in subset\n", name);
Daniel Veillarde57ec792003-09-10 10:50:59 +0000591 xmlFreeEnumeration(tree);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000592 return;
593 }
Daniel Veillard4432df22003-09-28 18:58:27 +0000594#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000595 if (ctxt->vctxt.valid == 0)
596 ctxt->valid = 0;
597 if ((attr != NULL) && (ctxt->validate) && (ctxt->wellFormed) &&
598 (ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset != NULL))
599 ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
600 attr);
Daniel Veillard4432df22003-09-28 18:58:27 +0000601#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000602 if (prefix != NULL)
603 xmlFree(prefix);
604 if (name != NULL)
605 xmlFree(name);
606}
607
608/**
609 * xmlSAX2ElementDecl:
610 * @ctx: the user data (XML parser context)
611 * @name: the element name
612 * @type: the element type
613 * @content: the element value tree
614 *
615 * An element definition has been parsed
616 */
617void
618xmlSAX2ElementDecl(void *ctx, const xmlChar * name, int type,
619 xmlElementContentPtr content)
620{
621 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
622 xmlElementPtr elem = NULL;
623
624#ifdef DEBUG_SAX
625 xmlGenericError(xmlGenericErrorContext,
626 "SAX.xmlSAX2ElementDecl(%s, %d, ...)\n", name, type);
627#endif
628
629 if (ctxt->inSubset == 1)
630 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
631 name, (xmlElementTypeVal) type, content);
632 else if (ctxt->inSubset == 2)
633 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
634 name, (xmlElementTypeVal) type, content);
635 else {
636 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000637 ctxt->sax->error(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000638 "SAX.xmlSAX2ElementDecl(%s) called while not in subset\n",
639 name);
640 return;
641 }
Daniel Veillard4432df22003-09-28 18:58:27 +0000642#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000643 if (elem == NULL)
644 ctxt->valid = 0;
645 if (ctxt->validate && ctxt->wellFormed &&
646 ctxt->myDoc && ctxt->myDoc->intSubset)
647 ctxt->valid &=
648 xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
Daniel Veillard4432df22003-09-28 18:58:27 +0000649#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000650}
651
652/**
653 * xmlSAX2NotationDecl:
654 * @ctx: the user data (XML parser context)
655 * @name: The name of the notation
656 * @publicId: The public ID of the entity
657 * @systemId: The system ID of the entity
658 *
659 * What to do when a notation declaration has been parsed.
660 */
661void
662xmlSAX2NotationDecl(void *ctx, const xmlChar *name,
663 const xmlChar *publicId, const xmlChar *systemId)
664{
665 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
666 xmlNotationPtr nota = NULL;
667
668#ifdef DEBUG_SAX
669 xmlGenericError(xmlGenericErrorContext,
670 "SAX.xmlSAX2NotationDecl(%s, %s, %s)\n", name, publicId, systemId);
671#endif
672
673 if ((publicId == NULL) && (systemId == NULL)) {
674 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000675 ctxt->sax->error(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000676 "SAX.xmlSAX2NotationDecl(%s) externalID or PublicID missing\n", name);
677 ctxt->valid = 0;
678 ctxt->wellFormed = 0;
679 return;
680 } else if (ctxt->inSubset == 1)
681 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
682 publicId, systemId);
683 else if (ctxt->inSubset == 2)
684 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, name,
685 publicId, systemId);
686 else {
687 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000688 ctxt->sax->error(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000689 "SAX.xmlSAX2NotationDecl(%s) called while not in subset\n", name);
690 return;
691 }
Daniel Veillard4432df22003-09-28 18:58:27 +0000692#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000693 if (nota == NULL) ctxt->valid = 0;
694 if (ctxt->validate && ctxt->wellFormed &&
695 ctxt->myDoc && ctxt->myDoc->intSubset)
696 ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
697 nota);
Daniel Veillard4432df22003-09-28 18:58:27 +0000698#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000699}
700
701/**
702 * xmlSAX2UnparsedEntityDecl:
703 * @ctx: the user data (XML parser context)
704 * @name: The name of the entity
705 * @publicId: The public ID of the entity
706 * @systemId: The system ID of the entity
707 * @notationName: the name of the notation
708 *
709 * What to do when an unparsed entity declaration is parsed
710 */
711void
712xmlSAX2UnparsedEntityDecl(void *ctx, const xmlChar *name,
713 const xmlChar *publicId, const xmlChar *systemId,
714 const xmlChar *notationName)
715{
716 xmlEntityPtr ent;
717 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
718#ifdef DEBUG_SAX
719 xmlGenericError(xmlGenericErrorContext,
720 "SAX.xmlSAX2UnparsedEntityDecl(%s, %s, %s, %s)\n",
721 name, publicId, systemId, notationName);
722#endif
723 if (ctxt->inSubset == 1) {
724 ent = xmlAddDocEntity(ctxt->myDoc, name,
725 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
726 publicId, systemId, notationName);
727 if ((ent == NULL) && (ctxt->pedantic) &&
728 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000729 ctxt->sax->warning(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000730 "Entity(%s) already defined in the internal subset\n", name);
731 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
732 xmlChar *URI;
733 const char *base = NULL;
734
735 if (ctxt->input != NULL)
736 base = ctxt->input->filename;
737 if (base == NULL)
738 base = ctxt->directory;
739
740 URI = xmlBuildURI(systemId, (const xmlChar *) base);
741 ent->URI = URI;
742 }
743 } else if (ctxt->inSubset == 2) {
744 ent = xmlAddDtdEntity(ctxt->myDoc, name,
745 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
746 publicId, systemId, notationName);
747 if ((ent == NULL) && (ctxt->pedantic) &&
748 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000749 ctxt->sax->warning(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000750 "Entity(%s) already defined in the external subset\n", name);
751 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
752 xmlChar *URI;
753 const char *base = NULL;
754
755 if (ctxt->input != NULL)
756 base = ctxt->input->filename;
757 if (base == NULL)
758 base = ctxt->directory;
759
760 URI = xmlBuildURI(systemId, (const xmlChar *) base);
761 ent->URI = URI;
762 }
763 } else {
764 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
William M. Brack4811ba32003-09-06 18:02:53 +0000765 ctxt->sax->error(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000766 "SAX.xmlSAX2UnparsedEntityDecl(%s) called while not in subset\n", name);
767 }
768}
769
770/**
771 * xmlSAX2SetDocumentLocator:
772 * @ctx: the user data (XML parser context)
773 * @loc: A SAX Locator
774 *
775 * Receive the document locator at startup, actually xmlDefaultSAXLocator
776 * Everything is available on the context, so this is useless in our case.
777 */
778void
779xmlSAX2SetDocumentLocator(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
780{
781 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
782#ifdef DEBUG_SAX
783 xmlGenericError(xmlGenericErrorContext,
784 "SAX.xmlSAX2SetDocumentLocator()\n");
785#endif
786}
787
788/**
789 * xmlSAX2StartDocument:
790 * @ctx: the user data (XML parser context)
791 *
792 * called when the document start being processed.
793 */
794void
795xmlSAX2StartDocument(void *ctx)
796{
797 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
798 xmlDocPtr doc;
799
800#ifdef DEBUG_SAX
801 xmlGenericError(xmlGenericErrorContext,
802 "SAX.xmlSAX2StartDocument()\n");
803#endif
804 if (ctxt->html) {
805#ifdef LIBXML_HTML_ENABLED
806 if (ctxt->myDoc == NULL)
807 ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
808 if (ctxt->myDoc == NULL) {
809 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
810 ctxt->sax->error(ctxt->userData,
811 "SAX.xmlSAX2StartDocument(): out of memory\n");
812 ctxt->errNo = XML_ERR_NO_MEMORY;
813 ctxt->instate = XML_PARSER_EOF;
814 ctxt->disableSAX = 1;
815 return;
816 }
817#else
818 xmlGenericError(xmlGenericErrorContext,
819 "libxml2 built without HTML support\n");
820 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
821 ctxt->instate = XML_PARSER_EOF;
822 ctxt->disableSAX = 1;
823 return;
824#endif
825 } else {
826 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
827 if (doc != NULL) {
828 if (ctxt->encoding != NULL)
829 doc->encoding = xmlStrdup(ctxt->encoding);
830 else
831 doc->encoding = NULL;
832 doc->standalone = ctxt->standalone;
833 } else {
834 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
835 ctxt->sax->error(ctxt->userData,
836 "SAX.xmlSAX2StartDocument(): out of memory\n");
837 ctxt->errNo = XML_ERR_NO_MEMORY;
838 ctxt->instate = XML_PARSER_EOF;
839 ctxt->disableSAX = 1;
840 return;
841 }
Daniel Veillarde96a2a42003-09-24 21:23:56 +0000842 if ((ctxt->dictNames) && (doc != NULL))
843 doc->dict = ctxt->dict;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000844 }
845 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
846 (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
847 ctxt->myDoc->URL = xmlCanonicPath((const xmlChar *) ctxt->input->filename);
848 if (ctxt->myDoc->URL == NULL)
849 ctxt->myDoc->URL = xmlStrdup((const xmlChar *) ctxt->input->filename);
850 }
851}
852
853/**
854 * xmlSAX2EndDocument:
855 * @ctx: the user data (XML parser context)
856 *
857 * called when the document end has been detected.
858 */
859void
860xmlSAX2EndDocument(void *ctx)
861{
862 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
863#ifdef DEBUG_SAX
864 xmlGenericError(xmlGenericErrorContext,
865 "SAX.xmlSAX2EndDocument()\n");
866#endif
Daniel Veillard4432df22003-09-28 18:58:27 +0000867#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000868 if (ctxt->validate && ctxt->wellFormed &&
869 ctxt->myDoc && ctxt->myDoc->intSubset)
870 ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
Daniel Veillard4432df22003-09-28 18:58:27 +0000871#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000872
873 /*
874 * Grab the encoding if it was added on-the-fly
875 */
876 if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
877 (ctxt->myDoc->encoding == NULL)) {
878 ctxt->myDoc->encoding = ctxt->encoding;
879 ctxt->encoding = NULL;
880 }
881 if ((ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
882 (ctxt->myDoc->encoding == NULL)) {
883 ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
884 }
885 if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
886 (ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
887 ctxt->myDoc->charset = ctxt->charset;
888 }
889}
890
Daniel Veillard81273902003-09-30 00:43:48 +0000891#if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED)
Daniel Veillard1af9a412003-08-20 22:54:39 +0000892/**
893 * xmlSAX2AttributeInternal:
894 * @ctx: the user data (XML parser context)
895 * @fullname: The attribute name, including namespace prefix
896 * @value: The attribute value
897 * @prefix: the prefix on the element node
898 *
899 * Handle an attribute that has been read by the parser.
900 * The default handling is to convert the attribute into an
901 * DOM subtree and past it in a new xmlAttr element added to
902 * the element.
903 */
904static void
905xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000906 const xmlChar *value, const xmlChar *prefix ATTRIBUTE_UNUSED)
Daniel Veillard1af9a412003-08-20 22:54:39 +0000907{
908 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
909 xmlAttrPtr ret;
910 xmlChar *name;
911 xmlChar *ns;
912 xmlChar *nval;
913 xmlNsPtr namespace;
914
915 /*
916 * Split the full name into a namespace prefix and the tag name
917 */
918 name = xmlSplitQName(ctxt, fullname, &ns);
919 if ((name != NULL) && (name[0] == 0)) {
920 if (xmlStrEqual(ns, BAD_CAST "xmlns")) {
921 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
922 ctxt->sax->error(ctxt->userData,
923 "invalid namespace declaration '%s'\n", fullname);
924 } else {
925 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
926 ctxt->sax->warning(ctxt->userData,
927 "Avoid attribute ending with ':' like '%s'\n", fullname);
928 }
929 if (ns != NULL)
930 xmlFree(ns);
931 ns = NULL;
932 xmlFree(name);
933 name = xmlStrdup(fullname);
934 }
935 if (name == NULL) {
936 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
937 ctxt->sax->error(ctxt->userData,
938 "SAX.xmlSAX2StartElement(): out of memory\n");
939 ctxt->errNo = XML_ERR_NO_MEMORY;
940 ctxt->instate = XML_PARSER_EOF;
941 ctxt->disableSAX = 1;
942 if (ns != NULL)
943 xmlFree(ns);
944 return;
945 }
946
Daniel Veillard4432df22003-09-28 18:58:27 +0000947#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000948 /*
949 * Do the last stage of the attribute normalization
950 * Needed for HTML too:
951 * http://www.w3.org/TR/html4/types.html#h-6.2
952 */
953 ctxt->vctxt.valid = 1;
954 nval = xmlValidCtxtNormalizeAttributeValue(&ctxt->vctxt,
955 ctxt->myDoc, ctxt->node,
956 fullname, value);
957 if (ctxt->vctxt.valid != 1) {
958 ctxt->valid = 0;
959 }
960 if (nval != NULL)
961 value = nval;
Daniel Veillard4432df22003-09-28 18:58:27 +0000962#else
963 nval = NULL;
964#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000965
966 /*
967 * Check whether it's a namespace definition
968 */
969 if ((!ctxt->html) && (ns == NULL) &&
970 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
971 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
972 xmlNsPtr nsret;
973 xmlChar *val;
974
975 if (!ctxt->replaceEntities) {
976 ctxt->depth++;
977 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
978 0,0,0);
979 ctxt->depth--;
980 } else {
981 val = (xmlChar *) value;
982 }
983
984 if (val[0] != 0) {
985 xmlURIPtr uri;
986
987 uri = xmlParseURI((const char *)val);
988 if (uri == NULL) {
989 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
990 ctxt->sax->warning(ctxt->userData,
William M. Brack4811ba32003-09-06 18:02:53 +0000991 "xmlns: %s not a valid URI\n", val);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000992 } else {
993 if (uri->scheme == NULL) {
994 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
995 ctxt->sax->warning(ctxt->userData,
996 "xmlns: URI %s is not absolute\n", val);
997 }
998 xmlFreeURI(uri);
999 }
1000 }
1001
1002 /* a default namespace definition */
1003 nsret = xmlNewNs(ctxt->node, val, NULL);
1004
Daniel Veillard4432df22003-09-28 18:58:27 +00001005#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001006 /*
1007 * Validate also for namespace decls, they are attributes from
1008 * an XML-1.0 perspective
1009 */
1010 if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
1011 ctxt->myDoc && ctxt->myDoc->intSubset)
1012 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
1013 ctxt->node, prefix, nsret, val);
Daniel Veillard4432df22003-09-28 18:58:27 +00001014#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001015 if (name != NULL)
1016 xmlFree(name);
1017 if (nval != NULL)
1018 xmlFree(nval);
1019 if (val != value)
1020 xmlFree(val);
1021 return;
1022 }
1023 if ((!ctxt->html) &&
1024 (ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
1025 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
1026 xmlNsPtr nsret;
1027 xmlChar *val;
1028
1029 if (!ctxt->replaceEntities) {
1030 ctxt->depth++;
1031 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1032 0,0,0);
1033 ctxt->depth--;
1034 if (val == NULL) {
1035 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1036 ctxt->sax->error(ctxt->userData,
1037 "SAX.xmlSAX2StartElement(): out of memory\n");
1038 ctxt->errNo = XML_ERR_NO_MEMORY;
1039 ctxt->instate = XML_PARSER_EOF;
1040 ctxt->disableSAX = 1;
1041 xmlFree(ns);
1042 if (name != NULL)
1043 xmlFree(name);
1044 return;
1045 }
1046 } else {
1047 val = (xmlChar *) value;
1048 }
1049
1050 if (val[0] == 0) {
1051 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1052 ctxt->sax->error(ctxt->userData,
1053 "Empty namespace name for prefix %s\n", name);
1054 }
1055 if ((ctxt->pedantic != 0) && (val[0] != 0)) {
1056 xmlURIPtr uri;
1057
1058 uri = xmlParseURI((const char *)val);
1059 if (uri == NULL) {
1060 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1061 ctxt->sax->warning(ctxt->userData,
1062 "xmlns:%s: %s not a valid URI\n", name, value);
1063 } else {
1064 if (uri->scheme == NULL) {
1065 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1066 ctxt->sax->warning(ctxt->userData,
1067 "xmlns:%s: URI %s is not absolute\n", name, value);
1068 }
1069 xmlFreeURI(uri);
1070 }
1071 }
1072
1073 /* a standard namespace definition */
1074 nsret = xmlNewNs(ctxt->node, val, name);
1075 xmlFree(ns);
Daniel Veillard4432df22003-09-28 18:58:27 +00001076#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001077 /*
1078 * Validate also for namespace decls, they are attributes from
1079 * an XML-1.0 perspective
1080 */
1081 if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
1082 ctxt->myDoc && ctxt->myDoc->intSubset)
1083 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
1084 ctxt->node, prefix, nsret, value);
Daniel Veillard4432df22003-09-28 18:58:27 +00001085#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001086 if (name != NULL)
1087 xmlFree(name);
1088 if (nval != NULL)
1089 xmlFree(nval);
1090 if (val != value)
1091 xmlFree(val);
1092 return;
1093 }
1094
1095 if (ns != NULL) {
1096 xmlAttrPtr prop;
1097 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
Daniel Veillard67906942003-08-28 21:13:25 +00001098 if (namespace == NULL) {
William M. Brack4811ba32003-09-06 18:02:53 +00001099 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1100 ctxt->sax->error(ctxt->userData,
1101 "Namespace prefix %s of attribute %s is not defined\n",
Daniel Veillard67906942003-08-28 21:13:25 +00001102 ns, name);
1103 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001104
1105 prop = ctxt->node->properties;
1106 while (prop != NULL) {
1107 if (prop->ns != NULL) {
1108 if ((xmlStrEqual(name, prop->name)) &&
1109 ((namespace == prop->ns) ||
1110 (xmlStrEqual(namespace->href, prop->ns->href)))) {
1111 ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
1112 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1113 ctxt->sax->error(ctxt->userData,
1114 "Attribute %s in %s redefined\n",
1115 name, namespace->href);
1116 ctxt->wellFormed = 0;
1117 if (ctxt->recovery == 0) ctxt->disableSAX = 1;
1118 goto error;
1119 }
1120 }
1121 prop = prop->next;
1122 }
1123 } else {
1124 namespace = NULL;
1125 }
1126
1127 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
1128 ret = xmlNewNsPropEatName(ctxt->node, namespace, name, NULL);
1129
1130 if (ret != NULL) {
1131 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
1132 xmlNodePtr tmp;
1133
1134 ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
1135 tmp = ret->children;
1136 while (tmp != NULL) {
1137 tmp->parent = (xmlNodePtr) ret;
1138 if (tmp->next == NULL)
1139 ret->last = tmp;
1140 tmp = tmp->next;
1141 }
1142 } else if (value != NULL) {
1143 ret->children = xmlNewDocText(ctxt->myDoc, value);
1144 ret->last = ret->children;
1145 if (ret->children != NULL)
1146 ret->children->parent = (xmlNodePtr) ret;
1147 }
1148 }
1149
Daniel Veillard4432df22003-09-28 18:58:27 +00001150#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001151 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
1152 ctxt->myDoc && ctxt->myDoc->intSubset) {
1153
1154 /*
1155 * If we don't substitute entities, the validation should be
1156 * done on a value with replaced entities anyway.
1157 */
1158 if (!ctxt->replaceEntities) {
1159 xmlChar *val;
1160
1161 ctxt->depth++;
1162 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1163 0,0,0);
1164 ctxt->depth--;
1165
1166 if (val == NULL)
1167 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1168 ctxt->myDoc, ctxt->node, ret, value);
1169 else {
1170 xmlChar *nvalnorm;
1171
1172 /*
1173 * Do the last stage of the attribute normalization
1174 * It need to be done twice ... it's an extra burden related
1175 * to the ability to keep xmlSAX2References in attributes
1176 */
1177 nvalnorm = xmlValidNormalizeAttributeValue(ctxt->myDoc,
1178 ctxt->node, fullname, val);
1179 if (nvalnorm != NULL) {
1180 xmlFree(val);
1181 val = nvalnorm;
1182 }
1183
1184 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1185 ctxt->myDoc, ctxt->node, ret, val);
1186 xmlFree(val);
1187 }
1188 } else {
1189 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
1190 ctxt->node, ret, value);
1191 }
Daniel Veillard4432df22003-09-28 18:58:27 +00001192 } else
1193#endif /* LIBXML_VALID_ENABLED */
1194 if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
Daniel Veillard1af9a412003-08-20 22:54:39 +00001195 (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
1196 ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
1197 /*
1198 * when validating, the ID registration is done at the attribute
1199 * validation level. Otherwise we have to do specific handling here.
1200 */
1201 if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
1202 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
1203 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
1204 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
1205 }
1206
1207error:
1208 if (nval != NULL)
1209 xmlFree(nval);
1210 if (ns != NULL)
1211 xmlFree(ns);
1212}
1213
Daniel Veillard1af9a412003-08-20 22:54:39 +00001214/*
1215 * xmlCheckDefaultedAttributes:
1216 *
1217 * Check defaulted attributes from the DTD
1218 */
1219static void
1220xmlCheckDefaultedAttributes(xmlParserCtxtPtr ctxt, const xmlChar *name,
1221 const xmlChar *prefix, const xmlChar **atts) {
1222 xmlElementPtr elemDecl;
1223 const xmlChar *att;
1224 int internal = 1;
1225 int i;
1226
1227 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset, name, prefix);
1228 if (elemDecl == NULL) {
1229 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset, name, prefix);
1230 internal = 0;
1231 }
1232
1233process_external_subset:
1234
1235 if (elemDecl != NULL) {
1236 xmlAttributePtr attr = elemDecl->attributes;
1237 /*
1238 * Check against defaulted attributes from the external subset
1239 * if the document is stamped as standalone
1240 */
1241 if ((ctxt->myDoc->standalone == 1) &&
1242 (ctxt->myDoc->extSubset != NULL) &&
1243 (ctxt->validate)) {
1244 while (attr != NULL) {
1245 if ((attr->defaultValue != NULL) &&
1246 (xmlGetDtdQAttrDesc(ctxt->myDoc->extSubset,
1247 attr->elem, attr->name,
1248 attr->prefix) == attr) &&
1249 (xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1250 attr->elem, attr->name,
1251 attr->prefix) == NULL)) {
1252 xmlChar *fulln;
1253
1254 if (attr->prefix != NULL) {
1255 fulln = xmlStrdup(attr->prefix);
1256 fulln = xmlStrcat(fulln, BAD_CAST ":");
1257 fulln = xmlStrcat(fulln, attr->name);
1258 } else {
1259 fulln = xmlStrdup(attr->name);
1260 }
1261
1262 /*
1263 * Check that the attribute is not declared in the
1264 * serialization
1265 */
1266 att = NULL;
1267 if (atts != NULL) {
1268 i = 0;
1269 att = atts[i];
1270 while (att != NULL) {
1271 if (xmlStrEqual(att, fulln))
1272 break;
1273 i += 2;
1274 att = atts[i];
1275 }
1276 }
1277 if (att == NULL) {
Daniel Veillardf88d8cf2003-12-08 10:25:02 +00001278 xmlErrValid(ctxt, XML_DTD_STANDALONE_DEFAULTED,
Daniel Veillard1af9a412003-08-20 22:54:39 +00001279 "standalone: attribute %s on %s defaulted from external subset\n",
Daniel Veillard427174f2003-12-10 10:42:59 +00001280 (const char *)fulln,
1281 (const char *)attr->elem);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001282 }
1283 }
1284 attr = attr->nexth;
1285 }
1286 }
1287
1288 /*
1289 * Actually insert defaulted values when needed
1290 */
1291 attr = elemDecl->attributes;
1292 while (attr != NULL) {
1293 /*
1294 * Make sure that attributes redefinition occuring in the
1295 * internal subset are not overriden by definitions in the
1296 * external subset.
1297 */
1298 if (attr->defaultValue != NULL) {
1299 /*
1300 * the element should be instantiated in the tree if:
1301 * - this is a namespace prefix
1302 * - the user required for completion in the tree
1303 * like XSLT
1304 * - there isn't already an attribute definition
1305 * in the internal subset overriding it.
1306 */
1307 if (((attr->prefix != NULL) &&
1308 (xmlStrEqual(attr->prefix, BAD_CAST "xmlns"))) ||
1309 ((attr->prefix == NULL) &&
1310 (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) ||
1311 (ctxt->loadsubset & XML_COMPLETE_ATTRS)) {
1312 xmlAttributePtr tst;
1313
1314 tst = xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1315 attr->elem, attr->name,
1316 attr->prefix);
1317 if ((tst == attr) || (tst == NULL)) {
1318 xmlChar fn[50];
1319 xmlChar *fulln;
1320
1321 fulln = xmlBuildQName(attr->name, attr->prefix, fn, 50);
1322 if (fulln == NULL) {
1323 if ((ctxt->sax != NULL) &&
1324 (ctxt->sax->error != NULL))
1325 ctxt->sax->error(ctxt->userData,
1326 "SAX.xmlSAX2StartElement(): out of memory\n");
1327 ctxt->errNo = XML_ERR_NO_MEMORY;
1328 ctxt->instate = XML_PARSER_EOF;
1329 ctxt->disableSAX = 1;
1330 return;
1331 }
1332
1333 /*
1334 * Check that the attribute is not declared in the
1335 * serialization
1336 */
1337 att = NULL;
1338 if (atts != NULL) {
1339 i = 0;
1340 att = atts[i];
1341 while (att != NULL) {
1342 if (xmlStrEqual(att, fulln))
1343 break;
1344 i += 2;
1345 att = atts[i];
1346 }
1347 }
1348 if (att == NULL) {
1349 xmlSAX2AttributeInternal(ctxt, fulln,
1350 attr->defaultValue, prefix);
1351 }
1352 if ((fulln != fn) && (fulln != attr->name))
1353 xmlFree(fulln);
1354 }
1355 }
1356 }
1357 attr = attr->nexth;
1358 }
1359 if (internal == 1) {
1360 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset,
1361 name, prefix);
1362 internal = 0;
1363 goto process_external_subset;
1364 }
1365 }
1366}
1367
1368/**
1369 * xmlSAX2StartElement:
1370 * @ctx: the user data (XML parser context)
1371 * @fullname: The element name, including namespace prefix
1372 * @atts: An array of name/value attributes pairs, NULL terminated
1373 *
1374 * called when an opening tag has been processed.
1375 */
1376void
1377xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
1378{
1379 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1380 xmlNodePtr ret;
1381 xmlNodePtr parent = ctxt->node;
1382 xmlNsPtr ns;
1383 xmlChar *name;
1384 xmlChar *prefix;
1385 const xmlChar *att;
1386 const xmlChar *value;
1387 int i;
1388
1389#ifdef DEBUG_SAX
1390 xmlGenericError(xmlGenericErrorContext,
1391 "SAX.xmlSAX2StartElement(%s)\n", fullname);
1392#endif
1393
1394 /*
1395 * First check on validity:
1396 */
1397 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
1398 ((ctxt->myDoc->intSubset == NULL) ||
1399 ((ctxt->myDoc->intSubset->notations == NULL) &&
1400 (ctxt->myDoc->intSubset->elements == NULL) &&
1401 (ctxt->myDoc->intSubset->attributes == NULL) &&
1402 (ctxt->myDoc->intSubset->entities == NULL)))) {
Daniel Veillardf88d8cf2003-12-08 10:25:02 +00001403 xmlErrValid(ctxt, XML_ERR_NO_DTD,
1404 "Validation failed: no DTD found !", NULL, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001405 ctxt->validate = 0;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001406 }
1407
1408
1409 /*
1410 * Split the full name into a namespace prefix and the tag name
1411 */
1412 name = xmlSplitQName(ctxt, fullname, &prefix);
1413
1414
1415 /*
1416 * Note : the namespace resolution is deferred until the end of the
1417 * attributes parsing, since local namespace can be defined as
1418 * an attribute at this level.
1419 */
1420 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL);
1421 if (ret == NULL) {
1422 if (prefix != NULL)
1423 xmlFree(prefix);
1424 ctxt->errNo = XML_ERR_NO_MEMORY;
1425 ctxt->instate = XML_PARSER_EOF;
1426 ctxt->disableSAX = 1;
1427 return;
1428 }
1429 if (ctxt->myDoc->children == NULL) {
1430#ifdef DEBUG_SAX_TREE
1431 xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
1432#endif
1433 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1434 } else if (parent == NULL) {
1435 parent = ctxt->myDoc->children;
1436 }
1437 ctxt->nodemem = -1;
1438 if (ctxt->linenumbers) {
Daniel Veillard3e35f8e2003-10-21 00:05:38 +00001439 if (ctxt->input != NULL) {
1440 if (ctxt->input->line < 65535)
1441 ret->line = (short) ctxt->input->line;
1442 else
1443 ret->line = 65535;
1444 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001445 }
1446
1447 /*
1448 * We are parsing a new node.
1449 */
1450#ifdef DEBUG_SAX_TREE
1451 xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);
1452#endif
1453 nodePush(ctxt, ret);
1454
1455 /*
1456 * Link the child element
1457 */
1458 if (parent != NULL) {
1459 if (parent->type == XML_ELEMENT_NODE) {
1460#ifdef DEBUG_SAX_TREE
1461 xmlGenericError(xmlGenericErrorContext,
1462 "adding child %s to %s\n", name, parent->name);
1463#endif
1464 xmlAddChild(parent, ret);
1465 } else {
1466#ifdef DEBUG_SAX_TREE
1467 xmlGenericError(xmlGenericErrorContext,
1468 "adding sibling %s to ", name);
1469 xmlDebugDumpOneNode(stderr, parent, 0);
1470#endif
1471 xmlAddSibling(parent, ret);
1472 }
1473 }
1474
1475 /*
1476 * Insert all the defaulted attributes from the DTD especially namespaces
1477 */
1478 if ((!ctxt->html) &&
1479 ((ctxt->myDoc->intSubset != NULL) ||
1480 (ctxt->myDoc->extSubset != NULL))) {
1481 xmlCheckDefaultedAttributes(ctxt, name, prefix, atts);
1482 }
1483
1484 /*
1485 * process all the attributes whose name start with "xmlns"
1486 */
1487 if (atts != NULL) {
1488 i = 0;
1489 att = atts[i++];
1490 value = atts[i++];
1491 if (!ctxt->html) {
1492 while ((att != NULL) && (value != NULL)) {
1493 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l') &&
1494 (att[3] == 'n') && (att[4] == 's'))
1495 xmlSAX2AttributeInternal(ctxt, att, value, prefix);
1496
1497 att = atts[i++];
1498 value = atts[i++];
1499 }
1500 }
1501 }
1502
1503 /*
1504 * Search the namespace, note that since the attributes have been
1505 * processed, the local namespaces are available.
1506 */
1507 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
1508 if ((ns == NULL) && (parent != NULL))
1509 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
1510 if ((prefix != NULL) && (ns == NULL)) {
1511 ns = xmlNewNs(ret, NULL, prefix);
1512 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1513 ctxt->sax->warning(ctxt->userData,
1514 "Namespace prefix %s is not defined\n", prefix);
1515 }
1516
1517 /*
1518 * set the namespace node, making sure that if the default namspace
1519 * is unbound on a parent we simply kee it NULL
1520 */
1521 if ((ns != NULL) && (ns->href != NULL) &&
1522 ((ns->href[0] != 0) || (ns->prefix != NULL)))
1523 xmlSetNs(ret, ns);
1524
1525 /*
1526 * process all the other attributes
1527 */
1528 if (atts != NULL) {
1529 i = 0;
1530 att = atts[i++];
1531 value = atts[i++];
1532 if (ctxt->html) {
1533 while (att != NULL) {
1534 xmlSAX2AttributeInternal(ctxt, att, value, NULL);
1535 att = atts[i++];
1536 value = atts[i++];
1537 }
1538 } else {
1539 while ((att != NULL) && (value != NULL)) {
1540 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l') ||
1541 (att[3] != 'n') || (att[4] != 's'))
1542 xmlSAX2AttributeInternal(ctxt, att, value, NULL);
1543
1544 /*
1545 * Next ones
1546 */
1547 att = atts[i++];
1548 value = atts[i++];
1549 }
1550 }
1551 }
1552
Daniel Veillard4432df22003-09-28 18:58:27 +00001553#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001554 /*
1555 * If it's the Document root, finish the DTD validation and
1556 * check the document root element for validity
1557 */
1558 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
1559 int chk;
1560
1561 chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
1562 if (chk <= 0)
1563 ctxt->valid = 0;
1564 if (chk < 0)
1565 ctxt->wellFormed = 0;
1566 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
1567 ctxt->vctxt.finishDtd = 1;
1568 }
Daniel Veillard4432df22003-09-28 18:58:27 +00001569#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001570
1571 if (prefix != NULL)
1572 xmlFree(prefix);
1573
1574}
1575
1576/**
1577 * xmlSAX2EndElement:
1578 * @ctx: the user data (XML parser context)
1579 * @name: The element name
1580 *
1581 * called when the end of an element has been detected.
1582 */
1583void
1584xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
1585{
1586 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1587 xmlParserNodeInfo node_info;
1588 xmlNodePtr cur = ctxt->node;
1589
1590#ifdef DEBUG_SAX
1591 if (name == NULL)
1592 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(NULL)\n");
1593 else
1594 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(%s)\n", name);
1595#endif
1596
1597 /* Capture end position and add node */
1598 if (cur != NULL && ctxt->record_info) {
1599 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
1600 node_info.end_line = ctxt->input->line;
1601 node_info.node = cur;
1602 xmlParserAddNodeInfo(ctxt, &node_info);
1603 }
1604 ctxt->nodemem = -1;
1605
Daniel Veillard4432df22003-09-28 18:58:27 +00001606#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001607 if (ctxt->validate && ctxt->wellFormed &&
1608 ctxt->myDoc && ctxt->myDoc->intSubset)
1609 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
1610 cur);
Daniel Veillard4432df22003-09-28 18:58:27 +00001611#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001612
1613
1614 /*
1615 * end of parsing of this node.
1616 */
1617#ifdef DEBUG_SAX_TREE
1618 xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);
1619#endif
1620 nodePop(ctxt);
1621}
Daniel Veillard81273902003-09-30 00:43:48 +00001622#endif /* LIBXML_SAX1_ENABLED || LIBXML_HTML_ENABLE */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001623
Daniel Veillarde57ec792003-09-10 10:50:59 +00001624/*
Daniel Veillard19895052003-09-17 13:59:32 +00001625 * xmlSAX2TextNode:
1626 * @ctxt: the parser context
1627 * @str: the input string
1628 * @len: the string length
1629 *
1630 * Remove the entities from an attribute value
1631 *
1632 * Returns the newly allocated string or NULL if not needed or error
1633 */
1634static xmlNodePtr
1635xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
1636 xmlNodePtr ret;
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001637 const xmlChar *intern = NULL;
Daniel Veillard19895052003-09-17 13:59:32 +00001638
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001639 /*
1640 * Allocate
1641 */
Daniel Veillard19895052003-09-17 13:59:32 +00001642 if (ctxt->freeElems != NULL) {
1643 ret = ctxt->freeElems;
1644 ctxt->freeElems = ret->next;
1645 ctxt->freeElemsNr--;
Daniel Veillard19895052003-09-17 13:59:32 +00001646 } else {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001647 ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard19895052003-09-17 13:59:32 +00001648 }
1649 if (ret == NULL) {
1650 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1651 ctxt->sax->error(ctxt->userData,
1652 "SAX.xmlSAX2Characters(): out of memory\n");
1653 ctxt->errNo = XML_ERR_NO_MEMORY;
1654 ctxt->instate = XML_PARSER_EOF;
1655 ctxt->disableSAX = 1;
1656 return(NULL);
1657 }
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001658 /*
1659 * intern the formatting blanks found between tags, or the
1660 * very short strings
1661 */
1662 if (ctxt->dictNames) {
1663 xmlChar cur = str[len];
1664
Daniel Veillarddca8cc72003-09-26 13:53:14 +00001665 if ((len <= 3) && ((cur == '"') || (cur == '\'') ||
1666 ((cur == '<') && (str[len + 1] != '!')))) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001667 intern = xmlDictLookup(ctxt->dict, str, len);
William M. Brack76e95df2003-10-18 16:20:14 +00001668 } else if (IS_BLANK_CH(*str) && (len < 60) && (cur == '<') &&
Daniel Veillarddca8cc72003-09-26 13:53:14 +00001669 (str[len + 1] != '!')) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001670 int i;
1671
1672 for (i = 1;i < len;i++) {
Daniel Veillard1a9b7082004-01-02 10:42:01 +00001673 if (!IS_BLANK_CH(str[i])) goto skip;
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001674 }
1675 intern = xmlDictLookup(ctxt->dict, str, len);
1676 }
1677 }
1678skip:
1679 memset(ret, 0, sizeof(xmlNode));
1680 ret->type = XML_TEXT_NODE;
1681
1682 ret->name = xmlStringText;
1683 if (intern == NULL)
1684 ret->content = xmlStrndup(str, len);
1685 else
1686 ret->content = (xmlChar *) intern;
1687
1688 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1689 xmlRegisterNodeDefaultValue(ret);
Daniel Veillard19895052003-09-17 13:59:32 +00001690 return(ret);
1691}
1692
Daniel Veillard4432df22003-09-28 18:58:27 +00001693#ifdef LIBXML_VALID_ENABLED
Daniel Veillard19895052003-09-17 13:59:32 +00001694/*
Daniel Veillarde57ec792003-09-10 10:50:59 +00001695 * xmlSAX2DecodeAttrEntities:
1696 * @ctxt: the parser context
1697 * @str: the input string
1698 * @len: the string length
1699 *
1700 * Remove the entities from an attribute value
1701 *
1702 * Returns the newly allocated string or NULL if not needed or error
1703 */
1704static xmlChar *
1705xmlSAX2DecodeAttrEntities(xmlParserCtxtPtr ctxt, const xmlChar *str,
1706 const xmlChar *end) {
1707 const xmlChar *in;
1708 xmlChar *ret;
1709
1710 in = str;
1711 while (in < end)
1712 if (*in++ == '&')
1713 goto decode;
1714 return(NULL);
1715decode:
1716 ctxt->depth++;
1717 ret = xmlStringLenDecodeEntities(ctxt, str, end - str,
1718 XML_SUBSTITUTE_REF, 0,0,0);
1719 ctxt->depth--;
1720 return(ret);
1721}
Daniel Veillard4432df22003-09-28 18:58:27 +00001722#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00001723
1724/**
1725 * xmlSAX2AttributeNs:
1726 * @ctx: the user data (XML parser context)
Daniel Veillard62998c02003-09-15 12:56:36 +00001727 * @localname: the local name of the attribute
1728 * @prefix: the attribute namespace prefix if available
1729 * @URI: the attribute namespace name if available
Daniel Veillarde57ec792003-09-10 10:50:59 +00001730 * @value: Start of the attribute value
1731 * @valueend: end of the attribute value
1732 *
1733 * Handle an attribute that has been read by the parser.
1734 * The default handling is to convert the attribute into an
1735 * DOM subtree and past it in a new xmlAttr element added to
1736 * the element.
1737 */
1738static void
1739xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
1740 const xmlChar * localname,
1741 const xmlChar * prefix,
1742 const xmlChar * value,
1743 const xmlChar * valueend)
1744{
1745 xmlAttrPtr ret;
1746 xmlNsPtr namespace = NULL;
1747 xmlChar *dup = NULL;
1748
Daniel Veillarde57ec792003-09-10 10:50:59 +00001749 /*
1750 * Note: if prefix == NULL, the attribute is not in the default namespace
1751 */
1752 if (prefix != NULL)
1753 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, prefix);
1754
Daniel Veillard8a44e592003-09-15 14:50:06 +00001755 /*
1756 * allocate the node
1757 */
1758 if (ctxt->freeAttrs != NULL) {
1759 ret = ctxt->freeAttrs;
1760 ctxt->freeAttrs = ret->next;
Daniel Veillard19895052003-09-17 13:59:32 +00001761 ctxt->freeAttrsNr--;
Daniel Veillard8a44e592003-09-15 14:50:06 +00001762 memset(ret, 0, sizeof(xmlAttr));
1763 ret->type = XML_ATTRIBUTE_NODE;
Daniel Veillarde57ec792003-09-10 10:50:59 +00001764
Daniel Veillard8a44e592003-09-15 14:50:06 +00001765 ret->parent = ctxt->node;
1766 ret->doc = ctxt->myDoc;
1767 ret->ns = namespace;
Daniel Veillarde57ec792003-09-10 10:50:59 +00001768
Daniel Veillard8a44e592003-09-15 14:50:06 +00001769 if (ctxt->dictNames)
1770 ret->name = localname;
1771 else
1772 ret->name = xmlStrdup(localname);
1773
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001774 /* link at the end to preserv order, TODO speed up with a last */
1775 if (ctxt->node->properties == NULL) {
1776 ctxt->node->properties = ret;
1777 } else {
1778 xmlAttrPtr prev = ctxt->node->properties;
1779
1780 while (prev->next != NULL) prev = prev->next;
1781 prev->next = ret;
1782 ret->prev = prev;
1783 }
1784
Daniel Veillard8a44e592003-09-15 14:50:06 +00001785 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1786 xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
1787 } else {
1788 if (ctxt->dictNames)
1789 ret = xmlNewNsPropEatName(ctxt->node, namespace,
1790 (xmlChar *) localname, NULL);
1791 else
1792 ret = xmlNewNsProp(ctxt->node, namespace, localname, NULL);
1793 if (ret == NULL) {
1794 ctxt->errNo = XML_ERR_NO_MEMORY;
1795 ctxt->instate = XML_PARSER_EOF;
1796 ctxt->disableSAX = 1;
1797 return;
Daniel Veillarde57ec792003-09-10 10:50:59 +00001798 }
1799 }
1800
Daniel Veillard8a44e592003-09-15 14:50:06 +00001801 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
1802 xmlNodePtr tmp;
1803
Daniel Veillard19895052003-09-17 13:59:32 +00001804 /*
1805 * We know that if there is an entity reference, then
1806 * the string has been dup'ed and terminates with 0
1807 * otherwise with ' or "
1808 */
1809 if (*valueend != 0) {
1810 tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
1811 ret->children = tmp;
1812 ret->last = tmp;
1813 if (tmp != NULL) {
1814 tmp->doc = ret->doc;
1815 tmp->parent = (xmlNodePtr) ret;
1816 }
1817 } else {
1818 ret->children = xmlStringLenGetNodeList(ctxt->myDoc, value,
1819 valueend - value);
1820 tmp = ret->children;
1821 while (tmp != NULL) {
1822 tmp->parent = (xmlNodePtr) ret;
1823 if (tmp->next == NULL)
1824 ret->last = tmp;
1825 tmp = tmp->next;
1826 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00001827 }
1828 } else if (value != NULL) {
Daniel Veillard19895052003-09-17 13:59:32 +00001829 xmlNodePtr tmp;
1830
1831 tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
1832 ret->children = tmp;
1833 ret->last = tmp;
1834 if (tmp != NULL) {
1835 tmp->doc = ret->doc;
1836 tmp->parent = (xmlNodePtr) ret;
1837 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00001838 }
1839
Daniel Veillard4432df22003-09-28 18:58:27 +00001840#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00001841 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
1842 ctxt->myDoc && ctxt->myDoc->intSubset) {
1843 /*
1844 * If we don't substitute entities, the validation should be
1845 * done on a value with replaced entities anyway.
1846 */
1847 if (!ctxt->replaceEntities) {
1848 dup = xmlSAX2DecodeAttrEntities(ctxt, value, valueend);
1849 if (dup == NULL) {
Daniel Veillard62998c02003-09-15 12:56:36 +00001850 if (*valueend == 0) {
1851 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1852 ctxt->myDoc, ctxt->node, ret, value);
1853 } else {
1854 /*
1855 * That should already be normalized.
1856 * cheaper to finally allocate here than duplicate
1857 * entry points in the full validation code
1858 */
1859 dup = xmlStrndup(value, valueend - value);
Daniel Veillarde57ec792003-09-10 10:50:59 +00001860
Daniel Veillard62998c02003-09-15 12:56:36 +00001861 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1862 ctxt->myDoc, ctxt->node, ret, dup);
1863 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00001864 } else {
Daniel Veillard62998c02003-09-15 12:56:36 +00001865 /*
1866 * dup now contains a string of the flattened attribute
1867 * content with entities substitued. Check if we need to
1868 * apply an extra layer of normalization.
Daniel Veillarde57ec792003-09-10 10:50:59 +00001869 * It need to be done twice ... it's an extra burden related
1870 * to the ability to keep references in attributes
1871 */
Daniel Veillard62998c02003-09-15 12:56:36 +00001872 if (ctxt->attsSpecial != NULL) {
1873 xmlChar *nvalnorm;
1874 xmlChar fn[50];
1875 xmlChar *fullname;
1876
1877 fullname = xmlBuildQName(localname, prefix, fn, 50);
1878 if (fullname != NULL) {
1879 ctxt->vctxt.valid = 1;
1880 nvalnorm = xmlValidCtxtNormalizeAttributeValue(
1881 &ctxt->vctxt, ctxt->myDoc,
1882 ctxt->node, fullname, dup);
1883 if (ctxt->vctxt.valid != 1)
1884 ctxt->valid = 0;
1885
1886 if ((fullname != fn) && (fullname != localname))
1887 xmlFree(fullname);
1888 if (nvalnorm != NULL) {
1889 xmlFree(dup);
1890 dup = nvalnorm;
1891 }
1892 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00001893 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00001894
1895 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1896 ctxt->myDoc, ctxt->node, ret, dup);
1897 }
1898 } else {
Daniel Veillard8e36e6a2003-09-10 10:50:59 +00001899 /*
1900 * if entities already have been substitued, then
1901 * the attribute as passed is already normalized
1902 */
Daniel Veillarde57ec792003-09-10 10:50:59 +00001903 dup = xmlStrndup(value, valueend - value);
1904
1905 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1906 ctxt->myDoc, ctxt->node, ret, dup);
1907 }
Daniel Veillard4432df22003-09-28 18:58:27 +00001908 } else
1909#endif /* LIBXML_VALID_ENABLED */
1910 if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
Daniel Veillarde57ec792003-09-10 10:50:59 +00001911 (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
1912 ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
1913 /*
1914 * when validating, the ID registration is done at the attribute
1915 * validation level. Otherwise we have to do specific handling here.
1916 */
1917 if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) {
1918 /* might be worth duplicate entry points and not copy */
1919 if (dup == NULL)
1920 dup = xmlStrndup(value, valueend - value);
1921 xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
1922 } else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) {
1923 if (dup == NULL)
1924 dup = xmlStrndup(value, valueend - value);
1925 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, dup, ret);
1926 }
1927 }
1928 if (dup != NULL)
1929 xmlFree(dup);
1930}
1931
1932/**
1933 * xmlSAX2StartElementNs:
1934 * @ctx: the user data (XML parser context)
1935 * @localname: the local name of the element
1936 * @prefix: the element namespace prefix if available
1937 * @URI: the element namespace name if available
1938 * @nb_namespaces: number of namespace definitions on that node
1939 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
1940 * @nb_attributes: the number of attributes on that node
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00001941 * @nb_defaulted: the number of defaulted attributes.
Daniel Veillarde57ec792003-09-10 10:50:59 +00001942 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
1943 * attribute values.
1944 *
1945 * SAX2 callback when an element start has been detected by the parser.
1946 * It provides the namespace informations for the element, as well as
1947 * the new namespace declarations on the element.
1948 */
1949void
1950xmlSAX2StartElementNs(void *ctx,
1951 const xmlChar *localname,
1952 const xmlChar *prefix,
1953 const xmlChar *URI,
1954 int nb_namespaces,
1955 const xmlChar **namespaces,
1956 int nb_attributes,
1957 int nb_defaulted,
1958 const xmlChar **attributes)
1959{
1960 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1961 xmlNodePtr ret;
1962 xmlNodePtr parent = ctxt->node;
1963 xmlNsPtr last = NULL, ns;
1964 const xmlChar *uri, *pref;
1965 int i, j;
1966
1967 /*
1968 * First check on validity:
1969 */
1970 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
1971 ((ctxt->myDoc->intSubset == NULL) ||
1972 ((ctxt->myDoc->intSubset->notations == NULL) &&
1973 (ctxt->myDoc->intSubset->elements == NULL) &&
1974 (ctxt->myDoc->intSubset->attributes == NULL) &&
1975 (ctxt->myDoc->intSubset->entities == NULL)))) {
Daniel Veillardf88d8cf2003-12-08 10:25:02 +00001976 xmlErrValid(ctxt, XML_ERR_NO_DTD,
1977 "Validation failed: no DTD found !", NULL, NULL);
Daniel Veillarde57ec792003-09-10 10:50:59 +00001978 ctxt->validate = 0;
Daniel Veillarde57ec792003-09-10 10:50:59 +00001979 }
1980
Daniel Veillard8a44e592003-09-15 14:50:06 +00001981 /*
1982 * allocate the node
1983 */
1984 if (ctxt->freeElems != NULL) {
1985 ret = ctxt->freeElems;
1986 ctxt->freeElems = ret->next;
Daniel Veillard19895052003-09-17 13:59:32 +00001987 ctxt->freeElemsNr--;
Daniel Veillard8a44e592003-09-15 14:50:06 +00001988 memset(ret, 0, sizeof(xmlNode));
1989 ret->type = XML_ELEMENT_NODE;
1990
1991 if (ctxt->dictNames)
1992 ret->name = localname;
1993 else
1994 ret->name = xmlStrdup(localname);
1995
1996 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1997 xmlRegisterNodeDefaultValue(ret);
1998 } else {
1999 if (ctxt->dictNames)
2000 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
2001 (xmlChar *) localname, NULL);
2002 else
2003 ret = xmlNewDocNode(ctxt->myDoc, NULL, localname, NULL);
2004 if (ret == NULL) {
2005 ctxt->errNo = XML_ERR_NO_MEMORY;
2006 ctxt->instate = XML_PARSER_EOF;
2007 ctxt->disableSAX = 1;
2008 return;
2009 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002010 }
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002011 if (ctxt->linenumbers) {
Daniel Veillard3e35f8e2003-10-21 00:05:38 +00002012 if (ctxt->input != NULL) {
2013 if (ctxt->input->line < 65535)
2014 ret->line = (short) ctxt->input->line;
2015 else
2016 ret->line = 65535;
2017 }
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002018 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00002019
Daniel Veillarde57ec792003-09-10 10:50:59 +00002020 if (ctxt->myDoc->children == NULL) {
2021 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2022 } else if (parent == NULL) {
2023 parent = ctxt->myDoc->children;
2024 }
2025 /*
2026 * Build the namespace list
2027 */
2028 for (i = 0,j = 0;j < nb_namespaces;j++) {
2029 pref = namespaces[i++];
2030 uri = namespaces[i++];
2031 ns = xmlNewNs(NULL, uri, pref);
2032 if (ns != NULL) {
2033 if (last == NULL) {
2034 ret->nsDef = last = ns;
2035 } else {
2036 last->next = ns;
2037 last = ns;
2038 }
2039 if ((URI != NULL) && (prefix == pref))
2040 ret->ns = ns;
2041 } else {
2042 ctxt->errNo = XML_ERR_NO_MEMORY;
2043 ctxt->instate = XML_PARSER_EOF;
2044 ctxt->disableSAX = 1;
2045 return;
2046 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002047#ifdef LIBXML_VALID_ENABLED
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002048 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
2049 ctxt->myDoc && ctxt->myDoc->intSubset) {
2050 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
2051 ret, prefix, ns, uri);
2052 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002053#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002054 }
2055 ctxt->nodemem = -1;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002056
2057 /*
2058 * We are parsing a new node.
2059 */
2060 nodePush(ctxt, ret);
2061
2062 /*
2063 * Link the child element
2064 */
2065 if (parent != NULL) {
2066 if (parent->type == XML_ELEMENT_NODE) {
2067 xmlAddChild(parent, ret);
2068 } else {
2069 xmlAddSibling(parent, ret);
2070 }
2071 }
2072
2073 /*
2074 * Insert the defaulted attributes from the DTD only if requested:
2075 */
2076 if ((nb_defaulted != 0) &&
2077 ((ctxt->loadsubset & XML_COMPLETE_ATTRS) == 0))
2078 nb_attributes -= nb_defaulted;
2079
2080 /*
2081 * Search the namespace if it wasn't already found
2082 */
2083 if ((URI != NULL) && (ret->ns == NULL)) {
2084 ret->ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
2085 if (ret->ns == NULL) {
2086 ns = xmlNewNs(ret, NULL, prefix);
2087 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
2088 ctxt->sax->warning(ctxt->userData,
2089 "Namespace prefix %s was not found\n", prefix);
2090 }
2091 }
2092
2093 /*
2094 * process all the other attributes
2095 */
2096 if (nb_attributes > 0) {
2097 for (j = 0,i = 0;i < nb_attributes;i++,j+=5) {
2098 xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1],
2099 attributes[j+3], attributes[j+4]);
2100 }
2101 }
2102
Daniel Veillard4432df22003-09-28 18:58:27 +00002103#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002104 /*
2105 * If it's the Document root, finish the DTD validation and
2106 * check the document root element for validity
2107 */
2108 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
2109 int chk;
2110
2111 chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
2112 if (chk <= 0)
2113 ctxt->valid = 0;
2114 if (chk < 0)
2115 ctxt->wellFormed = 0;
2116 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
2117 ctxt->vctxt.finishDtd = 1;
2118 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002119#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002120}
2121
2122/**
2123 * xmlSAX2EndElementNs:
2124 * @ctx: the user data (XML parser context)
2125 * @localname: the local name of the element
2126 * @prefix: the element namespace prefix if available
2127 * @URI: the element namespace name if available
2128 *
2129 * SAX2 callback when an element end has been detected by the parser.
2130 * It provides the namespace informations for the element.
2131 */
2132void
2133xmlSAX2EndElementNs(void *ctx,
2134 const xmlChar * localname ATTRIBUTE_UNUSED,
2135 const xmlChar * prefix ATTRIBUTE_UNUSED,
2136 const xmlChar * URI ATTRIBUTE_UNUSED)
2137{
2138 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2139 xmlParserNodeInfo node_info;
2140 xmlNodePtr cur = ctxt->node;
2141
2142 /* Capture end position and add node */
2143 if ((ctxt->record_info) && (cur != NULL)) {
2144 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
2145 node_info.end_line = ctxt->input->line;
2146 node_info.node = cur;
2147 xmlParserAddNodeInfo(ctxt, &node_info);
2148 }
2149 ctxt->nodemem = -1;
2150
Daniel Veillard4432df22003-09-28 18:58:27 +00002151#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002152 if (ctxt->validate && ctxt->wellFormed &&
2153 ctxt->myDoc && ctxt->myDoc->intSubset)
2154 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, cur);
Daniel Veillard4432df22003-09-28 18:58:27 +00002155#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002156
2157 /*
2158 * end of parsing of this node.
2159 */
2160 nodePop(ctxt);
2161}
2162
Daniel Veillard1af9a412003-08-20 22:54:39 +00002163/**
2164 * xmlSAX2Reference:
2165 * @ctx: the user data (XML parser context)
2166 * @name: The entity name
2167 *
2168 * called when an entity xmlSAX2Reference is detected.
2169 */
2170void
2171xmlSAX2Reference(void *ctx, const xmlChar *name)
2172{
2173 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2174 xmlNodePtr ret;
2175
2176#ifdef DEBUG_SAX
2177 xmlGenericError(xmlGenericErrorContext,
2178 "SAX.xmlSAX2Reference(%s)\n", name);
2179#endif
2180 if (name[0] == '#')
2181 ret = xmlNewCharRef(ctxt->myDoc, name);
2182 else
2183 ret = xmlNewReference(ctxt->myDoc, name);
2184#ifdef DEBUG_SAX_TREE
2185 xmlGenericError(xmlGenericErrorContext,
2186 "add xmlSAX2Reference %s to %s \n", name, ctxt->node->name);
2187#endif
2188 xmlAddChild(ctxt->node, ret);
2189}
2190
2191/**
2192 * xmlSAX2Characters:
2193 * @ctx: the user data (XML parser context)
2194 * @ch: a xmlChar string
2195 * @len: the number of xmlChar
2196 *
2197 * receiving some chars from the parser.
2198 */
2199void
2200xmlSAX2Characters(void *ctx, const xmlChar *ch, int len)
2201{
2202 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2203 xmlNodePtr lastChild;
2204
2205#ifdef DEBUG_SAX
2206 xmlGenericError(xmlGenericErrorContext,
2207 "SAX.xmlSAX2Characters(%.30s, %d)\n", ch, len);
2208#endif
2209 /*
2210 * Handle the data if any. If there is no child
2211 * add it as content, otherwise if the last child is text,
2212 * concatenate it, else create a new node of type text.
2213 */
2214
2215 if (ctxt->node == NULL) {
2216#ifdef DEBUG_SAX_TREE
2217 xmlGenericError(xmlGenericErrorContext,
2218 "add chars: ctxt->node == NULL !\n");
2219#endif
2220 return;
2221 }
Daniel Veillard19895052003-09-17 13:59:32 +00002222 lastChild = ctxt->node->last;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002223#ifdef DEBUG_SAX_TREE
2224 xmlGenericError(xmlGenericErrorContext,
2225 "add chars to %s \n", ctxt->node->name);
2226#endif
2227
2228 /*
2229 * Here we needed an accelerator mechanism in case of very large
2230 * elements. Use an attribute in the structure !!!
2231 */
2232 if (lastChild == NULL) {
Daniel Veillard19895052003-09-17 13:59:32 +00002233 lastChild = xmlSAX2TextNode(ctxt, ch, len);
2234 if (lastChild != NULL) {
2235 ctxt->node->children = lastChild;
2236 ctxt->node->last = lastChild;
2237 lastChild->parent = ctxt->node;
2238 lastChild->doc = ctxt->node->doc;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002239 ctxt->nodelen = len;
2240 ctxt->nodemem = len + 1;
2241 }
2242 } else {
2243 int coalesceText = (lastChild != NULL) &&
2244 (lastChild->type == XML_TEXT_NODE) &&
2245 (lastChild->name == xmlStringText);
2246 if ((coalesceText) && (ctxt->nodemem != 0)) {
2247 /*
2248 * The whole point of maintaining nodelen and nodemem,
2249 * xmlTextConcat is too costly, i.e. compute length,
2250 * reallocate a new buffer, move data, append ch. Here
2251 * We try to minimaze realloc() uses and avoid copying
2252 * and recomputing length over and over.
2253 */
Daniel Veillard2b0f8792003-10-10 19:36:36 +00002254 if ((ctxt->nodemem == ctxt->nodelen + 1) &&
2255 (xmlDictOwns(ctxt->dict, lastChild->content))) {
2256 lastChild->content = xmlStrdup(lastChild->content);
2257 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00002258 if (ctxt->nodelen + len >= ctxt->nodemem) {
2259 xmlChar *newbuf;
2260 int size;
2261
2262 size = ctxt->nodemem + len;
2263 size *= 2;
2264 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
2265 if (newbuf == NULL) {
2266 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2267 ctxt->sax->error(ctxt->userData,
2268 "SAX.xmlSAX2Characters(): out of memory\n");
2269 ctxt->errNo = XML_ERR_NO_MEMORY;
2270 ctxt->instate = XML_PARSER_EOF;
2271 ctxt->disableSAX = 1;
2272 return;
2273 }
2274 ctxt->nodemem = size;
2275 lastChild->content = newbuf;
2276 }
2277 memcpy(&lastChild->content[ctxt->nodelen], ch, len);
2278 ctxt->nodelen += len;
2279 lastChild->content[ctxt->nodelen] = 0;
2280 } else if (coalesceText) {
2281 if (xmlTextConcat(lastChild, ch, len)) {
2282 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2283 ctxt->sax->error(ctxt->userData,
2284 "SAX.xmlSAX2Characters(): out of memory\n");
2285 ctxt->errNo = XML_ERR_NO_MEMORY;
2286 ctxt->instate = XML_PARSER_EOF;
2287 ctxt->disableSAX = 1;
2288 }
2289 if (ctxt->node->children != NULL) {
2290 ctxt->nodelen = xmlStrlen(lastChild->content);
2291 ctxt->nodemem = ctxt->nodelen + 1;
2292 }
2293 } else {
2294 /* Mixed content, first time */
Daniel Veillard19895052003-09-17 13:59:32 +00002295 lastChild = xmlSAX2TextNode(ctxt, ch, len);
2296 if (lastChild != NULL) {
Daniel Veillard1af9a412003-08-20 22:54:39 +00002297 xmlAddChild(ctxt->node, lastChild);
2298 if (ctxt->node->children != NULL) {
2299 ctxt->nodelen = len;
2300 ctxt->nodemem = len + 1;
2301 }
2302 }
2303 }
2304 }
2305}
2306
2307/**
2308 * xmlSAX2IgnorableWhitespace:
2309 * @ctx: the user data (XML parser context)
2310 * @ch: a xmlChar string
2311 * @len: the number of xmlChar
2312 *
2313 * receiving some ignorable whitespaces from the parser.
2314 * UNUSED: by default the DOM building will use xmlSAX2Characters
2315 */
2316void
2317xmlSAX2IgnorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
2318{
2319 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
2320#ifdef DEBUG_SAX
2321 xmlGenericError(xmlGenericErrorContext,
2322 "SAX.xmlSAX2IgnorableWhitespace(%.30s, %d)\n", ch, len);
2323#endif
2324}
2325
2326/**
2327 * xmlSAX2ProcessingInstruction:
2328 * @ctx: the user data (XML parser context)
2329 * @target: the target name
2330 * @data: the PI data's
2331 *
2332 * A processing instruction has been parsed.
2333 */
2334void
2335xmlSAX2ProcessingInstruction(void *ctx, const xmlChar *target,
2336 const xmlChar *data)
2337{
2338 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2339 xmlNodePtr ret;
2340 xmlNodePtr parent = ctxt->node;
2341
2342#ifdef DEBUG_SAX
2343 xmlGenericError(xmlGenericErrorContext,
2344 "SAX.xmlSAX2ProcessingInstruction(%s, %s)\n", target, data);
2345#endif
2346
2347 ret = xmlNewPI(target, data);
2348 if (ret == NULL) return;
2349 parent = ctxt->node;
2350
2351 if (ctxt->inSubset == 1) {
2352 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2353 return;
2354 } else if (ctxt->inSubset == 2) {
2355 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2356 return;
2357 }
2358 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
2359#ifdef DEBUG_SAX_TREE
2360 xmlGenericError(xmlGenericErrorContext,
2361 "Setting PI %s as root\n", target);
2362#endif
2363 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2364 return;
2365 }
2366 if (parent->type == XML_ELEMENT_NODE) {
2367#ifdef DEBUG_SAX_TREE
2368 xmlGenericError(xmlGenericErrorContext,
2369 "adding PI %s child to %s\n", target, parent->name);
2370#endif
2371 xmlAddChild(parent, ret);
2372 } else {
2373#ifdef DEBUG_SAX_TREE
2374 xmlGenericError(xmlGenericErrorContext,
2375 "adding PI %s sibling to ", target);
2376 xmlDebugDumpOneNode(stderr, parent, 0);
2377#endif
2378 xmlAddSibling(parent, ret);
2379 }
2380}
2381
2382/**
2383 * xmlSAX2Comment:
2384 * @ctx: the user data (XML parser context)
2385 * @value: the xmlSAX2Comment content
2386 *
2387 * A xmlSAX2Comment has been parsed.
2388 */
2389void
2390xmlSAX2Comment(void *ctx, const xmlChar *value)
2391{
2392 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2393 xmlNodePtr ret;
2394 xmlNodePtr parent = ctxt->node;
2395
2396#ifdef DEBUG_SAX
2397 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2Comment(%s)\n", value);
2398#endif
2399 ret = xmlNewDocComment(ctxt->myDoc, value);
2400 if (ret == NULL) return;
2401
2402 if (ctxt->inSubset == 1) {
2403 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2404 return;
2405 } else if (ctxt->inSubset == 2) {
2406 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2407 return;
2408 }
2409 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
2410#ifdef DEBUG_SAX_TREE
2411 xmlGenericError(xmlGenericErrorContext,
2412 "Setting xmlSAX2Comment as root\n");
2413#endif
2414 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2415 return;
2416 }
2417 if (parent->type == XML_ELEMENT_NODE) {
2418#ifdef DEBUG_SAX_TREE
2419 xmlGenericError(xmlGenericErrorContext,
2420 "adding xmlSAX2Comment child to %s\n", parent->name);
2421#endif
2422 xmlAddChild(parent, ret);
2423 } else {
2424#ifdef DEBUG_SAX_TREE
2425 xmlGenericError(xmlGenericErrorContext,
2426 "adding xmlSAX2Comment sibling to ");
2427 xmlDebugDumpOneNode(stderr, parent, 0);
2428#endif
2429 xmlAddSibling(parent, ret);
2430 }
2431}
2432
2433/**
2434 * xmlSAX2CDataBlock:
2435 * @ctx: the user data (XML parser context)
2436 * @value: The pcdata content
2437 * @len: the block length
2438 *
2439 * called when a pcdata block has been parsed
2440 */
2441void
2442xmlSAX2CDataBlock(void *ctx, const xmlChar *value, int len)
2443{
2444 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2445 xmlNodePtr ret, lastChild;
2446
2447#ifdef DEBUG_SAX
2448 xmlGenericError(xmlGenericErrorContext,
2449 "SAX.pcdata(%.10s, %d)\n", value, len);
2450#endif
2451 lastChild = xmlGetLastChild(ctxt->node);
2452#ifdef DEBUG_SAX_TREE
2453 xmlGenericError(xmlGenericErrorContext,
2454 "add chars to %s \n", ctxt->node->name);
2455#endif
2456 if ((lastChild != NULL) &&
2457 (lastChild->type == XML_CDATA_SECTION_NODE)) {
2458 xmlTextConcat(lastChild, value, len);
2459 } else {
2460 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
2461 xmlAddChild(ctxt->node, ret);
2462 }
2463}
2464
Daniel Veillard62998c02003-09-15 12:56:36 +00002465static int xmlSAX2DefaultVersionValue = 2;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002466
Daniel Veillard81273902003-09-30 00:43:48 +00002467#ifdef LIBXML_SAX1_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002468/**
2469 * xmlSAXDefaultVersion:
2470 * @version: the version, 1 or 2
2471 *
2472 * Set the default version of SAX used globally by the library.
2473 * Note that this may not be a good thing to do from a library
2474 * it is better to use xmlSAXVersion() to set up specifically the
2475 * version for a given parsing context.
2476 *
2477 * Returns the previous value in case of success and -1 in case of error.
2478 */
2479int
2480xmlSAXDefaultVersion(int version)
2481{
2482 int ret = xmlSAX2DefaultVersionValue;
2483
2484 if ((version != 1) && (version != 2))
2485 return(-1);
2486 xmlSAX2DefaultVersionValue = version;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002487 return(ret);
2488}
Daniel Veillard81273902003-09-30 00:43:48 +00002489#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002490
2491/**
2492 * xmlSAXVersion:
2493 * @hdlr: the SAX handler
2494 * @version: the version, 1 or 2
2495 *
2496 * Initialize the default XML SAX handler according to the version
2497 *
2498 * Returns 0 in case of success and -1 in case of error.
2499 */
2500int
2501xmlSAXVersion(xmlSAXHandler *hdlr, int version)
2502{
2503 if (hdlr == NULL) return(-1);
Daniel Veillard81273902003-09-30 00:43:48 +00002504 if (version == 2) {
Daniel Veillarde57ec792003-09-10 10:50:59 +00002505 hdlr->startElement = NULL;
2506 hdlr->endElement = NULL;
2507 hdlr->startElementNs = xmlSAX2StartElementNs;
2508 hdlr->endElementNs = xmlSAX2EndElementNs;
Daniel Veillardffbbed42003-10-10 14:46:54 +00002509 hdlr->serror = NULL;
Daniel Veillard092643b2003-09-25 14:29:29 +00002510 hdlr->initialized = XML_SAX2_MAGIC;
Daniel Veillard81273902003-09-30 00:43:48 +00002511#ifdef LIBXML_SAX1_ENABLED
2512 } else if (version == 1) {
2513 hdlr->startElement = xmlSAX2StartElement;
2514 hdlr->endElement = xmlSAX2EndElement;
2515 hdlr->initialized = 1;
2516#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002517 } else
2518 return(-1);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002519 hdlr->internalSubset = xmlSAX2InternalSubset;
2520 hdlr->externalSubset = xmlSAX2ExternalSubset;
2521 hdlr->isStandalone = xmlSAX2IsStandalone;
2522 hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
2523 hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
2524 hdlr->resolveEntity = xmlSAX2ResolveEntity;
2525 hdlr->getEntity = xmlSAX2GetEntity;
2526 hdlr->getParameterEntity = xmlSAX2GetParameterEntity;
2527 hdlr->entityDecl = xmlSAX2EntityDecl;
2528 hdlr->attributeDecl = xmlSAX2AttributeDecl;
2529 hdlr->elementDecl = xmlSAX2ElementDecl;
2530 hdlr->notationDecl = xmlSAX2NotationDecl;
2531 hdlr->unparsedEntityDecl = xmlSAX2UnparsedEntityDecl;
2532 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2533 hdlr->startDocument = xmlSAX2StartDocument;
2534 hdlr->endDocument = xmlSAX2EndDocument;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002535 hdlr->reference = xmlSAX2Reference;
2536 hdlr->characters = xmlSAX2Characters;
2537 hdlr->cdataBlock = xmlSAX2CDataBlock;
2538 hdlr->ignorableWhitespace = xmlSAX2Characters;
2539 hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
2540 hdlr->comment = xmlSAX2Comment;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002541 hdlr->warning = xmlParserWarning;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002542 hdlr->error = xmlParserError;
2543 hdlr->fatalError = xmlParserError;
2544
Daniel Veillarde57ec792003-09-10 10:50:59 +00002545 return(0);
2546}
2547
2548/**
2549 * xmlSAX2InitDefaultSAXHandler:
2550 * @hdlr: the SAX handler
2551 * @warning: flag if non-zero sets the handler warning procedure
2552 *
2553 * Initialize the default XML SAX2 handler
2554 */
2555void
2556xmlSAX2InitDefaultSAXHandler(xmlSAXHandler *hdlr, int warning)
2557{
2558 if ((hdlr == NULL) || (hdlr->initialized != 0))
2559 return;
2560
2561 xmlSAXVersion(hdlr, xmlSAX2DefaultVersionValue);
2562 if (warning == 0)
2563 hdlr->warning = NULL;
2564 else
2565 hdlr->warning = xmlParserWarning;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002566}
2567
2568/**
2569 * xmlDefaultSAXHandlerInit:
2570 *
2571 * Initialize the default SAX2 handler
2572 */
2573void
2574xmlDefaultSAXHandlerInit(void)
2575{
Daniel Veillard81273902003-09-30 00:43:48 +00002576#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard092643b2003-09-25 14:29:29 +00002577 xmlSAXVersion((xmlSAXHandlerPtr) &xmlDefaultSAXHandler, 1);
Daniel Veillard81273902003-09-30 00:43:48 +00002578#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00002579}
2580
2581#ifdef LIBXML_HTML_ENABLED
2582
2583/**
2584 * xmlSAX2InitHtmlDefaultSAXHandler:
2585 * @hdlr: the SAX handler
2586 *
2587 * Initialize the default HTML SAX2 handler
2588 */
2589void
2590xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr)
2591{
2592 if(hdlr->initialized != 0)
2593 return;
2594
2595 hdlr->internalSubset = xmlSAX2InternalSubset;
2596 hdlr->externalSubset = NULL;
2597 hdlr->isStandalone = NULL;
2598 hdlr->hasInternalSubset = NULL;
2599 hdlr->hasExternalSubset = NULL;
2600 hdlr->resolveEntity = NULL;
2601 hdlr->getEntity = xmlSAX2GetEntity;
2602 hdlr->getParameterEntity = NULL;
2603 hdlr->entityDecl = NULL;
2604 hdlr->attributeDecl = NULL;
2605 hdlr->elementDecl = NULL;
2606 hdlr->notationDecl = NULL;
2607 hdlr->unparsedEntityDecl = NULL;
2608 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2609 hdlr->startDocument = xmlSAX2StartDocument;
2610 hdlr->endDocument = xmlSAX2EndDocument;
2611 hdlr->startElement = xmlSAX2StartElement;
2612 hdlr->endElement = xmlSAX2EndElement;
2613 hdlr->reference = NULL;
2614 hdlr->characters = xmlSAX2Characters;
2615 hdlr->cdataBlock = xmlSAX2CDataBlock;
2616 hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
2617 hdlr->processingInstruction = NULL;
2618 hdlr->comment = xmlSAX2Comment;
2619 hdlr->warning = xmlParserWarning;
2620 hdlr->error = xmlParserError;
2621 hdlr->fatalError = xmlParserError;
2622
Daniel Veillard092643b2003-09-25 14:29:29 +00002623 hdlr->initialized = 1;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002624}
2625
2626/**
2627 * htmlDefaultSAXHandlerInit:
2628 *
2629 * Initialize the default SAX handler
2630 */
2631void
2632htmlDefaultSAXHandlerInit(void)
2633{
Daniel Veillard092643b2003-09-25 14:29:29 +00002634 xmlSAX2InitHtmlDefaultSAXHandler((xmlSAXHandlerPtr) &htmlDefaultSAXHandler);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002635}
2636
2637#endif /* LIBXML_HTML_ENABLED */
2638
2639#ifdef LIBXML_DOCB_ENABLED
2640
2641/**
2642 * xmlSAX2InitDocbDefaultSAXHandler:
2643 * @hdlr: the SAX handler
2644 *
2645 * Initialize the default DocBook SAX2 handler
2646 */
2647void
2648xmlSAX2InitDocbDefaultSAXHandler(xmlSAXHandler *hdlr)
2649{
2650 if(hdlr->initialized != 0)
2651 return;
2652
2653 hdlr->internalSubset = xmlSAX2InternalSubset;
2654 hdlr->externalSubset = NULL;
2655 hdlr->isStandalone = xmlSAX2IsStandalone;
2656 hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
2657 hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
2658 hdlr->resolveEntity = xmlSAX2ResolveEntity;
2659 hdlr->getEntity = xmlSAX2GetEntity;
2660 hdlr->getParameterEntity = NULL;
2661 hdlr->entityDecl = xmlSAX2EntityDecl;
2662 hdlr->attributeDecl = NULL;
2663 hdlr->elementDecl = NULL;
2664 hdlr->notationDecl = NULL;
2665 hdlr->unparsedEntityDecl = NULL;
2666 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2667 hdlr->startDocument = xmlSAX2StartDocument;
2668 hdlr->endDocument = xmlSAX2EndDocument;
2669 hdlr->startElement = xmlSAX2StartElement;
2670 hdlr->endElement = xmlSAX2EndElement;
2671 hdlr->reference = xmlSAX2Reference;
2672 hdlr->characters = xmlSAX2Characters;
2673 hdlr->cdataBlock = NULL;
2674 hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
2675 hdlr->processingInstruction = NULL;
2676 hdlr->comment = xmlSAX2Comment;
2677 hdlr->warning = xmlParserWarning;
2678 hdlr->error = xmlParserError;
2679 hdlr->fatalError = xmlParserError;
2680
Daniel Veillardffbbed42003-10-10 14:46:54 +00002681 hdlr->initialized = 1;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002682}
2683
2684/**
2685 * docbDefaultSAXHandlerInit:
2686 *
2687 * Initialize the default SAX handler
2688 */
2689void
2690docbDefaultSAXHandlerInit(void)
2691{
Daniel Veillard092643b2003-09-25 14:29:29 +00002692 xmlSAX2InitDocbDefaultSAXHandler((xmlSAXHandlerPtr) &docbDefaultSAXHandler);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002693}
2694
2695#endif /* LIBXML_DOCB_ENABLED */