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