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