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