blob: e6e310e0a9384e9c864e9db1f46bdb7a6680b8b8 [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 Veillard500a1de2004-03-22 15:22:58 +0000842 if ((ctxt->dictNames) && (doc != NULL)) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +0000843 doc->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000844 xmlDictReference(doc->dict);
845 }
Daniel Veillard1af9a412003-08-20 22:54:39 +0000846 }
847 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
848 (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
849 ctxt->myDoc->URL = xmlCanonicPath((const xmlChar *) ctxt->input->filename);
850 if (ctxt->myDoc->URL == NULL)
851 ctxt->myDoc->URL = xmlStrdup((const xmlChar *) ctxt->input->filename);
852 }
853}
854
855/**
856 * xmlSAX2EndDocument:
857 * @ctx: the user data (XML parser context)
858 *
859 * called when the document end has been detected.
860 */
861void
862xmlSAX2EndDocument(void *ctx)
863{
864 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
865#ifdef DEBUG_SAX
866 xmlGenericError(xmlGenericErrorContext,
867 "SAX.xmlSAX2EndDocument()\n");
868#endif
Daniel Veillard4432df22003-09-28 18:58:27 +0000869#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000870 if (ctxt->validate && ctxt->wellFormed &&
871 ctxt->myDoc && ctxt->myDoc->intSubset)
872 ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
Daniel Veillard4432df22003-09-28 18:58:27 +0000873#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000874
875 /*
876 * Grab the encoding if it was added on-the-fly
877 */
878 if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
879 (ctxt->myDoc->encoding == NULL)) {
880 ctxt->myDoc->encoding = ctxt->encoding;
881 ctxt->encoding = NULL;
882 }
883 if ((ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
884 (ctxt->myDoc->encoding == NULL)) {
885 ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
886 }
887 if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
888 (ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
889 ctxt->myDoc->charset = ctxt->charset;
890 }
891}
892
Daniel Veillard81273902003-09-30 00:43:48 +0000893#if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED)
Daniel Veillard1af9a412003-08-20 22:54:39 +0000894/**
895 * xmlSAX2AttributeInternal:
896 * @ctx: the user data (XML parser context)
897 * @fullname: The attribute name, including namespace prefix
898 * @value: The attribute value
899 * @prefix: the prefix on the element node
900 *
901 * Handle an attribute that has been read by the parser.
902 * The default handling is to convert the attribute into an
903 * DOM subtree and past it in a new xmlAttr element added to
904 * the element.
905 */
906static void
907xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000908 const xmlChar *value, const xmlChar *prefix ATTRIBUTE_UNUSED)
Daniel Veillard1af9a412003-08-20 22:54:39 +0000909{
910 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
911 xmlAttrPtr ret;
912 xmlChar *name;
913 xmlChar *ns;
914 xmlChar *nval;
915 xmlNsPtr namespace;
916
917 /*
918 * Split the full name into a namespace prefix and the tag name
919 */
920 name = xmlSplitQName(ctxt, fullname, &ns);
921 if ((name != NULL) && (name[0] == 0)) {
922 if (xmlStrEqual(ns, BAD_CAST "xmlns")) {
923 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
924 ctxt->sax->error(ctxt->userData,
925 "invalid namespace declaration '%s'\n", fullname);
926 } else {
927 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
928 ctxt->sax->warning(ctxt->userData,
929 "Avoid attribute ending with ':' like '%s'\n", fullname);
930 }
931 if (ns != NULL)
932 xmlFree(ns);
933 ns = NULL;
934 xmlFree(name);
935 name = xmlStrdup(fullname);
936 }
937 if (name == NULL) {
938 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
939 ctxt->sax->error(ctxt->userData,
940 "SAX.xmlSAX2StartElement(): out of memory\n");
941 ctxt->errNo = XML_ERR_NO_MEMORY;
942 ctxt->instate = XML_PARSER_EOF;
943 ctxt->disableSAX = 1;
944 if (ns != NULL)
945 xmlFree(ns);
946 return;
947 }
948
Daniel Veillard4432df22003-09-28 18:58:27 +0000949#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000950 /*
951 * Do the last stage of the attribute normalization
952 * Needed for HTML too:
953 * http://www.w3.org/TR/html4/types.html#h-6.2
954 */
955 ctxt->vctxt.valid = 1;
956 nval = xmlValidCtxtNormalizeAttributeValue(&ctxt->vctxt,
957 ctxt->myDoc, ctxt->node,
958 fullname, value);
959 if (ctxt->vctxt.valid != 1) {
960 ctxt->valid = 0;
961 }
962 if (nval != NULL)
963 value = nval;
Daniel Veillard4432df22003-09-28 18:58:27 +0000964#else
965 nval = NULL;
966#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000967
968 /*
969 * Check whether it's a namespace definition
970 */
971 if ((!ctxt->html) && (ns == NULL) &&
972 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
973 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
974 xmlNsPtr nsret;
975 xmlChar *val;
976
977 if (!ctxt->replaceEntities) {
978 ctxt->depth++;
979 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
980 0,0,0);
981 ctxt->depth--;
982 } else {
983 val = (xmlChar *) value;
984 }
985
986 if (val[0] != 0) {
987 xmlURIPtr uri;
988
989 uri = xmlParseURI((const char *)val);
990 if (uri == NULL) {
991 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
992 ctxt->sax->warning(ctxt->userData,
William M. Brack4811ba32003-09-06 18:02:53 +0000993 "xmlns: %s not a valid URI\n", val);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000994 } else {
995 if (uri->scheme == NULL) {
996 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
997 ctxt->sax->warning(ctxt->userData,
998 "xmlns: URI %s is not absolute\n", val);
999 }
1000 xmlFreeURI(uri);
1001 }
1002 }
1003
1004 /* a default namespace definition */
1005 nsret = xmlNewNs(ctxt->node, val, NULL);
1006
Daniel Veillard4432df22003-09-28 18:58:27 +00001007#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001008 /*
1009 * Validate also for namespace decls, they are attributes from
1010 * an XML-1.0 perspective
1011 */
1012 if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
1013 ctxt->myDoc && ctxt->myDoc->intSubset)
1014 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
1015 ctxt->node, prefix, nsret, val);
Daniel Veillard4432df22003-09-28 18:58:27 +00001016#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001017 if (name != NULL)
1018 xmlFree(name);
1019 if (nval != NULL)
1020 xmlFree(nval);
1021 if (val != value)
1022 xmlFree(val);
1023 return;
1024 }
1025 if ((!ctxt->html) &&
1026 (ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
1027 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
1028 xmlNsPtr nsret;
1029 xmlChar *val;
1030
1031 if (!ctxt->replaceEntities) {
1032 ctxt->depth++;
1033 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1034 0,0,0);
1035 ctxt->depth--;
1036 if (val == NULL) {
1037 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1038 ctxt->sax->error(ctxt->userData,
1039 "SAX.xmlSAX2StartElement(): out of memory\n");
1040 ctxt->errNo = XML_ERR_NO_MEMORY;
1041 ctxt->instate = XML_PARSER_EOF;
1042 ctxt->disableSAX = 1;
1043 xmlFree(ns);
1044 if (name != NULL)
1045 xmlFree(name);
1046 return;
1047 }
1048 } else {
1049 val = (xmlChar *) value;
1050 }
1051
1052 if (val[0] == 0) {
1053 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1054 ctxt->sax->error(ctxt->userData,
1055 "Empty namespace name for prefix %s\n", name);
1056 }
1057 if ((ctxt->pedantic != 0) && (val[0] != 0)) {
1058 xmlURIPtr uri;
1059
1060 uri = xmlParseURI((const char *)val);
1061 if (uri == NULL) {
1062 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1063 ctxt->sax->warning(ctxt->userData,
1064 "xmlns:%s: %s not a valid URI\n", name, value);
1065 } else {
1066 if (uri->scheme == NULL) {
1067 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1068 ctxt->sax->warning(ctxt->userData,
1069 "xmlns:%s: URI %s is not absolute\n", name, value);
1070 }
1071 xmlFreeURI(uri);
1072 }
1073 }
1074
1075 /* a standard namespace definition */
1076 nsret = xmlNewNs(ctxt->node, val, name);
1077 xmlFree(ns);
Daniel Veillard4432df22003-09-28 18:58:27 +00001078#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001079 /*
1080 * Validate also for namespace decls, they are attributes from
1081 * an XML-1.0 perspective
1082 */
1083 if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
1084 ctxt->myDoc && ctxt->myDoc->intSubset)
1085 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
1086 ctxt->node, prefix, nsret, value);
Daniel Veillard4432df22003-09-28 18:58:27 +00001087#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001088 if (name != NULL)
1089 xmlFree(name);
1090 if (nval != NULL)
1091 xmlFree(nval);
1092 if (val != value)
1093 xmlFree(val);
1094 return;
1095 }
1096
1097 if (ns != NULL) {
1098 xmlAttrPtr prop;
1099 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
Daniel Veillard67906942003-08-28 21:13:25 +00001100 if (namespace == NULL) {
William M. Brack4811ba32003-09-06 18:02:53 +00001101 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1102 ctxt->sax->error(ctxt->userData,
1103 "Namespace prefix %s of attribute %s is not defined\n",
Daniel Veillard67906942003-08-28 21:13:25 +00001104 ns, name);
1105 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001106
1107 prop = ctxt->node->properties;
1108 while (prop != NULL) {
1109 if (prop->ns != NULL) {
1110 if ((xmlStrEqual(name, prop->name)) &&
1111 ((namespace == prop->ns) ||
1112 (xmlStrEqual(namespace->href, prop->ns->href)))) {
1113 ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
1114 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1115 ctxt->sax->error(ctxt->userData,
1116 "Attribute %s in %s redefined\n",
1117 name, namespace->href);
1118 ctxt->wellFormed = 0;
1119 if (ctxt->recovery == 0) ctxt->disableSAX = 1;
1120 goto error;
1121 }
1122 }
1123 prop = prop->next;
1124 }
1125 } else {
1126 namespace = NULL;
1127 }
1128
1129 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
1130 ret = xmlNewNsPropEatName(ctxt->node, namespace, name, NULL);
1131
1132 if (ret != NULL) {
1133 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
1134 xmlNodePtr tmp;
1135
1136 ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
1137 tmp = ret->children;
1138 while (tmp != NULL) {
1139 tmp->parent = (xmlNodePtr) ret;
1140 if (tmp->next == NULL)
1141 ret->last = tmp;
1142 tmp = tmp->next;
1143 }
1144 } else if (value != NULL) {
1145 ret->children = xmlNewDocText(ctxt->myDoc, value);
1146 ret->last = ret->children;
1147 if (ret->children != NULL)
1148 ret->children->parent = (xmlNodePtr) ret;
1149 }
1150 }
1151
Daniel Veillard4432df22003-09-28 18:58:27 +00001152#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001153 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
1154 ctxt->myDoc && ctxt->myDoc->intSubset) {
1155
1156 /*
1157 * If we don't substitute entities, the validation should be
1158 * done on a value with replaced entities anyway.
1159 */
1160 if (!ctxt->replaceEntities) {
1161 xmlChar *val;
1162
1163 ctxt->depth++;
1164 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1165 0,0,0);
1166 ctxt->depth--;
1167
1168 if (val == NULL)
1169 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1170 ctxt->myDoc, ctxt->node, ret, value);
1171 else {
1172 xmlChar *nvalnorm;
1173
1174 /*
1175 * Do the last stage of the attribute normalization
1176 * It need to be done twice ... it's an extra burden related
1177 * to the ability to keep xmlSAX2References in attributes
1178 */
1179 nvalnorm = xmlValidNormalizeAttributeValue(ctxt->myDoc,
1180 ctxt->node, fullname, val);
1181 if (nvalnorm != NULL) {
1182 xmlFree(val);
1183 val = nvalnorm;
1184 }
1185
1186 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1187 ctxt->myDoc, ctxt->node, ret, val);
1188 xmlFree(val);
1189 }
1190 } else {
1191 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
1192 ctxt->node, ret, value);
1193 }
Daniel Veillard4432df22003-09-28 18:58:27 +00001194 } else
1195#endif /* LIBXML_VALID_ENABLED */
1196 if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
Daniel Veillard1af9a412003-08-20 22:54:39 +00001197 (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
1198 ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
1199 /*
1200 * when validating, the ID registration is done at the attribute
1201 * validation level. Otherwise we have to do specific handling here.
1202 */
1203 if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
1204 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
1205 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
1206 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
1207 }
1208
1209error:
1210 if (nval != NULL)
1211 xmlFree(nval);
1212 if (ns != NULL)
1213 xmlFree(ns);
1214}
1215
Daniel Veillard1af9a412003-08-20 22:54:39 +00001216/*
1217 * xmlCheckDefaultedAttributes:
1218 *
1219 * Check defaulted attributes from the DTD
1220 */
1221static void
1222xmlCheckDefaultedAttributes(xmlParserCtxtPtr ctxt, const xmlChar *name,
1223 const xmlChar *prefix, const xmlChar **atts) {
1224 xmlElementPtr elemDecl;
1225 const xmlChar *att;
1226 int internal = 1;
1227 int i;
1228
1229 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset, name, prefix);
1230 if (elemDecl == NULL) {
1231 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset, name, prefix);
1232 internal = 0;
1233 }
1234
1235process_external_subset:
1236
1237 if (elemDecl != NULL) {
1238 xmlAttributePtr attr = elemDecl->attributes;
1239 /*
1240 * Check against defaulted attributes from the external subset
1241 * if the document is stamped as standalone
1242 */
1243 if ((ctxt->myDoc->standalone == 1) &&
1244 (ctxt->myDoc->extSubset != NULL) &&
1245 (ctxt->validate)) {
1246 while (attr != NULL) {
1247 if ((attr->defaultValue != NULL) &&
1248 (xmlGetDtdQAttrDesc(ctxt->myDoc->extSubset,
1249 attr->elem, attr->name,
1250 attr->prefix) == attr) &&
1251 (xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1252 attr->elem, attr->name,
1253 attr->prefix) == NULL)) {
1254 xmlChar *fulln;
1255
1256 if (attr->prefix != NULL) {
1257 fulln = xmlStrdup(attr->prefix);
1258 fulln = xmlStrcat(fulln, BAD_CAST ":");
1259 fulln = xmlStrcat(fulln, attr->name);
1260 } else {
1261 fulln = xmlStrdup(attr->name);
1262 }
1263
1264 /*
1265 * Check that the attribute is not declared in the
1266 * serialization
1267 */
1268 att = NULL;
1269 if (atts != NULL) {
1270 i = 0;
1271 att = atts[i];
1272 while (att != NULL) {
1273 if (xmlStrEqual(att, fulln))
1274 break;
1275 i += 2;
1276 att = atts[i];
1277 }
1278 }
1279 if (att == NULL) {
Daniel Veillardf88d8cf2003-12-08 10:25:02 +00001280 xmlErrValid(ctxt, XML_DTD_STANDALONE_DEFAULTED,
Daniel Veillard1af9a412003-08-20 22:54:39 +00001281 "standalone: attribute %s on %s defaulted from external subset\n",
Daniel Veillard427174f2003-12-10 10:42:59 +00001282 (const char *)fulln,
1283 (const char *)attr->elem);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001284 }
1285 }
1286 attr = attr->nexth;
1287 }
1288 }
1289
1290 /*
1291 * Actually insert defaulted values when needed
1292 */
1293 attr = elemDecl->attributes;
1294 while (attr != NULL) {
1295 /*
1296 * Make sure that attributes redefinition occuring in the
1297 * internal subset are not overriden by definitions in the
1298 * external subset.
1299 */
1300 if (attr->defaultValue != NULL) {
1301 /*
1302 * the element should be instantiated in the tree if:
1303 * - this is a namespace prefix
1304 * - the user required for completion in the tree
1305 * like XSLT
1306 * - there isn't already an attribute definition
1307 * in the internal subset overriding it.
1308 */
1309 if (((attr->prefix != NULL) &&
1310 (xmlStrEqual(attr->prefix, BAD_CAST "xmlns"))) ||
1311 ((attr->prefix == NULL) &&
1312 (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) ||
1313 (ctxt->loadsubset & XML_COMPLETE_ATTRS)) {
1314 xmlAttributePtr tst;
1315
1316 tst = xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1317 attr->elem, attr->name,
1318 attr->prefix);
1319 if ((tst == attr) || (tst == NULL)) {
1320 xmlChar fn[50];
1321 xmlChar *fulln;
1322
1323 fulln = xmlBuildQName(attr->name, attr->prefix, fn, 50);
1324 if (fulln == NULL) {
1325 if ((ctxt->sax != NULL) &&
1326 (ctxt->sax->error != NULL))
1327 ctxt->sax->error(ctxt->userData,
1328 "SAX.xmlSAX2StartElement(): out of memory\n");
1329 ctxt->errNo = XML_ERR_NO_MEMORY;
1330 ctxt->instate = XML_PARSER_EOF;
1331 ctxt->disableSAX = 1;
1332 return;
1333 }
1334
1335 /*
1336 * Check that the attribute is not declared in the
1337 * serialization
1338 */
1339 att = NULL;
1340 if (atts != NULL) {
1341 i = 0;
1342 att = atts[i];
1343 while (att != NULL) {
1344 if (xmlStrEqual(att, fulln))
1345 break;
1346 i += 2;
1347 att = atts[i];
1348 }
1349 }
1350 if (att == NULL) {
1351 xmlSAX2AttributeInternal(ctxt, fulln,
1352 attr->defaultValue, prefix);
1353 }
1354 if ((fulln != fn) && (fulln != attr->name))
1355 xmlFree(fulln);
1356 }
1357 }
1358 }
1359 attr = attr->nexth;
1360 }
1361 if (internal == 1) {
1362 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset,
1363 name, prefix);
1364 internal = 0;
1365 goto process_external_subset;
1366 }
1367 }
1368}
1369
1370/**
1371 * xmlSAX2StartElement:
1372 * @ctx: the user data (XML parser context)
1373 * @fullname: The element name, including namespace prefix
1374 * @atts: An array of name/value attributes pairs, NULL terminated
1375 *
1376 * called when an opening tag has been processed.
1377 */
1378void
1379xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
1380{
1381 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1382 xmlNodePtr ret;
1383 xmlNodePtr parent = ctxt->node;
1384 xmlNsPtr ns;
1385 xmlChar *name;
1386 xmlChar *prefix;
1387 const xmlChar *att;
1388 const xmlChar *value;
1389 int i;
1390
1391#ifdef DEBUG_SAX
1392 xmlGenericError(xmlGenericErrorContext,
1393 "SAX.xmlSAX2StartElement(%s)\n", fullname);
1394#endif
1395
1396 /*
1397 * First check on validity:
1398 */
1399 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
1400 ((ctxt->myDoc->intSubset == NULL) ||
1401 ((ctxt->myDoc->intSubset->notations == NULL) &&
1402 (ctxt->myDoc->intSubset->elements == NULL) &&
1403 (ctxt->myDoc->intSubset->attributes == NULL) &&
1404 (ctxt->myDoc->intSubset->entities == NULL)))) {
Daniel Veillardf88d8cf2003-12-08 10:25:02 +00001405 xmlErrValid(ctxt, XML_ERR_NO_DTD,
1406 "Validation failed: no DTD found !", NULL, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001407 ctxt->validate = 0;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001408 }
1409
1410
1411 /*
1412 * Split the full name into a namespace prefix and the tag name
1413 */
1414 name = xmlSplitQName(ctxt, fullname, &prefix);
1415
1416
1417 /*
1418 * Note : the namespace resolution is deferred until the end of the
1419 * attributes parsing, since local namespace can be defined as
1420 * an attribute at this level.
1421 */
1422 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL);
1423 if (ret == NULL) {
1424 if (prefix != NULL)
1425 xmlFree(prefix);
1426 ctxt->errNo = XML_ERR_NO_MEMORY;
1427 ctxt->instate = XML_PARSER_EOF;
1428 ctxt->disableSAX = 1;
1429 return;
1430 }
1431 if (ctxt->myDoc->children == NULL) {
1432#ifdef DEBUG_SAX_TREE
1433 xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
1434#endif
1435 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1436 } else if (parent == NULL) {
1437 parent = ctxt->myDoc->children;
1438 }
1439 ctxt->nodemem = -1;
1440 if (ctxt->linenumbers) {
Daniel Veillard3e35f8e2003-10-21 00:05:38 +00001441 if (ctxt->input != NULL) {
1442 if (ctxt->input->line < 65535)
1443 ret->line = (short) ctxt->input->line;
1444 else
1445 ret->line = 65535;
1446 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001447 }
1448
1449 /*
1450 * We are parsing a new node.
1451 */
1452#ifdef DEBUG_SAX_TREE
1453 xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);
1454#endif
1455 nodePush(ctxt, ret);
1456
1457 /*
1458 * Link the child element
1459 */
1460 if (parent != NULL) {
1461 if (parent->type == XML_ELEMENT_NODE) {
1462#ifdef DEBUG_SAX_TREE
1463 xmlGenericError(xmlGenericErrorContext,
1464 "adding child %s to %s\n", name, parent->name);
1465#endif
1466 xmlAddChild(parent, ret);
1467 } else {
1468#ifdef DEBUG_SAX_TREE
1469 xmlGenericError(xmlGenericErrorContext,
1470 "adding sibling %s to ", name);
1471 xmlDebugDumpOneNode(stderr, parent, 0);
1472#endif
1473 xmlAddSibling(parent, ret);
1474 }
1475 }
1476
1477 /*
1478 * Insert all the defaulted attributes from the DTD especially namespaces
1479 */
1480 if ((!ctxt->html) &&
1481 ((ctxt->myDoc->intSubset != NULL) ||
1482 (ctxt->myDoc->extSubset != NULL))) {
1483 xmlCheckDefaultedAttributes(ctxt, name, prefix, atts);
1484 }
1485
1486 /*
1487 * process all the attributes whose name start with "xmlns"
1488 */
1489 if (atts != NULL) {
1490 i = 0;
1491 att = atts[i++];
1492 value = atts[i++];
1493 if (!ctxt->html) {
1494 while ((att != NULL) && (value != NULL)) {
1495 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l') &&
1496 (att[3] == 'n') && (att[4] == 's'))
1497 xmlSAX2AttributeInternal(ctxt, att, value, prefix);
1498
1499 att = atts[i++];
1500 value = atts[i++];
1501 }
1502 }
1503 }
1504
1505 /*
1506 * Search the namespace, note that since the attributes have been
1507 * processed, the local namespaces are available.
1508 */
1509 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
1510 if ((ns == NULL) && (parent != NULL))
1511 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
1512 if ((prefix != NULL) && (ns == NULL)) {
1513 ns = xmlNewNs(ret, NULL, prefix);
1514 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1515 ctxt->sax->warning(ctxt->userData,
1516 "Namespace prefix %s is not defined\n", prefix);
1517 }
1518
1519 /*
1520 * set the namespace node, making sure that if the default namspace
1521 * is unbound on a parent we simply kee it NULL
1522 */
1523 if ((ns != NULL) && (ns->href != NULL) &&
1524 ((ns->href[0] != 0) || (ns->prefix != NULL)))
1525 xmlSetNs(ret, ns);
1526
1527 /*
1528 * process all the other attributes
1529 */
1530 if (atts != NULL) {
1531 i = 0;
1532 att = atts[i++];
1533 value = atts[i++];
1534 if (ctxt->html) {
1535 while (att != NULL) {
1536 xmlSAX2AttributeInternal(ctxt, att, value, NULL);
1537 att = atts[i++];
1538 value = atts[i++];
1539 }
1540 } else {
1541 while ((att != NULL) && (value != NULL)) {
1542 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l') ||
1543 (att[3] != 'n') || (att[4] != 's'))
1544 xmlSAX2AttributeInternal(ctxt, att, value, NULL);
1545
1546 /*
1547 * Next ones
1548 */
1549 att = atts[i++];
1550 value = atts[i++];
1551 }
1552 }
1553 }
1554
Daniel Veillard4432df22003-09-28 18:58:27 +00001555#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001556 /*
1557 * If it's the Document root, finish the DTD validation and
1558 * check the document root element for validity
1559 */
1560 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
1561 int chk;
1562
1563 chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
1564 if (chk <= 0)
1565 ctxt->valid = 0;
1566 if (chk < 0)
1567 ctxt->wellFormed = 0;
1568 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
1569 ctxt->vctxt.finishDtd = 1;
1570 }
Daniel Veillard4432df22003-09-28 18:58:27 +00001571#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001572
1573 if (prefix != NULL)
1574 xmlFree(prefix);
1575
1576}
1577
1578/**
1579 * xmlSAX2EndElement:
1580 * @ctx: the user data (XML parser context)
1581 * @name: The element name
1582 *
1583 * called when the end of an element has been detected.
1584 */
1585void
1586xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
1587{
1588 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1589 xmlParserNodeInfo node_info;
1590 xmlNodePtr cur = ctxt->node;
1591
1592#ifdef DEBUG_SAX
1593 if (name == NULL)
1594 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(NULL)\n");
1595 else
1596 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(%s)\n", name);
1597#endif
1598
1599 /* Capture end position and add node */
1600 if (cur != NULL && ctxt->record_info) {
1601 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
1602 node_info.end_line = ctxt->input->line;
1603 node_info.node = cur;
1604 xmlParserAddNodeInfo(ctxt, &node_info);
1605 }
1606 ctxt->nodemem = -1;
1607
Daniel Veillard4432df22003-09-28 18:58:27 +00001608#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001609 if (ctxt->validate && ctxt->wellFormed &&
1610 ctxt->myDoc && ctxt->myDoc->intSubset)
1611 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
1612 cur);
Daniel Veillard4432df22003-09-28 18:58:27 +00001613#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001614
1615
1616 /*
1617 * end of parsing of this node.
1618 */
1619#ifdef DEBUG_SAX_TREE
1620 xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);
1621#endif
1622 nodePop(ctxt);
1623}
Daniel Veillard81273902003-09-30 00:43:48 +00001624#endif /* LIBXML_SAX1_ENABLED || LIBXML_HTML_ENABLE */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001625
Daniel Veillarde57ec792003-09-10 10:50:59 +00001626/*
Daniel Veillard19895052003-09-17 13:59:32 +00001627 * xmlSAX2TextNode:
1628 * @ctxt: the parser context
1629 * @str: the input string
1630 * @len: the string length
1631 *
1632 * Remove the entities from an attribute value
1633 *
1634 * Returns the newly allocated string or NULL if not needed or error
1635 */
1636static xmlNodePtr
1637xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
1638 xmlNodePtr ret;
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001639 const xmlChar *intern = NULL;
Daniel Veillard19895052003-09-17 13:59:32 +00001640
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001641 /*
1642 * Allocate
1643 */
Daniel Veillard19895052003-09-17 13:59:32 +00001644 if (ctxt->freeElems != NULL) {
1645 ret = ctxt->freeElems;
1646 ctxt->freeElems = ret->next;
1647 ctxt->freeElemsNr--;
Daniel Veillard19895052003-09-17 13:59:32 +00001648 } else {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001649 ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard19895052003-09-17 13:59:32 +00001650 }
1651 if (ret == NULL) {
1652 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1653 ctxt->sax->error(ctxt->userData,
1654 "SAX.xmlSAX2Characters(): out of memory\n");
1655 ctxt->errNo = XML_ERR_NO_MEMORY;
1656 ctxt->instate = XML_PARSER_EOF;
1657 ctxt->disableSAX = 1;
1658 return(NULL);
1659 }
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001660 /*
1661 * intern the formatting blanks found between tags, or the
1662 * very short strings
1663 */
1664 if (ctxt->dictNames) {
1665 xmlChar cur = str[len];
1666
Daniel Veillarddca8cc72003-09-26 13:53:14 +00001667 if ((len <= 3) && ((cur == '"') || (cur == '\'') ||
1668 ((cur == '<') && (str[len + 1] != '!')))) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001669 intern = xmlDictLookup(ctxt->dict, str, len);
William M. Brack76e95df2003-10-18 16:20:14 +00001670 } else if (IS_BLANK_CH(*str) && (len < 60) && (cur == '<') &&
Daniel Veillarddca8cc72003-09-26 13:53:14 +00001671 (str[len + 1] != '!')) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001672 int i;
1673
1674 for (i = 1;i < len;i++) {
Daniel Veillard1a9b7082004-01-02 10:42:01 +00001675 if (!IS_BLANK_CH(str[i])) goto skip;
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001676 }
1677 intern = xmlDictLookup(ctxt->dict, str, len);
1678 }
1679 }
1680skip:
1681 memset(ret, 0, sizeof(xmlNode));
1682 ret->type = XML_TEXT_NODE;
1683
1684 ret->name = xmlStringText;
1685 if (intern == NULL)
1686 ret->content = xmlStrndup(str, len);
1687 else
1688 ret->content = (xmlChar *) intern;
1689
1690 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1691 xmlRegisterNodeDefaultValue(ret);
Daniel Veillard19895052003-09-17 13:59:32 +00001692 return(ret);
1693}
1694
Daniel Veillard4432df22003-09-28 18:58:27 +00001695#ifdef LIBXML_VALID_ENABLED
Daniel Veillard19895052003-09-17 13:59:32 +00001696/*
Daniel Veillarde57ec792003-09-10 10:50:59 +00001697 * xmlSAX2DecodeAttrEntities:
1698 * @ctxt: the parser context
1699 * @str: the input string
1700 * @len: the string length
1701 *
1702 * Remove the entities from an attribute value
1703 *
1704 * Returns the newly allocated string or NULL if not needed or error
1705 */
1706static xmlChar *
1707xmlSAX2DecodeAttrEntities(xmlParserCtxtPtr ctxt, const xmlChar *str,
1708 const xmlChar *end) {
1709 const xmlChar *in;
1710 xmlChar *ret;
1711
1712 in = str;
1713 while (in < end)
1714 if (*in++ == '&')
1715 goto decode;
1716 return(NULL);
1717decode:
1718 ctxt->depth++;
1719 ret = xmlStringLenDecodeEntities(ctxt, str, end - str,
1720 XML_SUBSTITUTE_REF, 0,0,0);
1721 ctxt->depth--;
1722 return(ret);
1723}
Daniel Veillard4432df22003-09-28 18:58:27 +00001724#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00001725
1726/**
1727 * xmlSAX2AttributeNs:
1728 * @ctx: the user data (XML parser context)
Daniel Veillard62998c02003-09-15 12:56:36 +00001729 * @localname: the local name of the attribute
1730 * @prefix: the attribute namespace prefix if available
1731 * @URI: the attribute namespace name if available
Daniel Veillarde57ec792003-09-10 10:50:59 +00001732 * @value: Start of the attribute value
1733 * @valueend: end of the attribute value
1734 *
1735 * Handle an attribute that has been read by the parser.
1736 * The default handling is to convert the attribute into an
1737 * DOM subtree and past it in a new xmlAttr element added to
1738 * the element.
1739 */
1740static void
1741xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
1742 const xmlChar * localname,
1743 const xmlChar * prefix,
1744 const xmlChar * value,
1745 const xmlChar * valueend)
1746{
1747 xmlAttrPtr ret;
1748 xmlNsPtr namespace = NULL;
1749 xmlChar *dup = NULL;
1750
Daniel Veillarde57ec792003-09-10 10:50:59 +00001751 /*
1752 * Note: if prefix == NULL, the attribute is not in the default namespace
1753 */
1754 if (prefix != NULL)
1755 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, prefix);
1756
Daniel Veillard8a44e592003-09-15 14:50:06 +00001757 /*
1758 * allocate the node
1759 */
1760 if (ctxt->freeAttrs != NULL) {
1761 ret = ctxt->freeAttrs;
1762 ctxt->freeAttrs = ret->next;
Daniel Veillard19895052003-09-17 13:59:32 +00001763 ctxt->freeAttrsNr--;
Daniel Veillard8a44e592003-09-15 14:50:06 +00001764 memset(ret, 0, sizeof(xmlAttr));
1765 ret->type = XML_ATTRIBUTE_NODE;
Daniel Veillarde57ec792003-09-10 10:50:59 +00001766
Daniel Veillard8a44e592003-09-15 14:50:06 +00001767 ret->parent = ctxt->node;
1768 ret->doc = ctxt->myDoc;
1769 ret->ns = namespace;
Daniel Veillarde57ec792003-09-10 10:50:59 +00001770
Daniel Veillard8a44e592003-09-15 14:50:06 +00001771 if (ctxt->dictNames)
1772 ret->name = localname;
1773 else
1774 ret->name = xmlStrdup(localname);
1775
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001776 /* link at the end to preserv order, TODO speed up with a last */
1777 if (ctxt->node->properties == NULL) {
1778 ctxt->node->properties = ret;
1779 } else {
1780 xmlAttrPtr prev = ctxt->node->properties;
1781
1782 while (prev->next != NULL) prev = prev->next;
1783 prev->next = ret;
1784 ret->prev = prev;
1785 }
1786
Daniel Veillard8a44e592003-09-15 14:50:06 +00001787 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1788 xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
1789 } else {
1790 if (ctxt->dictNames)
1791 ret = xmlNewNsPropEatName(ctxt->node, namespace,
1792 (xmlChar *) localname, NULL);
1793 else
1794 ret = xmlNewNsProp(ctxt->node, namespace, localname, NULL);
1795 if (ret == NULL) {
1796 ctxt->errNo = XML_ERR_NO_MEMORY;
1797 ctxt->instate = XML_PARSER_EOF;
1798 ctxt->disableSAX = 1;
1799 return;
Daniel Veillarde57ec792003-09-10 10:50:59 +00001800 }
1801 }
1802
Daniel Veillard8a44e592003-09-15 14:50:06 +00001803 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
1804 xmlNodePtr tmp;
1805
Daniel Veillard19895052003-09-17 13:59:32 +00001806 /*
1807 * We know that if there is an entity reference, then
1808 * the string has been dup'ed and terminates with 0
1809 * otherwise with ' or "
1810 */
1811 if (*valueend != 0) {
1812 tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
1813 ret->children = tmp;
1814 ret->last = tmp;
1815 if (tmp != NULL) {
1816 tmp->doc = ret->doc;
1817 tmp->parent = (xmlNodePtr) ret;
1818 }
1819 } else {
1820 ret->children = xmlStringLenGetNodeList(ctxt->myDoc, value,
1821 valueend - value);
1822 tmp = ret->children;
1823 while (tmp != NULL) {
1824 tmp->parent = (xmlNodePtr) ret;
1825 if (tmp->next == NULL)
1826 ret->last = tmp;
1827 tmp = tmp->next;
1828 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00001829 }
1830 } else if (value != NULL) {
Daniel Veillard19895052003-09-17 13:59:32 +00001831 xmlNodePtr tmp;
1832
1833 tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
1834 ret->children = tmp;
1835 ret->last = tmp;
1836 if (tmp != NULL) {
1837 tmp->doc = ret->doc;
1838 tmp->parent = (xmlNodePtr) ret;
1839 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00001840 }
1841
Daniel Veillard4432df22003-09-28 18:58:27 +00001842#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00001843 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
1844 ctxt->myDoc && ctxt->myDoc->intSubset) {
1845 /*
1846 * If we don't substitute entities, the validation should be
1847 * done on a value with replaced entities anyway.
1848 */
1849 if (!ctxt->replaceEntities) {
1850 dup = xmlSAX2DecodeAttrEntities(ctxt, value, valueend);
1851 if (dup == NULL) {
Daniel Veillard62998c02003-09-15 12:56:36 +00001852 if (*valueend == 0) {
1853 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1854 ctxt->myDoc, ctxt->node, ret, value);
1855 } else {
1856 /*
1857 * That should already be normalized.
1858 * cheaper to finally allocate here than duplicate
1859 * entry points in the full validation code
1860 */
1861 dup = xmlStrndup(value, valueend - value);
Daniel Veillarde57ec792003-09-10 10:50:59 +00001862
Daniel Veillard62998c02003-09-15 12:56:36 +00001863 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1864 ctxt->myDoc, ctxt->node, ret, dup);
1865 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00001866 } else {
Daniel Veillard62998c02003-09-15 12:56:36 +00001867 /*
1868 * dup now contains a string of the flattened attribute
1869 * content with entities substitued. Check if we need to
1870 * apply an extra layer of normalization.
Daniel Veillarde57ec792003-09-10 10:50:59 +00001871 * It need to be done twice ... it's an extra burden related
1872 * to the ability to keep references in attributes
1873 */
Daniel Veillard62998c02003-09-15 12:56:36 +00001874 if (ctxt->attsSpecial != NULL) {
1875 xmlChar *nvalnorm;
1876 xmlChar fn[50];
1877 xmlChar *fullname;
1878
1879 fullname = xmlBuildQName(localname, prefix, fn, 50);
1880 if (fullname != NULL) {
1881 ctxt->vctxt.valid = 1;
1882 nvalnorm = xmlValidCtxtNormalizeAttributeValue(
1883 &ctxt->vctxt, ctxt->myDoc,
1884 ctxt->node, fullname, dup);
1885 if (ctxt->vctxt.valid != 1)
1886 ctxt->valid = 0;
1887
1888 if ((fullname != fn) && (fullname != localname))
1889 xmlFree(fullname);
1890 if (nvalnorm != NULL) {
1891 xmlFree(dup);
1892 dup = nvalnorm;
1893 }
1894 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00001895 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00001896
1897 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1898 ctxt->myDoc, ctxt->node, ret, dup);
1899 }
1900 } else {
Daniel Veillard8e36e6a2003-09-10 10:50:59 +00001901 /*
1902 * if entities already have been substitued, then
1903 * the attribute as passed is already normalized
1904 */
Daniel Veillarde57ec792003-09-10 10:50:59 +00001905 dup = xmlStrndup(value, valueend - value);
1906
1907 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1908 ctxt->myDoc, ctxt->node, ret, dup);
1909 }
Daniel Veillard4432df22003-09-28 18:58:27 +00001910 } else
1911#endif /* LIBXML_VALID_ENABLED */
1912 if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
Daniel Veillarde57ec792003-09-10 10:50:59 +00001913 (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
1914 ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
1915 /*
1916 * when validating, the ID registration is done at the attribute
1917 * validation level. Otherwise we have to do specific handling here.
1918 */
1919 if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) {
1920 /* might be worth duplicate entry points and not copy */
1921 if (dup == NULL)
1922 dup = xmlStrndup(value, valueend - value);
1923 xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
1924 } else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) {
1925 if (dup == NULL)
1926 dup = xmlStrndup(value, valueend - value);
1927 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, dup, ret);
1928 }
1929 }
1930 if (dup != NULL)
1931 xmlFree(dup);
1932}
1933
1934/**
1935 * xmlSAX2StartElementNs:
1936 * @ctx: the user data (XML parser context)
1937 * @localname: the local name of the element
1938 * @prefix: the element namespace prefix if available
1939 * @URI: the element namespace name if available
1940 * @nb_namespaces: number of namespace definitions on that node
1941 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
1942 * @nb_attributes: the number of attributes on that node
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00001943 * @nb_defaulted: the number of defaulted attributes.
Daniel Veillarde57ec792003-09-10 10:50:59 +00001944 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
1945 * attribute values.
1946 *
1947 * SAX2 callback when an element start has been detected by the parser.
1948 * It provides the namespace informations for the element, as well as
1949 * the new namespace declarations on the element.
1950 */
1951void
1952xmlSAX2StartElementNs(void *ctx,
1953 const xmlChar *localname,
1954 const xmlChar *prefix,
1955 const xmlChar *URI,
1956 int nb_namespaces,
1957 const xmlChar **namespaces,
1958 int nb_attributes,
1959 int nb_defaulted,
1960 const xmlChar **attributes)
1961{
1962 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1963 xmlNodePtr ret;
1964 xmlNodePtr parent = ctxt->node;
1965 xmlNsPtr last = NULL, ns;
1966 const xmlChar *uri, *pref;
1967 int i, j;
1968
1969 /*
1970 * First check on validity:
1971 */
1972 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
1973 ((ctxt->myDoc->intSubset == NULL) ||
1974 ((ctxt->myDoc->intSubset->notations == NULL) &&
1975 (ctxt->myDoc->intSubset->elements == NULL) &&
1976 (ctxt->myDoc->intSubset->attributes == NULL) &&
1977 (ctxt->myDoc->intSubset->entities == NULL)))) {
Daniel Veillardf88d8cf2003-12-08 10:25:02 +00001978 xmlErrValid(ctxt, XML_ERR_NO_DTD,
1979 "Validation failed: no DTD found !", NULL, NULL);
Daniel Veillarde57ec792003-09-10 10:50:59 +00001980 ctxt->validate = 0;
Daniel Veillarde57ec792003-09-10 10:50:59 +00001981 }
1982
Daniel Veillard8a44e592003-09-15 14:50:06 +00001983 /*
1984 * allocate the node
1985 */
1986 if (ctxt->freeElems != NULL) {
1987 ret = ctxt->freeElems;
1988 ctxt->freeElems = ret->next;
Daniel Veillard19895052003-09-17 13:59:32 +00001989 ctxt->freeElemsNr--;
Daniel Veillard8a44e592003-09-15 14:50:06 +00001990 memset(ret, 0, sizeof(xmlNode));
1991 ret->type = XML_ELEMENT_NODE;
1992
1993 if (ctxt->dictNames)
1994 ret->name = localname;
1995 else
1996 ret->name = xmlStrdup(localname);
1997
1998 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1999 xmlRegisterNodeDefaultValue(ret);
2000 } else {
2001 if (ctxt->dictNames)
2002 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
2003 (xmlChar *) localname, NULL);
2004 else
2005 ret = xmlNewDocNode(ctxt->myDoc, NULL, localname, NULL);
2006 if (ret == NULL) {
2007 ctxt->errNo = XML_ERR_NO_MEMORY;
2008 ctxt->instate = XML_PARSER_EOF;
2009 ctxt->disableSAX = 1;
2010 return;
2011 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002012 }
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002013 if (ctxt->linenumbers) {
Daniel Veillard3e35f8e2003-10-21 00:05:38 +00002014 if (ctxt->input != NULL) {
2015 if (ctxt->input->line < 65535)
2016 ret->line = (short) ctxt->input->line;
2017 else
2018 ret->line = 65535;
2019 }
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002020 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00002021
Daniel Veillarde57ec792003-09-10 10:50:59 +00002022 if (ctxt->myDoc->children == NULL) {
2023 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2024 } else if (parent == NULL) {
2025 parent = ctxt->myDoc->children;
2026 }
2027 /*
2028 * Build the namespace list
2029 */
2030 for (i = 0,j = 0;j < nb_namespaces;j++) {
2031 pref = namespaces[i++];
2032 uri = namespaces[i++];
2033 ns = xmlNewNs(NULL, uri, pref);
2034 if (ns != NULL) {
2035 if (last == NULL) {
2036 ret->nsDef = last = ns;
2037 } else {
2038 last->next = ns;
2039 last = ns;
2040 }
2041 if ((URI != NULL) && (prefix == pref))
2042 ret->ns = ns;
2043 } else {
2044 ctxt->errNo = XML_ERR_NO_MEMORY;
2045 ctxt->instate = XML_PARSER_EOF;
2046 ctxt->disableSAX = 1;
2047 return;
2048 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002049#ifdef LIBXML_VALID_ENABLED
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002050 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
2051 ctxt->myDoc && ctxt->myDoc->intSubset) {
2052 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
2053 ret, prefix, ns, uri);
2054 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002055#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002056 }
2057 ctxt->nodemem = -1;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002058
2059 /*
2060 * We are parsing a new node.
2061 */
2062 nodePush(ctxt, ret);
2063
2064 /*
2065 * Link the child element
2066 */
2067 if (parent != NULL) {
2068 if (parent->type == XML_ELEMENT_NODE) {
2069 xmlAddChild(parent, ret);
2070 } else {
2071 xmlAddSibling(parent, ret);
2072 }
2073 }
2074
2075 /*
2076 * Insert the defaulted attributes from the DTD only if requested:
2077 */
2078 if ((nb_defaulted != 0) &&
2079 ((ctxt->loadsubset & XML_COMPLETE_ATTRS) == 0))
2080 nb_attributes -= nb_defaulted;
2081
2082 /*
2083 * Search the namespace if it wasn't already found
2084 */
2085 if ((URI != NULL) && (ret->ns == NULL)) {
2086 ret->ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
2087 if (ret->ns == NULL) {
2088 ns = xmlNewNs(ret, NULL, prefix);
2089 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
2090 ctxt->sax->warning(ctxt->userData,
2091 "Namespace prefix %s was not found\n", prefix);
2092 }
2093 }
2094
2095 /*
2096 * process all the other attributes
2097 */
2098 if (nb_attributes > 0) {
2099 for (j = 0,i = 0;i < nb_attributes;i++,j+=5) {
2100 xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1],
2101 attributes[j+3], attributes[j+4]);
2102 }
2103 }
2104
Daniel Veillard4432df22003-09-28 18:58:27 +00002105#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002106 /*
2107 * If it's the Document root, finish the DTD validation and
2108 * check the document root element for validity
2109 */
2110 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
2111 int chk;
2112
2113 chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
2114 if (chk <= 0)
2115 ctxt->valid = 0;
2116 if (chk < 0)
2117 ctxt->wellFormed = 0;
2118 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
2119 ctxt->vctxt.finishDtd = 1;
2120 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002121#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002122}
2123
2124/**
2125 * xmlSAX2EndElementNs:
2126 * @ctx: the user data (XML parser context)
2127 * @localname: the local name of the element
2128 * @prefix: the element namespace prefix if available
2129 * @URI: the element namespace name if available
2130 *
2131 * SAX2 callback when an element end has been detected by the parser.
2132 * It provides the namespace informations for the element.
2133 */
2134void
2135xmlSAX2EndElementNs(void *ctx,
2136 const xmlChar * localname ATTRIBUTE_UNUSED,
2137 const xmlChar * prefix ATTRIBUTE_UNUSED,
2138 const xmlChar * URI ATTRIBUTE_UNUSED)
2139{
2140 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2141 xmlParserNodeInfo node_info;
2142 xmlNodePtr cur = ctxt->node;
2143
2144 /* Capture end position and add node */
2145 if ((ctxt->record_info) && (cur != NULL)) {
2146 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
2147 node_info.end_line = ctxt->input->line;
2148 node_info.node = cur;
2149 xmlParserAddNodeInfo(ctxt, &node_info);
2150 }
2151 ctxt->nodemem = -1;
2152
Daniel Veillard4432df22003-09-28 18:58:27 +00002153#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002154 if (ctxt->validate && ctxt->wellFormed &&
2155 ctxt->myDoc && ctxt->myDoc->intSubset)
2156 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, cur);
Daniel Veillard4432df22003-09-28 18:58:27 +00002157#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002158
2159 /*
2160 * end of parsing of this node.
2161 */
2162 nodePop(ctxt);
2163}
2164
Daniel Veillard1af9a412003-08-20 22:54:39 +00002165/**
2166 * xmlSAX2Reference:
2167 * @ctx: the user data (XML parser context)
2168 * @name: The entity name
2169 *
2170 * called when an entity xmlSAX2Reference is detected.
2171 */
2172void
2173xmlSAX2Reference(void *ctx, const xmlChar *name)
2174{
2175 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2176 xmlNodePtr ret;
2177
2178#ifdef DEBUG_SAX
2179 xmlGenericError(xmlGenericErrorContext,
2180 "SAX.xmlSAX2Reference(%s)\n", name);
2181#endif
2182 if (name[0] == '#')
2183 ret = xmlNewCharRef(ctxt->myDoc, name);
2184 else
2185 ret = xmlNewReference(ctxt->myDoc, name);
2186#ifdef DEBUG_SAX_TREE
2187 xmlGenericError(xmlGenericErrorContext,
2188 "add xmlSAX2Reference %s to %s \n", name, ctxt->node->name);
2189#endif
2190 xmlAddChild(ctxt->node, ret);
2191}
2192
2193/**
2194 * xmlSAX2Characters:
2195 * @ctx: the user data (XML parser context)
2196 * @ch: a xmlChar string
2197 * @len: the number of xmlChar
2198 *
2199 * receiving some chars from the parser.
2200 */
2201void
2202xmlSAX2Characters(void *ctx, const xmlChar *ch, int len)
2203{
2204 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2205 xmlNodePtr lastChild;
2206
2207#ifdef DEBUG_SAX
2208 xmlGenericError(xmlGenericErrorContext,
2209 "SAX.xmlSAX2Characters(%.30s, %d)\n", ch, len);
2210#endif
2211 /*
2212 * Handle the data if any. If there is no child
2213 * add it as content, otherwise if the last child is text,
2214 * concatenate it, else create a new node of type text.
2215 */
2216
2217 if (ctxt->node == NULL) {
2218#ifdef DEBUG_SAX_TREE
2219 xmlGenericError(xmlGenericErrorContext,
2220 "add chars: ctxt->node == NULL !\n");
2221#endif
2222 return;
2223 }
Daniel Veillard19895052003-09-17 13:59:32 +00002224 lastChild = ctxt->node->last;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002225#ifdef DEBUG_SAX_TREE
2226 xmlGenericError(xmlGenericErrorContext,
2227 "add chars to %s \n", ctxt->node->name);
2228#endif
2229
2230 /*
2231 * Here we needed an accelerator mechanism in case of very large
2232 * elements. Use an attribute in the structure !!!
2233 */
2234 if (lastChild == NULL) {
Daniel Veillard19895052003-09-17 13:59:32 +00002235 lastChild = xmlSAX2TextNode(ctxt, ch, len);
2236 if (lastChild != NULL) {
2237 ctxt->node->children = lastChild;
2238 ctxt->node->last = lastChild;
2239 lastChild->parent = ctxt->node;
2240 lastChild->doc = ctxt->node->doc;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002241 ctxt->nodelen = len;
2242 ctxt->nodemem = len + 1;
2243 }
2244 } else {
2245 int coalesceText = (lastChild != NULL) &&
2246 (lastChild->type == XML_TEXT_NODE) &&
2247 (lastChild->name == xmlStringText);
2248 if ((coalesceText) && (ctxt->nodemem != 0)) {
2249 /*
2250 * The whole point of maintaining nodelen and nodemem,
2251 * xmlTextConcat is too costly, i.e. compute length,
2252 * reallocate a new buffer, move data, append ch. Here
2253 * We try to minimaze realloc() uses and avoid copying
2254 * and recomputing length over and over.
2255 */
Daniel Veillard2b0f8792003-10-10 19:36:36 +00002256 if ((ctxt->nodemem == ctxt->nodelen + 1) &&
2257 (xmlDictOwns(ctxt->dict, lastChild->content))) {
2258 lastChild->content = xmlStrdup(lastChild->content);
2259 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00002260 if (ctxt->nodelen + len >= ctxt->nodemem) {
2261 xmlChar *newbuf;
2262 int size;
2263
2264 size = ctxt->nodemem + len;
2265 size *= 2;
2266 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
2267 if (newbuf == NULL) {
2268 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2269 ctxt->sax->error(ctxt->userData,
2270 "SAX.xmlSAX2Characters(): out of memory\n");
2271 ctxt->errNo = XML_ERR_NO_MEMORY;
2272 ctxt->instate = XML_PARSER_EOF;
2273 ctxt->disableSAX = 1;
2274 return;
2275 }
2276 ctxt->nodemem = size;
2277 lastChild->content = newbuf;
2278 }
2279 memcpy(&lastChild->content[ctxt->nodelen], ch, len);
2280 ctxt->nodelen += len;
2281 lastChild->content[ctxt->nodelen] = 0;
2282 } else if (coalesceText) {
2283 if (xmlTextConcat(lastChild, ch, len)) {
2284 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
2285 ctxt->sax->error(ctxt->userData,
2286 "SAX.xmlSAX2Characters(): out of memory\n");
2287 ctxt->errNo = XML_ERR_NO_MEMORY;
2288 ctxt->instate = XML_PARSER_EOF;
2289 ctxt->disableSAX = 1;
2290 }
2291 if (ctxt->node->children != NULL) {
2292 ctxt->nodelen = xmlStrlen(lastChild->content);
2293 ctxt->nodemem = ctxt->nodelen + 1;
2294 }
2295 } else {
2296 /* Mixed content, first time */
Daniel Veillard19895052003-09-17 13:59:32 +00002297 lastChild = xmlSAX2TextNode(ctxt, ch, len);
2298 if (lastChild != NULL) {
Daniel Veillard1af9a412003-08-20 22:54:39 +00002299 xmlAddChild(ctxt->node, lastChild);
2300 if (ctxt->node->children != NULL) {
2301 ctxt->nodelen = len;
2302 ctxt->nodemem = len + 1;
2303 }
2304 }
2305 }
2306 }
2307}
2308
2309/**
2310 * xmlSAX2IgnorableWhitespace:
2311 * @ctx: the user data (XML parser context)
2312 * @ch: a xmlChar string
2313 * @len: the number of xmlChar
2314 *
2315 * receiving some ignorable whitespaces from the parser.
2316 * UNUSED: by default the DOM building will use xmlSAX2Characters
2317 */
2318void
2319xmlSAX2IgnorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
2320{
2321 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
2322#ifdef DEBUG_SAX
2323 xmlGenericError(xmlGenericErrorContext,
2324 "SAX.xmlSAX2IgnorableWhitespace(%.30s, %d)\n", ch, len);
2325#endif
2326}
2327
2328/**
2329 * xmlSAX2ProcessingInstruction:
2330 * @ctx: the user data (XML parser context)
2331 * @target: the target name
2332 * @data: the PI data's
2333 *
2334 * A processing instruction has been parsed.
2335 */
2336void
2337xmlSAX2ProcessingInstruction(void *ctx, const xmlChar *target,
2338 const xmlChar *data)
2339{
2340 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2341 xmlNodePtr ret;
2342 xmlNodePtr parent = ctxt->node;
2343
2344#ifdef DEBUG_SAX
2345 xmlGenericError(xmlGenericErrorContext,
2346 "SAX.xmlSAX2ProcessingInstruction(%s, %s)\n", target, data);
2347#endif
2348
2349 ret = xmlNewPI(target, data);
2350 if (ret == NULL) return;
2351 parent = ctxt->node;
2352
2353 if (ctxt->inSubset == 1) {
2354 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2355 return;
2356 } else if (ctxt->inSubset == 2) {
2357 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2358 return;
2359 }
2360 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
2361#ifdef DEBUG_SAX_TREE
2362 xmlGenericError(xmlGenericErrorContext,
2363 "Setting PI %s as root\n", target);
2364#endif
2365 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2366 return;
2367 }
2368 if (parent->type == XML_ELEMENT_NODE) {
2369#ifdef DEBUG_SAX_TREE
2370 xmlGenericError(xmlGenericErrorContext,
2371 "adding PI %s child to %s\n", target, parent->name);
2372#endif
2373 xmlAddChild(parent, ret);
2374 } else {
2375#ifdef DEBUG_SAX_TREE
2376 xmlGenericError(xmlGenericErrorContext,
2377 "adding PI %s sibling to ", target);
2378 xmlDebugDumpOneNode(stderr, parent, 0);
2379#endif
2380 xmlAddSibling(parent, ret);
2381 }
2382}
2383
2384/**
2385 * xmlSAX2Comment:
2386 * @ctx: the user data (XML parser context)
2387 * @value: the xmlSAX2Comment content
2388 *
2389 * A xmlSAX2Comment has been parsed.
2390 */
2391void
2392xmlSAX2Comment(void *ctx, const xmlChar *value)
2393{
2394 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2395 xmlNodePtr ret;
2396 xmlNodePtr parent = ctxt->node;
2397
2398#ifdef DEBUG_SAX
2399 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2Comment(%s)\n", value);
2400#endif
2401 ret = xmlNewDocComment(ctxt->myDoc, value);
2402 if (ret == NULL) return;
2403
2404 if (ctxt->inSubset == 1) {
2405 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2406 return;
2407 } else if (ctxt->inSubset == 2) {
2408 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2409 return;
2410 }
2411 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
2412#ifdef DEBUG_SAX_TREE
2413 xmlGenericError(xmlGenericErrorContext,
2414 "Setting xmlSAX2Comment as root\n");
2415#endif
2416 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2417 return;
2418 }
2419 if (parent->type == XML_ELEMENT_NODE) {
2420#ifdef DEBUG_SAX_TREE
2421 xmlGenericError(xmlGenericErrorContext,
2422 "adding xmlSAX2Comment child to %s\n", parent->name);
2423#endif
2424 xmlAddChild(parent, ret);
2425 } else {
2426#ifdef DEBUG_SAX_TREE
2427 xmlGenericError(xmlGenericErrorContext,
2428 "adding xmlSAX2Comment sibling to ");
2429 xmlDebugDumpOneNode(stderr, parent, 0);
2430#endif
2431 xmlAddSibling(parent, ret);
2432 }
2433}
2434
2435/**
2436 * xmlSAX2CDataBlock:
2437 * @ctx: the user data (XML parser context)
2438 * @value: The pcdata content
2439 * @len: the block length
2440 *
2441 * called when a pcdata block has been parsed
2442 */
2443void
2444xmlSAX2CDataBlock(void *ctx, const xmlChar *value, int len)
2445{
2446 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2447 xmlNodePtr ret, lastChild;
2448
2449#ifdef DEBUG_SAX
2450 xmlGenericError(xmlGenericErrorContext,
2451 "SAX.pcdata(%.10s, %d)\n", value, len);
2452#endif
2453 lastChild = xmlGetLastChild(ctxt->node);
2454#ifdef DEBUG_SAX_TREE
2455 xmlGenericError(xmlGenericErrorContext,
2456 "add chars to %s \n", ctxt->node->name);
2457#endif
2458 if ((lastChild != NULL) &&
2459 (lastChild->type == XML_CDATA_SECTION_NODE)) {
2460 xmlTextConcat(lastChild, value, len);
2461 } else {
2462 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
2463 xmlAddChild(ctxt->node, ret);
2464 }
2465}
2466
Daniel Veillard62998c02003-09-15 12:56:36 +00002467static int xmlSAX2DefaultVersionValue = 2;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002468
Daniel Veillard81273902003-09-30 00:43:48 +00002469#ifdef LIBXML_SAX1_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002470/**
2471 * xmlSAXDefaultVersion:
2472 * @version: the version, 1 or 2
2473 *
2474 * Set the default version of SAX used globally by the library.
2475 * Note that this may not be a good thing to do from a library
2476 * it is better to use xmlSAXVersion() to set up specifically the
2477 * version for a given parsing context.
2478 *
2479 * Returns the previous value in case of success and -1 in case of error.
2480 */
2481int
2482xmlSAXDefaultVersion(int version)
2483{
2484 int ret = xmlSAX2DefaultVersionValue;
2485
2486 if ((version != 1) && (version != 2))
2487 return(-1);
2488 xmlSAX2DefaultVersionValue = version;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002489 return(ret);
2490}
Daniel Veillard81273902003-09-30 00:43:48 +00002491#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002492
2493/**
2494 * xmlSAXVersion:
2495 * @hdlr: the SAX handler
2496 * @version: the version, 1 or 2
2497 *
2498 * Initialize the default XML SAX handler according to the version
2499 *
2500 * Returns 0 in case of success and -1 in case of error.
2501 */
2502int
2503xmlSAXVersion(xmlSAXHandler *hdlr, int version)
2504{
2505 if (hdlr == NULL) return(-1);
Daniel Veillard81273902003-09-30 00:43:48 +00002506 if (version == 2) {
Daniel Veillarde57ec792003-09-10 10:50:59 +00002507 hdlr->startElement = NULL;
2508 hdlr->endElement = NULL;
2509 hdlr->startElementNs = xmlSAX2StartElementNs;
2510 hdlr->endElementNs = xmlSAX2EndElementNs;
Daniel Veillardffbbed42003-10-10 14:46:54 +00002511 hdlr->serror = NULL;
Daniel Veillard092643b2003-09-25 14:29:29 +00002512 hdlr->initialized = XML_SAX2_MAGIC;
Daniel Veillard81273902003-09-30 00:43:48 +00002513#ifdef LIBXML_SAX1_ENABLED
2514 } else if (version == 1) {
2515 hdlr->startElement = xmlSAX2StartElement;
2516 hdlr->endElement = xmlSAX2EndElement;
2517 hdlr->initialized = 1;
2518#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002519 } else
2520 return(-1);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002521 hdlr->internalSubset = xmlSAX2InternalSubset;
2522 hdlr->externalSubset = xmlSAX2ExternalSubset;
2523 hdlr->isStandalone = xmlSAX2IsStandalone;
2524 hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
2525 hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
2526 hdlr->resolveEntity = xmlSAX2ResolveEntity;
2527 hdlr->getEntity = xmlSAX2GetEntity;
2528 hdlr->getParameterEntity = xmlSAX2GetParameterEntity;
2529 hdlr->entityDecl = xmlSAX2EntityDecl;
2530 hdlr->attributeDecl = xmlSAX2AttributeDecl;
2531 hdlr->elementDecl = xmlSAX2ElementDecl;
2532 hdlr->notationDecl = xmlSAX2NotationDecl;
2533 hdlr->unparsedEntityDecl = xmlSAX2UnparsedEntityDecl;
2534 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2535 hdlr->startDocument = xmlSAX2StartDocument;
2536 hdlr->endDocument = xmlSAX2EndDocument;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002537 hdlr->reference = xmlSAX2Reference;
2538 hdlr->characters = xmlSAX2Characters;
2539 hdlr->cdataBlock = xmlSAX2CDataBlock;
2540 hdlr->ignorableWhitespace = xmlSAX2Characters;
2541 hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
2542 hdlr->comment = xmlSAX2Comment;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002543 hdlr->warning = xmlParserWarning;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002544 hdlr->error = xmlParserError;
2545 hdlr->fatalError = xmlParserError;
2546
Daniel Veillarde57ec792003-09-10 10:50:59 +00002547 return(0);
2548}
2549
2550/**
2551 * xmlSAX2InitDefaultSAXHandler:
2552 * @hdlr: the SAX handler
2553 * @warning: flag if non-zero sets the handler warning procedure
2554 *
2555 * Initialize the default XML SAX2 handler
2556 */
2557void
2558xmlSAX2InitDefaultSAXHandler(xmlSAXHandler *hdlr, int warning)
2559{
2560 if ((hdlr == NULL) || (hdlr->initialized != 0))
2561 return;
2562
2563 xmlSAXVersion(hdlr, xmlSAX2DefaultVersionValue);
2564 if (warning == 0)
2565 hdlr->warning = NULL;
2566 else
2567 hdlr->warning = xmlParserWarning;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002568}
2569
2570/**
2571 * xmlDefaultSAXHandlerInit:
2572 *
2573 * Initialize the default SAX2 handler
2574 */
2575void
2576xmlDefaultSAXHandlerInit(void)
2577{
Daniel Veillard81273902003-09-30 00:43:48 +00002578#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard092643b2003-09-25 14:29:29 +00002579 xmlSAXVersion((xmlSAXHandlerPtr) &xmlDefaultSAXHandler, 1);
Daniel Veillard81273902003-09-30 00:43:48 +00002580#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00002581}
2582
2583#ifdef LIBXML_HTML_ENABLED
2584
2585/**
2586 * xmlSAX2InitHtmlDefaultSAXHandler:
2587 * @hdlr: the SAX handler
2588 *
2589 * Initialize the default HTML SAX2 handler
2590 */
2591void
2592xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr)
2593{
2594 if(hdlr->initialized != 0)
2595 return;
2596
2597 hdlr->internalSubset = xmlSAX2InternalSubset;
2598 hdlr->externalSubset = NULL;
2599 hdlr->isStandalone = NULL;
2600 hdlr->hasInternalSubset = NULL;
2601 hdlr->hasExternalSubset = NULL;
2602 hdlr->resolveEntity = NULL;
2603 hdlr->getEntity = xmlSAX2GetEntity;
2604 hdlr->getParameterEntity = NULL;
2605 hdlr->entityDecl = NULL;
2606 hdlr->attributeDecl = NULL;
2607 hdlr->elementDecl = NULL;
2608 hdlr->notationDecl = NULL;
2609 hdlr->unparsedEntityDecl = NULL;
2610 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2611 hdlr->startDocument = xmlSAX2StartDocument;
2612 hdlr->endDocument = xmlSAX2EndDocument;
2613 hdlr->startElement = xmlSAX2StartElement;
2614 hdlr->endElement = xmlSAX2EndElement;
2615 hdlr->reference = NULL;
2616 hdlr->characters = xmlSAX2Characters;
2617 hdlr->cdataBlock = xmlSAX2CDataBlock;
2618 hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
2619 hdlr->processingInstruction = NULL;
2620 hdlr->comment = xmlSAX2Comment;
2621 hdlr->warning = xmlParserWarning;
2622 hdlr->error = xmlParserError;
2623 hdlr->fatalError = xmlParserError;
2624
Daniel Veillard092643b2003-09-25 14:29:29 +00002625 hdlr->initialized = 1;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002626}
2627
2628/**
2629 * htmlDefaultSAXHandlerInit:
2630 *
2631 * Initialize the default SAX handler
2632 */
2633void
2634htmlDefaultSAXHandlerInit(void)
2635{
Daniel Veillard092643b2003-09-25 14:29:29 +00002636 xmlSAX2InitHtmlDefaultSAXHandler((xmlSAXHandlerPtr) &htmlDefaultSAXHandler);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002637}
2638
2639#endif /* LIBXML_HTML_ENABLED */
2640
2641#ifdef LIBXML_DOCB_ENABLED
2642
2643/**
2644 * xmlSAX2InitDocbDefaultSAXHandler:
2645 * @hdlr: the SAX handler
2646 *
2647 * Initialize the default DocBook SAX2 handler
2648 */
2649void
2650xmlSAX2InitDocbDefaultSAXHandler(xmlSAXHandler *hdlr)
2651{
2652 if(hdlr->initialized != 0)
2653 return;
2654
2655 hdlr->internalSubset = xmlSAX2InternalSubset;
2656 hdlr->externalSubset = NULL;
2657 hdlr->isStandalone = xmlSAX2IsStandalone;
2658 hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
2659 hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
2660 hdlr->resolveEntity = xmlSAX2ResolveEntity;
2661 hdlr->getEntity = xmlSAX2GetEntity;
2662 hdlr->getParameterEntity = NULL;
2663 hdlr->entityDecl = xmlSAX2EntityDecl;
2664 hdlr->attributeDecl = NULL;
2665 hdlr->elementDecl = NULL;
2666 hdlr->notationDecl = NULL;
2667 hdlr->unparsedEntityDecl = NULL;
2668 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2669 hdlr->startDocument = xmlSAX2StartDocument;
2670 hdlr->endDocument = xmlSAX2EndDocument;
2671 hdlr->startElement = xmlSAX2StartElement;
2672 hdlr->endElement = xmlSAX2EndElement;
2673 hdlr->reference = xmlSAX2Reference;
2674 hdlr->characters = xmlSAX2Characters;
2675 hdlr->cdataBlock = NULL;
2676 hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
2677 hdlr->processingInstruction = NULL;
2678 hdlr->comment = xmlSAX2Comment;
2679 hdlr->warning = xmlParserWarning;
2680 hdlr->error = xmlParserError;
2681 hdlr->fatalError = xmlParserError;
2682
Daniel Veillardffbbed42003-10-10 14:46:54 +00002683 hdlr->initialized = 1;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002684}
2685
2686/**
2687 * docbDefaultSAXHandlerInit:
2688 *
2689 * Initialize the default SAX handler
2690 */
2691void
2692docbDefaultSAXHandlerInit(void)
2693{
Daniel Veillard092643b2003-09-25 14:29:29 +00002694 xmlSAX2InitDocbDefaultSAXHandler((xmlSAXHandlerPtr) &docbDefaultSAXHandler);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002695}
2696
2697#endif /* LIBXML_DOCB_ENABLED */