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