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