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