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