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