blob: 9691a88811c440bb66ab174a76bd5817a981c87e [file] [log] [blame]
Owen Taylor3473f882001-02-23 17:55:21 +00001/*
2 * SAX.c : Default SAX handler to build a tree.
3 *
4 * See Copyright for the status of this software.
5 *
6 * Daniel Veillard <Daniel.Veillard@w3.org>
7 */
8
9
10#ifdef WIN32
11#include "win32config.h"
12#else
13#include "config.h"
14#endif
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18#include <libxml/xmlmemory.h>
19#include <libxml/tree.h>
20#include <libxml/parser.h>
21#include <libxml/parserInternals.h>
22#include <libxml/valid.h>
23#include <libxml/entities.h>
24#include <libxml/xmlerror.h>
25#include <libxml/debugXML.h>
26#include <libxml/xmlIO.h>
27#include <libxml/SAX.h>
28#include <libxml/uri.h>
29#include <libxml/HTMLtree.h>
30
31/* #define DEBUG_SAX */
32/* #define DEBUG_SAX_TREE */
33
Daniel Veillard56a4cb82001-03-24 17:00:36 +000034#ifdef __GNUC__
Daniel Veillardc86a4fa2001-03-26 16:28:29 +000035#ifdef DEBUG_SAX
36#define ATTRIBUTE_UNUSED
Daniel Veillard56a4cb82001-03-24 17:00:36 +000037#endif
Daniel Veillard56a4cb82001-03-24 17:00:36 +000038#endif
39
Owen Taylor3473f882001-02-23 17:55:21 +000040/**
41 * getPublicId:
42 * @ctx: the user data (XML parser context)
43 *
44 * Return the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
45 *
46 * Returns a xmlChar *
47 */
48const xmlChar *
Daniel Veillardc86a4fa2001-03-26 16:28:29 +000049getPublicId(void *ctx ATTRIBUTE_UNUSED)
Owen Taylor3473f882001-02-23 17:55:21 +000050{
51 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
52 return(NULL);
53}
54
55/**
56 * getSystemId:
57 * @ctx: the user data (XML parser context)
58 *
59 * Return the system ID, basically URL or filename e.g.
60 * http://www.sgmlsource.com/dtds/memo.dtd
61 *
62 * Returns a xmlChar *
63 */
64const xmlChar *
65getSystemId(void *ctx)
66{
67 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard56a4cb82001-03-24 17:00:36 +000068 return((const xmlChar *) ctxt->input->filename);
Owen Taylor3473f882001-02-23 17:55:21 +000069}
70
71/**
72 * getLineNumber:
73 * @ctx: the user data (XML parser context)
74 *
75 * Return the line number of the current parsing point.
76 *
77 * Returns an int
78 */
79int
80getLineNumber(void *ctx)
81{
82 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
83 return(ctxt->input->line);
84}
85
86/**
87 * getColumnNumber:
88 * @ctx: the user data (XML parser context)
89 *
90 * Return the column number of the current parsing point.
91 *
92 * Returns an int
93 */
94int
95getColumnNumber(void *ctx)
96{
97 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
98 return(ctxt->input->col);
99}
100
101/*
102 * The default SAX Locator.
103 */
104
105xmlSAXLocator xmlDefaultSAXLocator = {
106 getPublicId, getSystemId, getLineNumber, getColumnNumber
107};
108
109/**
110 * isStandalone:
111 * @ctx: the user data (XML parser context)
112 *
113 * Is this document tagged standalone ?
114 *
115 * Returns 1 if true
116 */
117int
118isStandalone(void *ctx)
119{
120 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
121 return(ctxt->myDoc->standalone == 1);
122}
123
124/**
125 * hasInternalSubset:
126 * @ctx: the user data (XML parser context)
127 *
128 * Does this document has an internal subset
129 *
130 * Returns 1 if true
131 */
132int
133hasInternalSubset(void *ctx)
134{
135 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
136 return(ctxt->myDoc->intSubset != NULL);
137}
138
139/**
140 * hasExternalSubset:
141 * @ctx: the user data (XML parser context)
142 *
143 * Does this document has an external subset
144 *
145 * Returns 1 if true
146 */
147int
148hasExternalSubset(void *ctx)
149{
150 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
151 return(ctxt->myDoc->extSubset != NULL);
152}
153
154/**
155 * internalSubset:
156 * @ctx: the user data (XML parser context)
157 * @name: the root element name
158 * @ExternalID: the external ID
159 * @SystemID: the SYSTEM ID (e.g. filename or URL)
160 *
161 * Callback on internal subset declaration.
162 */
163void
164internalSubset(void *ctx, const xmlChar *name,
165 const xmlChar *ExternalID, const xmlChar *SystemID)
166{
167 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
168 xmlDtdPtr dtd;
169#ifdef DEBUG_SAX
170 xmlGenericError(xmlGenericErrorContext,
171 "SAX.internalSubset(%s, %s, %s)\n",
172 name, ExternalID, SystemID);
173#endif
174
175 if (ctxt->myDoc == NULL)
176 return;
177 dtd = xmlGetIntSubset(ctxt->myDoc);
178 if (dtd != NULL) {
179 if (ctxt->html)
180 return;
181 xmlUnlinkNode((xmlNodePtr) dtd);
182 xmlFreeDtd(dtd);
183 ctxt->myDoc->intSubset = NULL;
184 }
185 ctxt->myDoc->intSubset =
186 xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
187}
188
189/**
190 * externalSubset:
191 * @ctx: the user data (XML parser context)
192 * @name: the root element name
193 * @ExternalID: the external ID
194 * @SystemID: the SYSTEM ID (e.g. filename or URL)
195 *
196 * Callback on external subset declaration.
197 */
198void
199externalSubset(void *ctx, const xmlChar *name,
200 const xmlChar *ExternalID, const xmlChar *SystemID)
201{
202 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
203#ifdef DEBUG_SAX
204 xmlGenericError(xmlGenericErrorContext,
205 "SAX.externalSubset(%s, %s, %s)\n",
206 name, ExternalID, SystemID);
207#endif
208 if (((ExternalID != NULL) || (SystemID != NULL)) &&
209 (((ctxt->validate) || (ctxt->loadsubset)) &&
210 (ctxt->wellFormed && ctxt->myDoc))) {
211 /*
212 * Try to fetch and parse the external subset.
213 */
214 xmlParserInputPtr oldinput;
215 int oldinputNr;
216 int oldinputMax;
217 xmlParserInputPtr *oldinputTab;
218 int oldwellFormed;
219 xmlParserInputPtr input = NULL;
220 xmlCharEncoding enc;
221 int oldcharset;
222
223 /*
224 * Ask the Entity resolver to load the damn thing
225 */
226 if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
227 input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
228 SystemID);
229 if (input == NULL) {
230 return;
231 }
232
233 xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
234
235 /*
236 * make sure we won't destroy the main document context
237 */
238 oldinput = ctxt->input;
239 oldinputNr = ctxt->inputNr;
240 oldinputMax = ctxt->inputMax;
241 oldinputTab = ctxt->inputTab;
242 oldwellFormed = ctxt->wellFormed;
243 oldcharset = ctxt->charset;
244
245 ctxt->inputTab = (xmlParserInputPtr *)
246 xmlMalloc(5 * sizeof(xmlParserInputPtr));
247 if (ctxt->inputTab == NULL) {
248 ctxt->errNo = XML_ERR_NO_MEMORY;
249 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
250 ctxt->sax->error(ctxt->userData,
251 "externalSubset: out of memory\n");
252 ctxt->errNo = XML_ERR_NO_MEMORY;
253 ctxt->input = oldinput;
254 ctxt->inputNr = oldinputNr;
255 ctxt->inputMax = oldinputMax;
256 ctxt->inputTab = oldinputTab;
257 ctxt->charset = oldcharset;
258 return;
259 }
260 ctxt->inputNr = 0;
261 ctxt->inputMax = 5;
262 ctxt->input = NULL;
263 xmlPushInput(ctxt, input);
264
265 /*
266 * On the fly encoding conversion if needed
267 */
268 enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
269 xmlSwitchEncoding(ctxt, enc);
270
271 if (input->filename == NULL)
272 input->filename = (char *) xmlStrdup(SystemID);
273 input->line = 1;
274 input->col = 1;
275 input->base = ctxt->input->cur;
276 input->cur = ctxt->input->cur;
277 input->free = NULL;
278
279 /*
280 * let's parse that entity knowing it's an external subset.
281 */
282 xmlParseExternalSubset(ctxt, ExternalID, SystemID);
283
284 /*
285 * Free up the external entities
286 */
287
288 while (ctxt->inputNr > 1)
289 xmlPopInput(ctxt);
290 xmlFreeInputStream(ctxt->input);
291 xmlFree(ctxt->inputTab);
292
293 /*
294 * Restore the parsing context of the main entity
295 */
296 ctxt->input = oldinput;
297 ctxt->inputNr = oldinputNr;
298 ctxt->inputMax = oldinputMax;
299 ctxt->inputTab = oldinputTab;
300 ctxt->charset = oldcharset;
301 /* ctxt->wellFormed = oldwellFormed; */
302 }
303}
304
305/**
306 * resolveEntity:
307 * @ctx: the user data (XML parser context)
308 * @publicId: The public ID of the entity
309 * @systemId: The system ID of the entity
310 *
311 * The entity loader, to control the loading of external entities,
312 * the application can either:
313 * - override this resolveEntity() callback in the SAX block
314 * - or better use the xmlSetExternalEntityLoader() function to
315 * set up it's own entity resolution routine
316 *
317 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
318 */
319xmlParserInputPtr
320resolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
321{
322 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
323 xmlParserInputPtr ret;
324 xmlChar *URI;
325 const char *base = NULL;
326
327 if (ctxt->input != NULL)
328 base = ctxt->input->filename;
329 if (base == NULL)
330 base = ctxt->directory;
331
332 URI = xmlBuildURI(systemId, (const xmlChar *) base);
333
334#ifdef DEBUG_SAX
335 xmlGenericError(xmlGenericErrorContext,
336 "SAX.resolveEntity(%s, %s)\n", publicId, systemId);
337#endif
338
339 ret = xmlLoadExternalEntity((const char *) URI,
340 (const char *) publicId, ctxt);
341 if (URI != NULL)
342 xmlFree(URI);
343 return(ret);
344}
345
346/**
347 * getEntity:
348 * @ctx: the user data (XML parser context)
349 * @name: The entity name
350 *
351 * Get an entity by name
352 *
353 * Returns the xmlEntityPtr if found.
354 */
355xmlEntityPtr
356getEntity(void *ctx, const xmlChar *name)
357{
358 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
359 xmlEntityPtr ret;
360
361#ifdef DEBUG_SAX
362 xmlGenericError(xmlGenericErrorContext,
363 "SAX.getEntity(%s)\n", name);
364#endif
365
366 ret = xmlGetDocEntity(ctxt->myDoc, name);
367 if ((ret != NULL) && (ctxt->validate) && (ret->children == NULL) &&
368 (ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
369 /*
370 * for validation purposes we really need to fetch and
371 * parse the external entity
372 */
373 int parse;
374 xmlNodePtr children;
375
376 parse = xmlParseCtxtExternalEntity(ctxt,
377 ret->SystemID, ret->ExternalID, &children);
378 xmlAddChildList((xmlNodePtr) ret, children);
379 }
380 return(ret);
381}
382
383/**
384 * getParameterEntity:
385 * @ctx: the user data (XML parser context)
386 * @name: The entity name
387 *
388 * Get a parameter entity by name
389 *
390 * Returns the xmlEntityPtr if found.
391 */
392xmlEntityPtr
393getParameterEntity(void *ctx, const xmlChar *name)
394{
395 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
396 xmlEntityPtr ret;
397
398#ifdef DEBUG_SAX
399 xmlGenericError(xmlGenericErrorContext,
400 "SAX.getParameterEntity(%s)\n", name);
401#endif
402
403 ret = xmlGetParameterEntity(ctxt->myDoc, name);
404 return(ret);
405}
406
407
408/**
409 * entityDecl:
410 * @ctx: the user data (XML parser context)
411 * @name: the entity name
412 * @type: the entity type
413 * @publicId: The public ID of the entity
414 * @systemId: The system ID of the entity
415 * @content: the entity value (without processing).
416 *
417 * An entity definition has been parsed
418 */
419void
420entityDecl(void *ctx, const xmlChar *name, int type,
421 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
422{
423 xmlEntityPtr ent;
424 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
425
426#ifdef DEBUG_SAX
427 xmlGenericError(xmlGenericErrorContext,
428 "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
429 name, type, publicId, systemId, content);
430#endif
431 if (ctxt->inSubset == 1) {
432 ent = xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
433 systemId, content);
434 if ((ent == NULL) && (ctxt->pedantic) &&
435 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
436 ctxt->sax->warning(ctxt,
437 "Entity(%s) already defined in the internal subset\n", name);
438 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
439 xmlChar *URI;
440 const char *base = NULL;
441
442 if (ctxt->input != NULL)
443 base = ctxt->input->filename;
444 if (base == NULL)
445 base = ctxt->directory;
446
447 URI = xmlBuildURI(systemId, (const xmlChar *) base);
448 ent->URI = URI;
449 }
450 } else if (ctxt->inSubset == 2) {
451 ent = xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
452 systemId, content);
453 if ((ent == NULL) && (ctxt->pedantic) &&
454 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
455 ctxt->sax->warning(ctxt,
456 "Entity(%s) already defined in the external subset\n", name);
457 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
458 xmlChar *URI;
459 const char *base = NULL;
460
461 if (ctxt->input != NULL)
462 base = ctxt->input->filename;
463 if (base == NULL)
464 base = ctxt->directory;
465
466 URI = xmlBuildURI(systemId, (const xmlChar *) base);
467 ent->URI = URI;
468 }
469 } else {
470 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
471 ctxt->sax->error(ctxt,
472 "SAX.entityDecl(%s) called while not in subset\n", name);
473 }
474}
475
476/**
477 * attributeDecl:
478 * @ctx: the user data (XML parser context)
479 * @elem: the name of the element
480 * @fullname: the attribute name
481 * @type: the attribute type
482 * @def: the type of default value
483 * @defaultValue: the attribute default value
484 * @tree: the tree of enumerated value set
485 *
486 * An attribute definition has been parsed
487 */
488void
489attributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
490 int type, int def, const xmlChar *defaultValue,
491 xmlEnumerationPtr tree)
492{
493 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
494 xmlAttributePtr attr;
495 xmlChar *name = NULL, *prefix = NULL;
496
497#ifdef DEBUG_SAX
498 xmlGenericError(xmlGenericErrorContext,
499 "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
500 elem, fullname, type, def, defaultValue);
501#endif
502 name = xmlSplitQName(ctxt, fullname, &prefix);
503 if (ctxt->inSubset == 1)
504 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
505 name, prefix, (xmlAttributeType) type,
506 (xmlAttributeDefault) def, defaultValue, tree);
507 else if (ctxt->inSubset == 2)
508 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
509 name, prefix, (xmlAttributeType) type,
510 (xmlAttributeDefault) def, defaultValue, tree);
511 else {
512 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
513 ctxt->sax->error(ctxt,
514 "SAX.attributeDecl(%s) called while not in subset\n", name);
515 return;
516 }
517 if (attr == 0) ctxt->valid = 0;
518 if (ctxt->validate && ctxt->wellFormed &&
519 ctxt->myDoc && ctxt->myDoc->intSubset)
520 ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
521 attr);
522 if (prefix != NULL)
523 xmlFree(prefix);
524 if (name != NULL)
525 xmlFree(name);
526}
527
528/**
529 * elementDecl:
530 * @ctx: the user data (XML parser context)
531 * @name: the element name
532 * @type: the element type
533 * @content: the element value tree
534 *
535 * An element definition has been parsed
536 */
537void
538elementDecl(void *ctx, const xmlChar *name, int type,
539 xmlElementContentPtr content)
540{
541 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
542 xmlElementPtr elem = NULL;
543
544#ifdef DEBUG_SAX
545 xmlGenericError(xmlGenericErrorContext,
546 "SAX.elementDecl(%s, %d, ...)\n",
547 fullname, type);
548#endif
549
550 if (ctxt->inSubset == 1)
551 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
552 name, (xmlElementTypeVal) type, content);
553 else if (ctxt->inSubset == 2)
554 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
555 name, (xmlElementTypeVal) type, content);
556 else {
557 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
558 ctxt->sax->error(ctxt,
559 "SAX.elementDecl(%s) called while not in subset\n", name);
560 return;
561 }
562 if (elem == NULL) ctxt->valid = 0;
563 if (ctxt->validate && ctxt->wellFormed &&
564 ctxt->myDoc && ctxt->myDoc->intSubset)
565 ctxt->valid &= xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
566}
567
568/**
569 * notationDecl:
570 * @ctx: the user data (XML parser context)
571 * @name: The name of the notation
572 * @publicId: The public ID of the entity
573 * @systemId: The system ID of the entity
574 *
575 * What to do when a notation declaration has been parsed.
576 */
577void
578notationDecl(void *ctx, const xmlChar *name,
579 const xmlChar *publicId, const xmlChar *systemId)
580{
581 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
582 xmlNotationPtr nota = NULL;
583
584#ifdef DEBUG_SAX
585 xmlGenericError(xmlGenericErrorContext,
586 "SAX.notationDecl(%s, %s, %s)\n", name, publicId, systemId);
587#endif
588
589 if (ctxt->inSubset == 1)
590 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
591 publicId, systemId);
592 else if (ctxt->inSubset == 2)
Daniel Veillard25239c12001-03-14 13:56:48 +0000593 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, name,
Owen Taylor3473f882001-02-23 17:55:21 +0000594 publicId, systemId);
595 else {
596 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
597 ctxt->sax->error(ctxt,
598 "SAX.notationDecl(%s) called while not in subset\n", name);
599 return;
600 }
601 if (nota == NULL) ctxt->valid = 0;
602 if (ctxt->validate && ctxt->wellFormed &&
603 ctxt->myDoc && ctxt->myDoc->intSubset)
604 ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
605 nota);
606}
607
608/**
609 * unparsedEntityDecl:
610 * @ctx: the user data (XML parser context)
611 * @name: The name of the entity
612 * @publicId: The public ID of the entity
613 * @systemId: The system ID of the entity
614 * @notationName: the name of the notation
615 *
616 * What to do when an unparsed entity declaration is parsed
617 */
618void
619unparsedEntityDecl(void *ctx, const xmlChar *name,
620 const xmlChar *publicId, const xmlChar *systemId,
621 const xmlChar *notationName)
622{
623 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
624#ifdef DEBUG_SAX
625 xmlGenericError(xmlGenericErrorContext,
626 "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
627 name, publicId, systemId, notationName);
628#endif
629 if (ctxt->validate && ctxt->wellFormed &&
Daniel Veillarde020c3a2001-03-21 18:06:15 +0000630 ctxt->myDoc && ctxt->myDoc->extSubset)
Owen Taylor3473f882001-02-23 17:55:21 +0000631 ctxt->valid &= xmlValidateNotationUse(&ctxt->vctxt, ctxt->myDoc,
632 notationName);
Daniel Veillarde020c3a2001-03-21 18:06:15 +0000633 if (ctxt->inSubset == 1)
634 xmlAddDocEntity(ctxt->myDoc, name,
635 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
636 publicId, systemId, notationName);
637 else if (ctxt->inSubset == 2)
638 xmlAddDtdEntity(ctxt->myDoc, name,
639 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
640 publicId, systemId, notationName);
641 else {
642 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
643 ctxt->sax->error(ctxt,
644 "SAX.unparsedEntityDecl(%s) called while not in subset\n", name);
645 }
Owen Taylor3473f882001-02-23 17:55:21 +0000646}
647
648/**
649 * setDocumentLocator:
650 * @ctx: the user data (XML parser context)
651 * @loc: A SAX Locator
652 *
653 * Receive the document locator at startup, actually xmlDefaultSAXLocator
654 * Everything is available on the context, so this is useless in our case.
655 */
656void
Daniel Veillardc86a4fa2001-03-26 16:28:29 +0000657setDocumentLocator(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
Owen Taylor3473f882001-02-23 17:55:21 +0000658{
659 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
660#ifdef DEBUG_SAX
661 xmlGenericError(xmlGenericErrorContext,
662 "SAX.setDocumentLocator()\n");
663#endif
664}
665
666/**
667 * startDocument:
668 * @ctx: the user data (XML parser context)
669 *
670 * called when the document start being processed.
671 */
672void
673startDocument(void *ctx)
674{
675 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
676 xmlDocPtr doc;
677
678#ifdef DEBUG_SAX
679 xmlGenericError(xmlGenericErrorContext,
680 "SAX.startDocument()\n");
681#endif
682 if (ctxt->html) {
683 if (ctxt->myDoc == NULL)
684#ifdef LIBXML_HTML_ENABLED
685 ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
686#else
687 xmlGenericError(xmlGenericErrorContext,
688 "libxml2 built without HTML support\n");
689#endif
690 } else {
691 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
692 if (doc != NULL) {
693 if (ctxt->encoding != NULL)
694 doc->encoding = xmlStrdup(ctxt->encoding);
695 else
696 doc->encoding = NULL;
697 doc->standalone = ctxt->standalone;
698 }
699 }
700 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
701 (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000702 ctxt->myDoc->URL = xmlStrdup((const xmlChar *) ctxt->input->filename);
Owen Taylor3473f882001-02-23 17:55:21 +0000703 }
704}
705
706/**
707 * endDocument:
708 * @ctx: the user data (XML parser context)
709 *
710 * called when the document end has been detected.
711 */
712void
713endDocument(void *ctx)
714{
715 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
716#ifdef DEBUG_SAX
717 xmlGenericError(xmlGenericErrorContext,
718 "SAX.endDocument()\n");
719#endif
720 if (ctxt->validate && ctxt->wellFormed &&
721 ctxt->myDoc && ctxt->myDoc->intSubset)
722 ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
723
724 /*
725 * Grab the encoding if it was added on-the-fly
726 */
727 if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
728 (ctxt->myDoc->encoding == NULL)) {
729 ctxt->myDoc->encoding = ctxt->encoding;
730 ctxt->encoding = NULL;
731 }
732 if ((ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
733 (ctxt->myDoc->encoding == NULL)) {
734 ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
735 }
736 if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
737 (ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
738 ctxt->myDoc->charset = ctxt->charset;
739 }
740}
741
742/**
743 * attribute:
744 * @ctx: the user data (XML parser context)
745 * @fullname: The attribute name, including namespace prefix
746 * @value: The attribute value
747 *
748 * Handle an attribute that has been read by the parser.
749 * The default handling is to convert the attribute into an
750 * DOM subtree and past it in a new xmlAttr element added to
751 * the element.
752 */
753void
754attribute(void *ctx, const xmlChar *fullname, const xmlChar *value)
755{
756 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
757 xmlAttrPtr ret;
758 xmlChar *name;
759 xmlChar *ns;
760 xmlChar *nval;
761 xmlNsPtr namespace;
762
763/****************
764#ifdef DEBUG_SAX
765 xmlGenericError(xmlGenericErrorContext,
766 "SAX.attribute(%s, %s)\n", fullname, value);
767#endif
768 ****************/
769 /*
770 * Split the full name into a namespace prefix and the tag name
771 */
772 name = xmlSplitQName(ctxt, fullname, &ns);
773
774 /*
775 * Do the last stage of the attribute normalization
776 * Needed for HTML too:
777 * http://www.w3.org/TR/html4/types.html#h-6.2
778 */
779 nval = xmlValidNormalizeAttributeValue(ctxt->myDoc, ctxt->node,
780 fullname, value);
781 if (nval != NULL)
782 value = nval;
783
784 /*
785 * Check whether it's a namespace definition
786 */
787 if ((!ctxt->html) && (ns == NULL) &&
788 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
789 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
790 if (value[0] != 0) {
791 xmlURIPtr uri;
792
793 uri = xmlParseURI((const char *)value);
794 if (uri == NULL) {
795 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
796 ctxt->sax->warning(ctxt->userData,
797 "nmlns: %s not a valid URI\n", value);
798 } else {
799 if (uri->scheme == NULL) {
800 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
801 ctxt->sax->warning(ctxt->userData,
802 "nmlns: URI %s is not absolute\n", value);
803 }
804 xmlFreeURI(uri);
805 }
806 }
807
808 /* a default namespace definition */
809 xmlNewNs(ctxt->node, value, NULL);
810 if (name != NULL)
811 xmlFree(name);
812 if (nval != NULL)
813 xmlFree(nval);
814 return;
815 }
816 if ((!ctxt->html) &&
817 (ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
818 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
819 /*
820 * Validate also for namespace decls, they are attributes from
821 * an XML-1.0 perspective
822 TODO ... doesn't map well with current API
823 if (ctxt->validate && ctxt->wellFormed &&
824 ctxt->myDoc && ctxt->myDoc->intSubset)
825 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
826 ctxt->node, ret, value);
827 */
828 /* a standard namespace definition */
829 xmlNewNs(ctxt->node, value, name);
830 xmlFree(ns);
831 if (name != NULL)
832 xmlFree(name);
833 if (nval != NULL)
834 xmlFree(nval);
835 return;
836 }
837
838 if (ns != NULL)
839 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
840 else {
841 namespace = NULL;
842 }
843
844 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
845 ret = xmlNewNsProp(ctxt->node, namespace, name, NULL);
846
847 if (ret != NULL) {
848 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
849 xmlNodePtr tmp;
850
851 ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
852 tmp = ret->children;
853 while (tmp != NULL) {
854 tmp->parent = (xmlNodePtr) ret;
855 if (tmp->next == NULL)
856 ret->last = tmp;
857 tmp = tmp->next;
858 }
859 } else if (value != NULL) {
860 ret->children = xmlNewDocText(ctxt->myDoc, value);
861 ret->last = ret->children;
862 if (ret->children != NULL)
863 ret->children->parent = (xmlNodePtr) ret;
864 }
865 }
866
867 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
868 ctxt->myDoc && ctxt->myDoc->intSubset) {
869
870 /*
871 * If we don't substitute entities, the validation should be
872 * done on a value with replaced entities anyway.
873 */
874 if (!ctxt->replaceEntities) {
875 xmlChar *val;
876
877 ctxt->depth++;
878 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
879 0,0,0);
880 ctxt->depth--;
881 if (val == NULL)
882 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
883 ctxt->myDoc, ctxt->node, ret, value);
884 else {
885 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
886 ctxt->myDoc, ctxt->node, ret, val);
887 xmlFree(val);
888 }
889 } else {
890 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
891 ctxt->node, ret, value);
892 }
893 } else {
894 /*
895 * when validating, the ID registration is done at the attribute
896 * validation level. Otherwise we have to do specific handling here.
897 */
898 if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
899 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
900 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
901 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
902 }
903
904 if (nval != NULL)
905 xmlFree(nval);
906 if (name != NULL)
907 xmlFree(name);
908 if (ns != NULL)
909 xmlFree(ns);
910}
911
912/**
913 * startElement:
914 * @ctx: the user data (XML parser context)
915 * @fullname: The element name, including namespace prefix
916 * @atts: An array of name/value attributes pairs, NULL terminated
917 *
918 * called when an opening tag has been processed.
919 */
920void
921startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
922{
923 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
924 xmlNodePtr ret;
925 xmlNodePtr parent = ctxt->node;
926 xmlNsPtr ns;
927 xmlChar *name;
928 xmlChar *prefix;
929 const xmlChar *att;
930 const xmlChar *value;
931 int i;
932
933#ifdef DEBUG_SAX
934 xmlGenericError(xmlGenericErrorContext,
935 "SAX.startElement(%s)\n", fullname);
936#endif
937
938 /*
939 * First check on validity:
940 */
941 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
942 ((ctxt->myDoc->intSubset == NULL) ||
943 ((ctxt->myDoc->intSubset->notations == NULL) &&
944 (ctxt->myDoc->intSubset->elements == NULL) &&
945 (ctxt->myDoc->intSubset->attributes == NULL) &&
946 (ctxt->myDoc->intSubset->entities == NULL)))) {
947 if (ctxt->vctxt.error != NULL) {
948 ctxt->vctxt.error(ctxt->vctxt.userData,
949 "Validation failed: no DTD found !\n");
950 }
951 ctxt->validate = 0;
952 }
953
954
955 /*
956 * Split the full name into a namespace prefix and the tag name
957 */
958 name = xmlSplitQName(ctxt, fullname, &prefix);
959
960
961 /*
962 * Note : the namespace resolution is deferred until the end of the
963 * attributes parsing, since local namespace can be defined as
964 * an attribute at this level.
965 */
966 ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL);
967 if (ret == NULL) return;
968 if (ctxt->myDoc->children == NULL) {
969#ifdef DEBUG_SAX_TREE
970 xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
971#endif
972 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
973 } else if (parent == NULL) {
974 parent = ctxt->myDoc->children;
975 }
976 ctxt->nodemem = -1;
977
978 /*
979 * We are parsing a new node.
980 */
981#ifdef DEBUG_SAX_TREE
982 xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);
983#endif
984 nodePush(ctxt, ret);
985
986 /*
987 * Link the child element
988 */
989 if (parent != NULL) {
990 if (parent->type == XML_ELEMENT_NODE) {
991#ifdef DEBUG_SAX_TREE
992 xmlGenericError(xmlGenericErrorContext,
993 "adding child %s to %s\n", name, parent->name);
994#endif
995 xmlAddChild(parent, ret);
996 } else {
997#ifdef DEBUG_SAX_TREE
998 xmlGenericError(xmlGenericErrorContext,
999 "adding sibling %s to ", name);
1000 xmlDebugDumpOneNode(stderr, parent, 0);
1001#endif
1002 xmlAddSibling(parent, ret);
1003 }
1004 }
1005
1006 /*
1007 * process all the attributes whose name start with "xml"
1008 */
1009 if (atts != NULL) {
1010 i = 0;
1011 att = atts[i++];
1012 value = atts[i++];
1013 if (!ctxt->html) {
1014 while ((att != NULL) && (value != NULL)) {
1015 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l'))
1016 attribute(ctxt, att, value);
1017
1018 att = atts[i++];
1019 value = atts[i++];
1020 }
1021 }
1022 }
1023
1024 /*
1025 * Search the namespace, note that since the attributes have been
1026 * processed, the local namespaces are available.
1027 */
1028 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
1029 if ((ns == NULL) && (parent != NULL))
1030 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
1031 if ((prefix != NULL) && (ns == NULL)) {
1032 ns = xmlNewNs(ret, NULL, prefix);
1033 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1034 ctxt->sax->warning(ctxt->userData,
1035 "Namespace prefix %s is not defined\n", prefix);
1036 }
1037 xmlSetNs(ret, ns);
1038
1039 /*
1040 * process all the other attributes
1041 */
1042 if (atts != NULL) {
1043 i = 0;
1044 att = atts[i++];
1045 value = atts[i++];
1046 if (ctxt->html) {
1047 while (att != NULL) {
1048 attribute(ctxt, att, value);
1049 att = atts[i++];
1050 value = atts[i++];
1051 }
1052 } else {
1053 while ((att != NULL) && (value != NULL)) {
1054 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l'))
1055 attribute(ctxt, att, value);
1056
1057 /*
1058 * Next ones
1059 */
1060 att = atts[i++];
1061 value = atts[i++];
1062 }
1063 }
1064 }
1065
1066 /*
1067 * If it's the Document root, finish the Dtd validation and
1068 * check the document root element for validity
1069 */
1070 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
1071 ctxt->valid &= xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
1072 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
1073 ctxt->vctxt.finishDtd = 1;
1074 }
1075
1076 if (prefix != NULL)
1077 xmlFree(prefix);
1078 if (name != NULL)
1079 xmlFree(name);
1080
1081}
1082
1083/**
1084 * endElement:
1085 * @ctx: the user data (XML parser context)
1086 * @name: The element name
1087 *
1088 * called when the end of an element has been detected.
1089 */
1090void
Daniel Veillardc86a4fa2001-03-26 16:28:29 +00001091endElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
Owen Taylor3473f882001-02-23 17:55:21 +00001092{
1093 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1094 xmlParserNodeInfo node_info;
1095 xmlNodePtr cur = ctxt->node;
1096
1097#ifdef DEBUG_SAX
1098 if (name == NULL)
1099 xmlGenericError(xmlGenericErrorContext, "SAX.endElement(NULL)\n");
1100 else
1101 xmlGenericError(xmlGenericErrorContext, "SAX.endElement(%s)\n", name);
1102#endif
1103
1104 /* Capture end position and add node */
1105 if (cur != NULL && ctxt->record_info) {
1106 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
1107 node_info.end_line = ctxt->input->line;
1108 node_info.node = cur;
1109 xmlParserAddNodeInfo(ctxt, &node_info);
1110 }
1111 ctxt->nodemem = -1;
1112
1113 if (ctxt->validate && ctxt->wellFormed &&
1114 ctxt->myDoc && ctxt->myDoc->intSubset)
1115 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
1116 cur);
1117
1118
1119 /*
1120 * end of parsing of this node.
1121 */
1122#ifdef DEBUG_SAX_TREE
1123 xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);
1124#endif
1125 nodePop(ctxt);
1126}
1127
1128/**
1129 * reference:
1130 * @ctx: the user data (XML parser context)
1131 * @name: The entity name
1132 *
1133 * called when an entity reference is detected.
1134 */
1135void
1136reference(void *ctx, const xmlChar *name)
1137{
1138 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1139 xmlNodePtr ret;
1140
1141#ifdef DEBUG_SAX
1142 xmlGenericError(xmlGenericErrorContext,
1143 "SAX.reference(%s)\n", name);
1144#endif
1145 if (name[0] == '#')
1146 ret = xmlNewCharRef(ctxt->myDoc, name);
1147 else
1148 ret = xmlNewReference(ctxt->myDoc, name);
1149#ifdef DEBUG_SAX_TREE
1150 xmlGenericError(xmlGenericErrorContext,
1151 "add reference %s to %s \n", name, ctxt->node->name);
1152#endif
1153 xmlAddChild(ctxt->node, ret);
1154}
1155
1156/**
1157 * characters:
1158 * @ctx: the user data (XML parser context)
1159 * @ch: a xmlChar string
1160 * @len: the number of xmlChar
1161 *
1162 * receiving some chars from the parser.
1163 * Question: how much at a time ???
1164 */
1165void
1166characters(void *ctx, const xmlChar *ch, int len)
1167{
1168 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1169 xmlNodePtr lastChild;
1170
1171#ifdef DEBUG_SAX
1172 xmlGenericError(xmlGenericErrorContext,
1173 "SAX.characters(%.30s, %d)\n", ch, len);
1174#endif
1175 /*
1176 * Handle the data if any. If there is no child
1177 * add it as content, otherwise if the last child is text,
1178 * concatenate it, else create a new node of type text.
1179 */
1180
1181 if (ctxt->node == NULL) {
1182#ifdef DEBUG_SAX_TREE
1183 xmlGenericError(xmlGenericErrorContext,
1184 "add chars: ctxt->node == NULL !\n");
1185#endif
1186 return;
1187 }
1188 lastChild = xmlGetLastChild(ctxt->node);
1189#ifdef DEBUG_SAX_TREE
1190 xmlGenericError(xmlGenericErrorContext,
1191 "add chars to %s \n", ctxt->node->name);
1192#endif
1193
1194 /*
1195 * Here we needed an accelerator mechanism in case of very large
1196 * elements. Use an attribute in the structure !!!
1197 */
1198 if (lastChild == NULL) {
1199 /* first node, first time */
1200 xmlNodeAddContentLen(ctxt->node, ch, len);
1201#ifndef XML_USE_BUFFER_CONTENT
1202 if (ctxt->node->children != NULL) {
1203 ctxt->nodelen = len;
1204 ctxt->nodemem = len + 1;
1205 }
1206#endif
1207 } else {
Daniel Veillard80f32572001-03-07 19:45:40 +00001208 int isText = xmlNodeIsText(lastChild);
1209 if ((isText) && (ctxt->nodemem != 0)) {
Owen Taylor3473f882001-02-23 17:55:21 +00001210#ifndef XML_USE_BUFFER_CONTENT
1211 /*
1212 * The whole point of maintaining nodelen and nodemem,
1213 * xmlTextConcat is too costly, i.e. compute lenght,
1214 * reallocate a new buffer, move data, append ch. Here
1215 * We try to minimaze realloc() uses and avoid copying
1216 * and recomputing lenght over and over.
1217 */
1218 if (ctxt->nodelen + len >= ctxt->nodemem) {
1219 xmlChar *newbuf;
1220 int size;
1221
1222 size = ctxt->nodemem + len;
1223 size *= 2;
1224 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
1225 if (newbuf == NULL) {
1226 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1227 ctxt->sax->error(ctxt->userData,
1228 "SAX.characters(): out of memory\n");
1229 return;
1230 }
1231 ctxt->nodemem = size;
1232 lastChild->content = newbuf;
1233 }
1234 memcpy(&lastChild->content[ctxt->nodelen], ch, len);
1235 ctxt->nodelen += len;
1236 lastChild->content[ctxt->nodelen] = 0;
1237#else
1238 xmlTextConcat(lastChild, ch, len);
1239#endif
Daniel Veillard80f32572001-03-07 19:45:40 +00001240 } else if (isText) {
1241 xmlTextConcat(lastChild, ch, len);
1242 if (ctxt->node->children != NULL) {
1243 ctxt->nodelen = xmlStrlen(lastChild->content);
1244 ctxt->nodemem = ctxt->nodelen + 1;
1245 }
Owen Taylor3473f882001-02-23 17:55:21 +00001246 } else {
1247 /* Mixed content, first time */
1248 lastChild = xmlNewTextLen(ch, len);
1249 xmlAddChild(ctxt->node, lastChild);
1250#ifndef XML_USE_BUFFER_CONTENT
1251 if (ctxt->node->children != NULL) {
1252 ctxt->nodelen = len;
1253 ctxt->nodemem = len + 1;
1254 }
1255#endif
1256 }
1257 }
1258}
1259
1260/**
1261 * ignorableWhitespace:
1262 * @ctx: the user data (XML parser context)
1263 * @ch: a xmlChar string
1264 * @len: the number of xmlChar
1265 *
1266 * receiving some ignorable whitespaces from the parser.
1267 * Question: how much at a time ???
1268 */
1269void
Daniel Veillardc86a4fa2001-03-26 16:28:29 +00001270ignorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
Owen Taylor3473f882001-02-23 17:55:21 +00001271{
1272 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
1273#ifdef DEBUG_SAX
1274 xmlGenericError(xmlGenericErrorContext,
1275 "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len);
1276#endif
1277}
1278
1279/**
1280 * processingInstruction:
1281 * @ctx: the user data (XML parser context)
1282 * @target: the target name
1283 * @data: the PI data's
1284 *
1285 * A processing instruction has been parsed.
1286 */
1287void
1288processingInstruction(void *ctx, const xmlChar *target,
1289 const xmlChar *data)
1290{
1291 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1292 xmlNodePtr ret;
1293 xmlNodePtr parent = ctxt->node;
1294
1295#ifdef DEBUG_SAX
1296 xmlGenericError(xmlGenericErrorContext,
1297 "SAX.processingInstruction(%s, %s)\n", target, data);
1298#endif
1299
1300 ret = xmlNewPI(target, data);
1301 if (ret == NULL) return;
1302 parent = ctxt->node;
1303
1304 if (ctxt->inSubset == 1) {
1305 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1306 return;
1307 } else if (ctxt->inSubset == 2) {
1308 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1309 return;
1310 }
1311 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
1312#ifdef DEBUG_SAX_TREE
1313 xmlGenericError(xmlGenericErrorContext,
1314 "Setting PI %s as root\n", target);
1315#endif
1316 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1317 return;
1318 }
1319 if (parent->type == XML_ELEMENT_NODE) {
1320#ifdef DEBUG_SAX_TREE
1321 xmlGenericError(xmlGenericErrorContext,
1322 "adding PI %s child to %s\n", target, parent->name);
1323#endif
1324 xmlAddChild(parent, ret);
1325 } else {
1326#ifdef DEBUG_SAX_TREE
1327 xmlGenericError(xmlGenericErrorContext,
1328 "adding PI %s sibling to ", target);
1329 xmlDebugDumpOneNode(stderr, parent, 0);
1330#endif
1331 xmlAddSibling(parent, ret);
1332 }
1333}
1334
1335/**
1336 * globalNamespace:
1337 * @ctx: the user data (XML parser context)
1338 * @href: the namespace associated URN
1339 * @prefix: the namespace prefix
1340 *
1341 * An old global namespace has been parsed.
1342 */
1343void
1344globalNamespace(void *ctx, const xmlChar *href, const xmlChar *prefix)
1345{
1346 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1347#ifdef DEBUG_SAX
1348 xmlGenericError(xmlGenericErrorContext,
1349 "SAX.globalNamespace(%s, %s)\n", href, prefix);
1350#endif
1351 xmlNewGlobalNs(ctxt->myDoc, href, prefix);
1352}
1353
1354/**
1355 * setNamespace:
1356 * @ctx: the user data (XML parser context)
1357 * @name: the namespace prefix
1358 *
1359 * Set the current element namespace.
1360 */
1361
1362void
1363setNamespace(void *ctx, const xmlChar *name)
1364{
1365 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1366 xmlNsPtr ns;
1367 xmlNodePtr parent;
1368
1369#ifdef DEBUG_SAX
1370 xmlGenericError(xmlGenericErrorContext, "SAX.setNamespace(%s)\n", name);
1371#endif
1372 ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name);
1373 if (ns == NULL) { /* ctxt->node may not have a parent yet ! */
1374 if (ctxt->nodeNr >= 2) {
1375 parent = ctxt->nodeTab[ctxt->nodeNr - 2];
1376 if (parent != NULL)
1377 ns = xmlSearchNs(ctxt->myDoc, parent, name);
1378 }
1379 }
1380 xmlSetNs(ctxt->node, ns);
1381}
1382
1383/**
1384 * getNamespace:
1385 * @ctx: the user data (XML parser context)
1386 *
1387 * Get the current element namespace.
1388 *
1389 * Returns the xmlNsPtr or NULL if none
1390 */
1391
1392xmlNsPtr
1393getNamespace(void *ctx)
1394{
1395 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1396 xmlNsPtr ret;
1397
1398#ifdef DEBUG_SAX
1399 xmlGenericError(xmlGenericErrorContext, "SAX.getNamespace()\n");
1400#endif
1401 ret = ctxt->node->ns;
1402 return(ret);
1403}
1404
1405/**
1406 * checkNamespace:
1407 * @ctx: the user data (XML parser context)
1408 * @namespace: the namespace to check against
1409 *
1410 * Check that the current element namespace is the same as the
1411 * one read upon parsing.
1412 *
1413 * Returns 1 if true 0 otherwise
1414 */
1415
1416int
1417checkNamespace(void *ctx, xmlChar *namespace)
1418{
1419 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1420 xmlNodePtr cur = ctxt->node;
1421
1422#ifdef DEBUG_SAX
1423 xmlGenericError(xmlGenericErrorContext,
1424 "SAX.checkNamespace(%s)\n", namespace);
1425#endif
1426
1427 /*
1428 * Check that the Name in the ETag is the same as in the STag.
1429 */
1430 if (namespace == NULL) {
1431 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1432 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1433 ctxt->sax->error(ctxt,
1434 "End tags for %s don't hold the namespace %s\n",
1435 cur->name, cur->ns->prefix);
1436 ctxt->wellFormed = 0;
1437 }
1438 } else {
1439 if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) {
1440 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1441 ctxt->sax->error(ctxt,
1442 "End tags %s holds a prefix %s not used by the open tag\n",
1443 cur->name, namespace);
1444 ctxt->wellFormed = 0;
1445 } else if (!xmlStrEqual(namespace, cur->ns->prefix)) {
1446 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1447 ctxt->sax->error(ctxt,
1448 "Start and End tags for %s don't use the same namespaces: %s and %s\n",
1449 cur->name, cur->ns->prefix, namespace);
1450 ctxt->wellFormed = 0;
1451 } else
1452 return(1);
1453 }
1454 return(0);
1455}
1456
1457/**
1458 * namespaceDecl:
1459 * @ctx: the user data (XML parser context)
1460 * @href: the namespace associated URN
1461 * @prefix: the namespace prefix
1462 *
1463 * A namespace has been parsed.
1464 */
1465void
1466namespaceDecl(void *ctx, const xmlChar *href, const xmlChar *prefix)
1467{
1468 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1469#ifdef DEBUG_SAX
1470 if (prefix == NULL)
1471 xmlGenericError(xmlGenericErrorContext,
1472 "SAX.namespaceDecl(%s, NULL)\n", href);
1473 else
1474 xmlGenericError(xmlGenericErrorContext,
1475 "SAX.namespaceDecl(%s, %s)\n", href, prefix);
1476#endif
1477 xmlNewNs(ctxt->node, href, prefix);
1478}
1479
1480/**
1481 * comment:
1482 * @ctx: the user data (XML parser context)
1483 * @value: the comment content
1484 *
1485 * A comment has been parsed.
1486 */
1487void
1488comment(void *ctx, const xmlChar *value)
1489{
1490 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1491 xmlNodePtr ret;
1492 xmlNodePtr parent = ctxt->node;
1493
1494#ifdef DEBUG_SAX
1495 xmlGenericError(xmlGenericErrorContext, "SAX.comment(%s)\n", value);
1496#endif
1497 ret = xmlNewDocComment(ctxt->myDoc, value);
1498 if (ret == NULL) return;
1499
1500 if (ctxt->inSubset == 1) {
1501 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1502 return;
1503 } else if (ctxt->inSubset == 2) {
1504 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1505 return;
1506 }
1507 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
1508#ifdef DEBUG_SAX_TREE
1509 xmlGenericError(xmlGenericErrorContext,
1510 "Setting comment as root\n");
1511#endif
1512 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1513 return;
1514 }
1515 if (parent->type == XML_ELEMENT_NODE) {
1516#ifdef DEBUG_SAX_TREE
1517 xmlGenericError(xmlGenericErrorContext,
1518 "adding comment child to %s\n", parent->name);
1519#endif
1520 xmlAddChild(parent, ret);
1521 } else {
1522#ifdef DEBUG_SAX_TREE
1523 xmlGenericError(xmlGenericErrorContext,
1524 "adding comment sibling to ");
1525 xmlDebugDumpOneNode(stderr, parent, 0);
1526#endif
1527 xmlAddSibling(parent, ret);
1528 }
1529}
1530
1531/**
1532 * cdataBlock:
1533 * @ctx: the user data (XML parser context)
1534 * @value: The pcdata content
1535 * @len: the block length
1536 *
1537 * called when a pcdata block has been parsed
1538 */
1539void
1540cdataBlock(void *ctx, const xmlChar *value, int len)
1541{
1542 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1543 xmlNodePtr ret, lastChild;
1544
1545#ifdef DEBUG_SAX
1546 xmlGenericError(xmlGenericErrorContext,
1547 "SAX.pcdata(%.10s, %d)\n", value, len);
1548#endif
1549 lastChild = xmlGetLastChild(ctxt->node);
1550#ifdef DEBUG_SAX_TREE
1551 xmlGenericError(xmlGenericErrorContext,
1552 "add chars to %s \n", ctxt->node->name);
1553#endif
1554 if ((lastChild != NULL) &&
1555 (lastChild->type == XML_CDATA_SECTION_NODE)) {
1556 xmlTextConcat(lastChild, value, len);
1557 } else {
1558 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
1559 xmlAddChild(ctxt->node, ret);
1560 }
1561}
1562
1563/*
1564 * Default handler for XML, builds the DOM tree
1565 */
1566xmlSAXHandler xmlDefaultSAXHandler = {
1567 internalSubset,
1568 isStandalone,
1569 hasInternalSubset,
1570 hasExternalSubset,
1571 resolveEntity,
1572 getEntity,
1573 entityDecl,
1574 notationDecl,
1575 attributeDecl,
1576 elementDecl,
1577 unparsedEntityDecl,
1578 setDocumentLocator,
1579 startDocument,
1580 endDocument,
1581 startElement,
1582 endElement,
1583 reference,
1584 characters,
1585 ignorableWhitespace,
1586 processingInstruction,
1587 comment,
1588 xmlParserWarning,
1589 xmlParserError,
1590 xmlParserError,
1591 getParameterEntity,
1592 cdataBlock,
1593 externalSubset,
1594};
1595
1596/**
1597 * xmlDefaultSAXHandlerInit:
1598 *
1599 * Initialize the default SAX handler
1600 */
1601void
1602xmlDefaultSAXHandlerInit(void)
1603{
1604 xmlDefaultSAXHandler.internalSubset = internalSubset;
1605 xmlDefaultSAXHandler.externalSubset = externalSubset;
1606 xmlDefaultSAXHandler.isStandalone = isStandalone;
1607 xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
1608 xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
1609 xmlDefaultSAXHandler.resolveEntity = resolveEntity;
1610 xmlDefaultSAXHandler.getEntity = getEntity;
1611 xmlDefaultSAXHandler.getParameterEntity = getParameterEntity;
1612 xmlDefaultSAXHandler.entityDecl = entityDecl;
1613 xmlDefaultSAXHandler.attributeDecl = attributeDecl;
1614 xmlDefaultSAXHandler.elementDecl = elementDecl;
1615 xmlDefaultSAXHandler.notationDecl = notationDecl;
1616 xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
1617 xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1618 xmlDefaultSAXHandler.startDocument = startDocument;
1619 xmlDefaultSAXHandler.endDocument = endDocument;
1620 xmlDefaultSAXHandler.startElement = startElement;
1621 xmlDefaultSAXHandler.endElement = endElement;
1622 xmlDefaultSAXHandler.reference = reference;
1623 xmlDefaultSAXHandler.characters = characters;
1624 xmlDefaultSAXHandler.cdataBlock = cdataBlock;
1625 xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1626 xmlDefaultSAXHandler.processingInstruction = processingInstruction;
1627 xmlDefaultSAXHandler.comment = comment;
1628 if (xmlGetWarningsDefaultValue == 0)
1629 xmlDefaultSAXHandler.warning = NULL;
1630 else
1631 xmlDefaultSAXHandler.warning = xmlParserWarning;
1632 xmlDefaultSAXHandler.error = xmlParserError;
1633 xmlDefaultSAXHandler.fatalError = xmlParserError;
1634}
1635
1636/*
1637 * Default handler for HTML, builds the DOM tree
1638 */
1639xmlSAXHandler htmlDefaultSAXHandler = {
1640 internalSubset,
1641 NULL,
1642 NULL,
1643 NULL,
1644 NULL,
1645 getEntity,
1646 NULL,
1647 NULL,
1648 NULL,
1649 NULL,
1650 NULL,
1651 setDocumentLocator,
1652 startDocument,
1653 endDocument,
1654 startElement,
1655 endElement,
1656 NULL,
1657 characters,
1658 ignorableWhitespace,
1659 NULL,
1660 comment,
1661 xmlParserWarning,
1662 xmlParserError,
1663 xmlParserError,
1664 getParameterEntity,
1665 cdataBlock,
1666 NULL,
1667};
1668
1669/**
1670 * htmlDefaultSAXHandlerInit:
1671 *
1672 * Initialize the default SAX handler
1673 */
1674void
1675htmlDefaultSAXHandlerInit(void)
1676{
1677 htmlDefaultSAXHandler.internalSubset = internalSubset;
1678 htmlDefaultSAXHandler.externalSubset = NULL;
1679 htmlDefaultSAXHandler.isStandalone = NULL;
1680 htmlDefaultSAXHandler.hasInternalSubset = NULL;
1681 htmlDefaultSAXHandler.hasExternalSubset = NULL;
1682 htmlDefaultSAXHandler.resolveEntity = NULL;
1683 htmlDefaultSAXHandler.getEntity = getEntity;
1684 htmlDefaultSAXHandler.getParameterEntity = NULL;
1685 htmlDefaultSAXHandler.entityDecl = NULL;
1686 htmlDefaultSAXHandler.attributeDecl = NULL;
1687 htmlDefaultSAXHandler.elementDecl = NULL;
1688 htmlDefaultSAXHandler.notationDecl = NULL;
1689 htmlDefaultSAXHandler.unparsedEntityDecl = NULL;
1690 htmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1691 htmlDefaultSAXHandler.startDocument = startDocument;
1692 htmlDefaultSAXHandler.endDocument = endDocument;
1693 htmlDefaultSAXHandler.startElement = startElement;
1694 htmlDefaultSAXHandler.endElement = endElement;
1695 htmlDefaultSAXHandler.reference = NULL;
1696 htmlDefaultSAXHandler.characters = characters;
1697 htmlDefaultSAXHandler.cdataBlock = cdataBlock;
1698 htmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1699 htmlDefaultSAXHandler.processingInstruction = NULL;
1700 htmlDefaultSAXHandler.comment = comment;
1701 htmlDefaultSAXHandler.warning = xmlParserWarning;
1702 htmlDefaultSAXHandler.error = xmlParserError;
1703 htmlDefaultSAXHandler.fatalError = xmlParserError;
1704}
1705
1706/*
1707 * Default handler for HTML, builds the DOM tree
1708 */
1709xmlSAXHandler sgmlDefaultSAXHandler = {
1710 internalSubset,
1711 NULL,
1712 NULL,
1713 NULL,
1714 NULL,
1715 getEntity,
1716 NULL,
1717 NULL,
1718 NULL,
1719 NULL,
1720 NULL,
1721 setDocumentLocator,
1722 startDocument,
1723 endDocument,
1724 startElement,
1725 endElement,
1726 NULL,
1727 characters,
1728 ignorableWhitespace,
1729 NULL,
1730 comment,
1731 xmlParserWarning,
1732 xmlParserError,
1733 xmlParserError,
1734 getParameterEntity,
1735 NULL,
1736 NULL,
1737};
1738
1739/**
1740 * sgmlDefaultSAXHandlerInit:
1741 *
1742 * Initialize the default SAX handler
1743 */
1744void
1745sgmlDefaultSAXHandlerInit(void)
1746{
1747 sgmlDefaultSAXHandler.internalSubset = internalSubset;
1748 sgmlDefaultSAXHandler.externalSubset = NULL;
1749 sgmlDefaultSAXHandler.isStandalone = NULL;
1750 sgmlDefaultSAXHandler.hasInternalSubset = NULL;
1751 sgmlDefaultSAXHandler.hasExternalSubset = NULL;
1752 sgmlDefaultSAXHandler.resolveEntity = NULL;
1753 sgmlDefaultSAXHandler.getEntity = getEntity;
1754 sgmlDefaultSAXHandler.getParameterEntity = NULL;
1755 sgmlDefaultSAXHandler.entityDecl = NULL;
1756 sgmlDefaultSAXHandler.attributeDecl = NULL;
1757 sgmlDefaultSAXHandler.elementDecl = NULL;
1758 sgmlDefaultSAXHandler.notationDecl = NULL;
1759 sgmlDefaultSAXHandler.unparsedEntityDecl = NULL;
1760 sgmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1761 sgmlDefaultSAXHandler.startDocument = startDocument;
1762 sgmlDefaultSAXHandler.endDocument = endDocument;
1763 sgmlDefaultSAXHandler.startElement = startElement;
1764 sgmlDefaultSAXHandler.endElement = endElement;
1765 sgmlDefaultSAXHandler.reference = NULL;
1766 sgmlDefaultSAXHandler.characters = characters;
1767 sgmlDefaultSAXHandler.cdataBlock = NULL;
1768 sgmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1769 sgmlDefaultSAXHandler.processingInstruction = NULL;
1770 sgmlDefaultSAXHandler.comment = comment;
1771 sgmlDefaultSAXHandler.warning = xmlParserWarning;
1772 sgmlDefaultSAXHandler.error = xmlParserError;
1773 sgmlDefaultSAXHandler.fatalError = xmlParserError;
1774}