Annotation of XML/SAX.c, revision 1.21
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:
9: #include <stdio.h>
1.5 daniel 10: #include <stdlib.h>
1.1 daniel 11: #include "tree.h"
12: #include "parser.h"
1.10 daniel 13: #include "parserInternals.h"
14: #include "valid.h"
1.5 daniel 15: #include "entities.h"
1.9 daniel 16: #include "xml-error.h"
1.1 daniel 17:
1.15 daniel 18: /* #define DEBUG_SAX */
1.2 daniel 19:
1.5 daniel 20: /**
21: * getPublicId:
1.16 daniel 22: * @ctx: the user data (XML parser context)
1.5 daniel 23: *
1.1 daniel 24: * Return the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
1.5 daniel 25: *
1.8 daniel 26: * Returns a CHAR *
1.1 daniel 27: */
1.5 daniel 28: const CHAR *
1.11 daniel 29: getPublicId(void *ctx)
1.5 daniel 30: {
1.11 daniel 31: /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
1.1 daniel 32: return(NULL);
33: }
34:
1.5 daniel 35: /**
36: * getSystemId:
1.16 daniel 37: * @ctx: the user data (XML parser context)
1.5 daniel 38: *
1.12 daniel 39: * Return the system ID, basically URL or filename e.g.
1.5 daniel 40: * http://www.sgmlsource.com/dtds/memo.dtd
41: *
1.8 daniel 42: * Returns a CHAR *
1.5 daniel 43: */
44: const CHAR *
1.11 daniel 45: getSystemId(void *ctx)
1.5 daniel 46: {
1.11 daniel 47: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.2 daniel 48: return(ctxt->input->filename);
1.1 daniel 49: }
50:
1.5 daniel 51: /**
52: * getLineNumber:
1.16 daniel 53: * @ctx: the user data (XML parser context)
1.5 daniel 54: *
1.1 daniel 55: * Return the line number of the current parsing point.
1.5 daniel 56: *
1.8 daniel 57: * Returns an int
1.1 daniel 58: */
1.5 daniel 59: int
1.11 daniel 60: getLineNumber(void *ctx)
1.5 daniel 61: {
1.11 daniel 62: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.1 daniel 63: return(ctxt->input->line);
64: }
1.5 daniel 65:
66: /**
67: * getColumnNumber:
1.16 daniel 68: * @ctx: the user data (XML parser context)
1.5 daniel 69: *
1.1 daniel 70: * Return the column number of the current parsing point.
1.5 daniel 71: *
1.8 daniel 72: * Returns an int
1.1 daniel 73: */
1.5 daniel 74: int
1.11 daniel 75: getColumnNumber(void *ctx)
1.5 daniel 76: {
1.11 daniel 77: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.1 daniel 78: return(ctxt->input->col);
79: }
80:
81: /*
82: * The default SAX Locator.
83: */
84:
85: xmlSAXLocator xmlDefaultSAXLocator = {
86: getPublicId, getSystemId, getLineNumber, getColumnNumber
87: };
88:
1.5 daniel 89: /**
1.10 daniel 90: * isStandalone:
1.16 daniel 91: * @ctx: the user data (XML parser context)
1.10 daniel 92: *
93: * Is this document tagged standalone ?
94: *
95: * Returns 1 if true
96: */
97: int
1.11 daniel 98: isStandalone(void *ctx)
1.10 daniel 99: {
1.11 daniel 100: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10 daniel 101: return(ctxt->myDoc->standalone == 1);
102: }
103:
104: /**
105: * hasInternalSubset:
1.16 daniel 106: * @ctx: the user data (XML parser context)
1.10 daniel 107: *
108: * Does this document has an internal subset
109: *
110: * Returns 1 if true
111: */
112: int
1.11 daniel 113: hasInternalSubset(void *ctx)
1.10 daniel 114: {
1.11 daniel 115: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10 daniel 116: return(ctxt->myDoc->intSubset != NULL);
117: }
118:
119: /**
120: * hasExternalSubset:
1.16 daniel 121: * @ctx: the user data (XML parser context)
1.10 daniel 122: *
123: * Does this document has an external subset
124: *
125: * Returns 1 if true
126: */
127: int
1.11 daniel 128: hasExternalSubset(void *ctx)
1.10 daniel 129: {
1.11 daniel 130: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10 daniel 131: return(ctxt->myDoc->extSubset != NULL);
132: }
133:
134: /**
1.19 veillard 135: * internalSubset:
1.16 daniel 136: * @ctx: the user data (XML parser context)
1.10 daniel 137: *
138: * Does this document has an internal subset
139: */
140: void
1.11 daniel 141: internalSubset(void *ctx, const CHAR *name,
1.10 daniel 142: const CHAR *ExternalID, const CHAR *SystemID)
143: {
1.11 daniel 144: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10 daniel 145: #ifdef DEBUG_SAX
146: fprintf(stderr, "SAX.internalSubset(%s, %s, %s)\n",
147: name, ExternalID, SystemID);
148: #endif
149: xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
1.12 daniel 150: if ((ExternalID != NULL) || (SystemID != NULL)) {
1.21 ! daniel 151: ctxt->myDoc->extSubset = xmlParseDTD(ExternalID, SystemID);
1.12 daniel 152: }
1.10 daniel 153: }
154:
155: /**
1.5 daniel 156: * resolveEntity:
1.16 daniel 157: * @ctx: the user data (XML parser context)
1.5 daniel 158: * @publicId: The public ID of the entity
159: * @systemId: The system ID of the entity
160: *
1.1 daniel 161: * Special entity resolver, better left to the parser, it has
162: * more context than the application layer.
1.5 daniel 163: * The default behaviour is to NOT resolve the entities, in that case
164: * the ENTITY_REF nodes are built in the structure (and the parameter
1.6 daniel 165: * values).
1.5 daniel 166: *
1.8 daniel 167: * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
1.5 daniel 168: */
169: xmlParserInputPtr
1.11 daniel 170: resolveEntity(void *ctx, const CHAR *publicId, const CHAR *systemId)
1.5 daniel 171: {
1.12 daniel 172: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.2 daniel 173:
174: #ifdef DEBUG_SAX
175: fprintf(stderr, "SAX.resolveEntity(%s, %s)\n", publicId, systemId);
176: #endif
1.5 daniel 177:
1.10 daniel 178: /*
179: * TODO : not 100% sure that the appropriate handling in that case.
180: */
1.12 daniel 181: if (systemId != NULL) {
1.18 daniel 182: if (!xmlStrncmp(systemId, "http://", 7)) {
183: /* !!!!!!!!! TODO */
184: } else if (!xmlStrncmp(systemId, "ftp://", 6)) {
185: /* !!!!!!!!! TODO */
186: } else {
187: return(xmlNewInputFromFile(ctxt, systemId));
188: }
1.12 daniel 189: }
1.1 daniel 190: return(NULL);
191: }
192:
1.5 daniel 193: /**
1.10 daniel 194: * getEntity:
1.16 daniel 195: * @ctx: the user data (XML parser context)
1.10 daniel 196: * @name: The entity name
197: *
198: * Get an entity by name
199: *
1.13 daniel 200: * Returns the xmlEntityPtr if found.
1.10 daniel 201: */
202: xmlEntityPtr
1.11 daniel 203: getEntity(void *ctx, const CHAR *name)
1.10 daniel 204: {
1.11 daniel 205: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10 daniel 206: xmlEntityPtr ret;
207:
208: #ifdef DEBUG_SAX
209: fprintf(stderr, "SAX.getEntity(%s)\n", name);
210: #endif
211:
212: ret = xmlGetDocEntity(ctxt->myDoc, name);
213: return(ret);
214: }
215:
1.20 daniel 216: /**
217: * getParameterEntity:
218: * @ctx: the user data (XML parser context)
219: * @name: The entity name
220: *
221: * Get a parameter entity by name
222: *
223: * Returns the xmlEntityPtr if found.
224: */
225: xmlEntityPtr
226: getParameterEntity(void *ctx, const CHAR *name)
227: {
228: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
229: xmlEntityPtr ret;
230:
231: #ifdef DEBUG_SAX
232: fprintf(stderr, "SAX.getParameterEntity(%s)\n", name);
233: #endif
234:
235: ret = xmlGetParameterEntity(ctxt->myDoc, name);
236: return(ret);
237: }
238:
1.10 daniel 239:
240: /**
241: * entityDecl:
1.16 daniel 242: * @ctx: the user data (XML parser context)
1.10 daniel 243: * @name: the entity name
244: * @type: the entity type
245: * @publicId: The public ID of the entity
246: * @systemId: The system ID of the entity
247: * @content: the entity value (without processing).
248: *
249: * An entity definition has been parsed
250: */
251: void
1.11 daniel 252: entityDecl(void *ctx, const CHAR *name, int type,
1.10 daniel 253: const CHAR *publicId, const CHAR *systemId, CHAR *content)
254: {
1.11 daniel 255: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10 daniel 256:
257: #ifdef DEBUG_SAX
258: fprintf(stderr, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
259: name, type, publicId, systemId, content);
260: #endif
261: xmlAddDocEntity(ctxt->myDoc, name, type, publicId, systemId, content);
262: }
263:
264: /**
265: * attributeDecl:
1.16 daniel 266: * @ctx: the user data (XML parser context)
1.10 daniel 267: * @name: the attribute name
268: * @type: the attribute type
269: * @publicId: The public ID of the attribute
270: * @systemId: The system ID of the attribute
271: * @content: the attribute value (without processing).
272: *
273: * An attribute definition has been parsed
274: */
275: void
1.11 daniel 276: attributeDecl(void *ctx, const CHAR *elem, const CHAR *name,
1.10 daniel 277: int type, int def, const CHAR *defaultValue,
278: xmlEnumerationPtr tree)
279: {
1.11 daniel 280: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.21 ! daniel 281: xmlAttributePtr attr;
1.10 daniel 282:
283: #ifdef DEBUG_SAX
284: fprintf(stderr, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
285: elem, name, type, def, defaultValue);
286: #endif
1.21 ! daniel 287: attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
! 288: name, type, def, defaultValue, tree);
! 289: if (attr == 0) ctxt->valid = 0;
! 290: if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc)
! 291: ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
! 292: attr);
1.10 daniel 293: }
294:
295: /**
296: * elementDecl:
1.16 daniel 297: * @ctx: the user data (XML parser context)
1.10 daniel 298: * @name: the element name
299: * @type: the element type
300: * @publicId: The public ID of the element
301: * @systemId: The system ID of the element
302: * @content: the element value (without processing).
303: *
304: * An element definition has been parsed
305: */
306: void
1.11 daniel 307: elementDecl(void *ctx, const CHAR *name, int type,
1.10 daniel 308: xmlElementContentPtr content)
309: {
1.11 daniel 310: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.21 ! daniel 311: xmlElementPtr elem;
1.10 daniel 312:
313: #ifdef DEBUG_SAX
314: fprintf(stderr, "SAX.elementDecl(%s, %d, ...)\n",
315: name, type);
316: #endif
1.21 ! daniel 317:
! 318: elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
! 319: name, type, content);
! 320: if (elem == 0) ctxt->valid = 0;
! 321: if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc)
! 322: ctxt->valid &= xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
1.10 daniel 323: }
324:
325: /**
1.5 daniel 326: * notationDecl:
1.16 daniel 327: * @ctx: the user data (XML parser context)
1.5 daniel 328: * @name: The name of the notation
329: * @publicId: The public ID of the entity
330: * @systemId: The system ID of the entity
331: *
1.1 daniel 332: * What to do when a notation declaration has been parsed.
333: * TODO Not handled currently.
334: */
1.5 daniel 335: void
1.11 daniel 336: notationDecl(void *ctx, const CHAR *name,
1.5 daniel 337: const CHAR *publicId, const CHAR *systemId)
338: {
1.11 daniel 339: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.21 ! daniel 340: xmlNotationPtr nota;
! 341:
1.2 daniel 342: #ifdef DEBUG_SAX
343: fprintf(stderr, "SAX.notationDecl(%s, %s, %s)\n", name, publicId, systemId);
344: #endif
1.21 ! daniel 345:
! 346: nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
! 347: publicId, systemId);
! 348: if (nota == 0) ctxt->valid = 0;
! 349: if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc)
! 350: ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
! 351: nota);
1.1 daniel 352: }
353:
1.5 daniel 354: /**
355: * unparsedEntityDecl:
1.16 daniel 356: * @ctx: the user data (XML parser context)
1.5 daniel 357: * @name: The name of the entity
358: * @publicId: The public ID of the entity
359: * @systemId: The system ID of the entity
360: * @notationName: the name of the notation
361: *
1.1 daniel 362: * What to do when an unparsed entity declaration is parsed
363: * TODO Create an Entity node.
364: */
1.5 daniel 365: void
1.11 daniel 366: unparsedEntityDecl(void *ctx, const CHAR *name,
1.5 daniel 367: const CHAR *publicId, const CHAR *systemId,
368: const CHAR *notationName)
369: {
1.11 daniel 370: /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
1.2 daniel 371: #ifdef DEBUG_SAX
372: fprintf(stderr, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
373: name, publicId, systemId, notationName);
374: #endif
1.1 daniel 375: }
376:
1.5 daniel 377: /**
378: * setDocumentLocator:
1.16 daniel 379: * @ctx: the user data (XML parser context)
1.5 daniel 380: * @loc: A SAX Locator
381: *
1.1 daniel 382: * Receive the document locator at startup, actually xmlDefaultSAXLocator
383: * Everything is available on the context, so this is useless in our case.
384: */
1.5 daniel 385: void
1.11 daniel 386: setDocumentLocator(void *ctx, xmlSAXLocatorPtr loc)
1.5 daniel 387: {
1.11 daniel 388: /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
1.2 daniel 389: #ifdef DEBUG_SAX
390: fprintf(stderr, "SAX.setDocumentLocator()\n");
391: #endif
1.1 daniel 392: }
393:
1.5 daniel 394: /**
395: * startDocument:
1.16 daniel 396: * @ctx: the user data (XML parser context)
1.5 daniel 397: *
1.1 daniel 398: * called when the document start being processed.
399: */
1.5 daniel 400: void
1.11 daniel 401: startDocument(void *ctx)
1.5 daniel 402: {
1.11 daniel 403: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10 daniel 404: xmlDocPtr doc;
405:
1.2 daniel 406: #ifdef DEBUG_SAX
407: fprintf(stderr, "SAX.startDocument()\n");
408: #endif
1.10 daniel 409: doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
410: if (doc != NULL) {
411: if (ctxt->encoding != NULL)
412: doc->encoding = xmlStrdup(ctxt->encoding);
413: else
414: doc->encoding = NULL;
415: doc->standalone = ctxt->standalone;
416: }
1.1 daniel 417: }
418:
1.5 daniel 419: /**
420: * endDocument:
1.16 daniel 421: * @ctx: the user data (XML parser context)
1.5 daniel 422: *
1.1 daniel 423: * called when the document end has been detected.
424: */
1.5 daniel 425: void
1.11 daniel 426: endDocument(void *ctx)
1.5 daniel 427: {
1.11 daniel 428: /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
1.2 daniel 429: #ifdef DEBUG_SAX
430: fprintf(stderr, "SAX.endDocument()\n");
431: #endif
1.1 daniel 432: }
433:
1.5 daniel 434: /**
1.10 daniel 435: * attribute:
1.16 daniel 436: * @ctx: the user data (XML parser context)
1.10 daniel 437: * @name: The attribute name
438: * @value: The attribute value
439: *
440: * Handle an attribute that has been read by the parser.
441: * The default handling is to convert the attribute into an
442: * DOM subtree and past it in a new xmlAttr element added to
443: * the element.
444: */
445: void
1.11 daniel 446: attribute(void *ctx, const CHAR *fullname, const CHAR *value)
1.10 daniel 447: {
1.11 daniel 448: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10 daniel 449: xmlAttrPtr ret;
450: CHAR *name;
451: CHAR *ns;
452:
453: /****************
454: #ifdef DEBUG_SAX
455: fprintf(stderr, "SAX.attribute(%s, %s)\n", fullname, value);
456: #endif
457: ****************/
458: /*
459: * Split the full name into a namespace prefix and the tag name
460: */
461: name = xmlSplitQName(fullname, &ns);
462:
463: /*
464: * Check whether it's a namespace definition
465: */
466: if ((ns == NULL) &&
467: (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
468: (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
469: /* a default namespace definition */
470: xmlNewNs(ctxt->node, value, NULL);
471: if (name != NULL)
472: free(name);
473: return;
474: }
475: if ((ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
476: (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
477: /* a standard namespace definition */
478: xmlNewNs(ctxt->node, value, name);
479: free(ns);
480: if (name != NULL)
481: free(name);
482: return;
483: }
484:
485: ret = xmlNewProp(ctxt->node, name, NULL);
1.14 daniel 486: if ((ret != NULL) && (ctxt->replaceEntities == 0))
1.10 daniel 487: ret->val = xmlStringGetNodeList(ctxt->myDoc, value);
488: if (name != NULL)
489: free(name);
490: if (ns != NULL)
491: free(ns);
492: }
493:
494: /**
1.5 daniel 495: * startElement:
1.16 daniel 496: * @ctx: the user data (XML parser context)
1.5 daniel 497: * @name: The element name
1.10 daniel 498: * @atts: An array of name/value attributes pairs, NULL terminated
1.5 daniel 499: *
1.1 daniel 500: * called when an opening tag has been processed.
501: * TODO We currently have a small pblm with the arguments ...
502: */
1.5 daniel 503: void
1.11 daniel 504: startElement(void *ctx, const CHAR *fullname, const CHAR **atts)
1.5 daniel 505: {
1.11 daniel 506: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10 daniel 507: xmlNodePtr ret;
508: xmlNodePtr parent = ctxt->node;
509: xmlNsPtr ns;
510: CHAR *name;
511: CHAR *prefix;
512: const CHAR *att;
513: const CHAR *value;
514:
515: int i;
516:
1.2 daniel 517: #ifdef DEBUG_SAX
1.10 daniel 518: fprintf(stderr, "SAX.startElement(%s)\n", fullname);
1.2 daniel 519: #endif
1.10 daniel 520: /*
521: * Split the full name into a namespace prefix and the tag name
522: */
523: name = xmlSplitQName(fullname, &prefix);
524:
525:
526: /*
527: * Note : the namespace resolution is deferred until the end of the
528: * attributes parsing, since local namespace can be defined as
529: * an attribute at this level.
530: */
531: ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL);
532: if (ret == NULL) return;
533: if (ctxt->myDoc->root == NULL)
534: ctxt->myDoc->root = ret;
535:
536: /*
537: * We are parsing a new node.
538: */
539: nodePush(ctxt, ret);
540:
541: /*
542: * Link the child element
543: */
544: if (parent != NULL)
545: xmlAddChild(parent, ctxt->node);
546:
547: /*
548: * process all the attributes.
549: */
550: if (atts != NULL) {
551: i = 0;
552: att = atts[i++];
553: value = atts[i++];
554: while ((att != NULL) && (value != NULL)) {
555: /*
556: * Handle one pair of attribute/value
557: */
558: attribute(ctxt, att, value);
559:
560: /*
561: * Next ones
562: */
563: att = atts[i++];
564: value = atts[i++];
565: }
566: }
567:
568: /*
569: * Search the namespace, note that since the attributes have been
570: * processed, the local namespaces are available.
571: */
572: ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
573: if ((ns == NULL) && (parent != NULL))
574: ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
575: xmlSetNs(ret, ns);
576:
577: if (prefix != NULL)
578: free(prefix);
579: if (name != NULL)
580: free(name);
581:
1.1 daniel 582: }
583:
1.5 daniel 584: /**
585: * endElement:
1.16 daniel 586: * @ctx: the user data (XML parser context)
1.5 daniel 587: * @name: The element name
588: *
1.1 daniel 589: * called when the end of an element has been detected.
590: */
1.5 daniel 591: void
1.11 daniel 592: endElement(void *ctx, const CHAR *name)
1.5 daniel 593: {
1.11 daniel 594: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10 daniel 595: xmlParserNodeInfo node_info;
596: xmlNodePtr cur = ctxt->node;
597:
1.2 daniel 598: #ifdef DEBUG_SAX
1.10 daniel 599: if (name == NULL)
600: fprintf(stderr, "SAX.endElement(NULL)\n");
601: else
602: fprintf(stderr, "SAX.endElement(%s)\n", name);
603: #endif
604:
605: /* Capture end position and add node */
606: if (cur != NULL && ctxt->record_info) {
607: node_info.end_pos = ctxt->input->cur - ctxt->input->base;
608: node_info.end_line = ctxt->input->line;
609: node_info.node = cur;
610: xmlParserAddNodeInfo(ctxt, &node_info);
611: }
612:
613: /*
614: * end of parsing of this node.
615: */
616: nodePop(ctxt);
1.1 daniel 617: }
618:
1.5 daniel 619: /**
1.10 daniel 620: * reference:
1.16 daniel 621: * @ctx: the user data (XML parser context)
1.10 daniel 622: * @name: The entity name
1.5 daniel 623: *
1.10 daniel 624: * called when an entity reference is detected.
1.5 daniel 625: */
626: void
1.11 daniel 627: reference(void *ctx, const CHAR *name)
1.5 daniel 628: {
1.11 daniel 629: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10 daniel 630: xmlNodePtr ret;
631:
1.5 daniel 632: #ifdef DEBUG_SAX
1.10 daniel 633: fprintf(stderr, "SAX.reference(%s)\n", name);
1.5 daniel 634: #endif
1.10 daniel 635: ret = xmlNewReference(ctxt->myDoc, name);
636: xmlAddChild(ctxt->node, ret);
1.5 daniel 637: }
638:
639: /**
640: * characters:
1.16 daniel 641: * @ctx: the user data (XML parser context)
1.5 daniel 642: * @ch: a CHAR string
643: * @len: the number of CHAR
644: *
1.1 daniel 645: * receiving some chars from the parser.
646: * Question: how much at a time ???
647: */
1.5 daniel 648: void
1.11 daniel 649: characters(void *ctx, const CHAR *ch, int len)
1.5 daniel 650: {
1.11 daniel 651: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.2 daniel 652: xmlNodePtr lastChild;
653:
654: #ifdef DEBUG_SAX
1.10 daniel 655: fprintf(stderr, "SAX.characters(%.30s, %d)\n", ch, len);
1.2 daniel 656: #endif
657: /*
658: * Handle the data if any. If there is no child
659: * add it as content, otherwise if the last child is text,
660: * concatenate it, else create a new node of type text.
661: */
662:
663: lastChild = xmlGetLastChild(ctxt->node);
664: if (lastChild == NULL)
1.10 daniel 665: xmlNodeAddContentLen(ctxt->node, ch, len);
1.2 daniel 666: else {
667: if (xmlNodeIsText(lastChild))
1.10 daniel 668: xmlTextConcat(lastChild, ch, len);
1.2 daniel 669: else {
1.10 daniel 670: lastChild = xmlNewTextLen(ch, len);
1.2 daniel 671: xmlAddChild(ctxt->node, lastChild);
672: }
673: }
1.1 daniel 674: }
675:
1.5 daniel 676: /**
677: * ignorableWhitespace:
1.16 daniel 678: * @ctx: the user data (XML parser context)
1.5 daniel 679: * @ch: a CHAR string
680: * @len: the number of CHAR
681: *
1.1 daniel 682: * receiving some ignorable whitespaces from the parser.
683: * Question: how much at a time ???
684: */
1.5 daniel 685: void
1.11 daniel 686: ignorableWhitespace(void *ctx, const CHAR *ch, int len)
1.5 daniel 687: {
1.11 daniel 688: /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
1.2 daniel 689: #ifdef DEBUG_SAX
1.10 daniel 690: fprintf(stderr, "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len);
1.2 daniel 691: #endif
1.1 daniel 692: }
693:
1.5 daniel 694: /**
695: * processingInstruction:
1.16 daniel 696: * @ctx: the user data (XML parser context)
1.5 daniel 697: * @target: the target name
698: * @data: the PI data's
699: * @len: the number of CHAR
700: *
701: * A processing instruction has been parsed.
702: */
703: void
1.11 daniel 704: processingInstruction(void *ctx, const CHAR *target,
1.5 daniel 705: const CHAR *data)
706: {
1.11 daniel 707: /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
1.2 daniel 708: #ifdef DEBUG_SAX
709: fprintf(stderr, "SAX.processingInstruction(%s, %s)\n", target, data);
710: #endif
1.1 daniel 711: }
712:
1.10 daniel 713: /**
714: * globalNamespace:
1.16 daniel 715: * @ctx: the user data (XML parser context)
1.10 daniel 716: * @href: the namespace associated URN
717: * @prefix: the namespace prefix
718: *
719: * An old global namespace has been parsed.
720: */
721: void
1.11 daniel 722: globalNamespace(void *ctx, const CHAR *href, const CHAR *prefix)
1.10 daniel 723: {
1.11 daniel 724: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10 daniel 725: #ifdef DEBUG_SAX
726: fprintf(stderr, "SAX.globalNamespace(%s, %s)\n", href, prefix);
727: #endif
728: xmlNewGlobalNs(ctxt->myDoc, href, prefix);
729: }
730:
731: /**
732: * setNamespace:
1.16 daniel 733: * @ctx: the user data (XML parser context)
1.10 daniel 734: * @name: the namespace prefix
735: *
736: * Set the current element namespace.
737: */
738: void
1.11 daniel 739: setNamespace(void *ctx, const CHAR *name)
1.10 daniel 740: {
1.11 daniel 741: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10 daniel 742: xmlNsPtr ns;
743: xmlNodePtr parent;
744:
745: #ifdef DEBUG_SAX
746: fprintf(stderr, "SAX.setNamespace(%s)\n", name);
747: #endif
748: ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name);
749: if (ns == NULL) { /* ctxt->node may not have a parent yet ! */
750: if (ctxt->nodeNr >= 2) {
751: parent = ctxt->nodeTab[ctxt->nodeNr - 2];
752: if (parent != NULL)
753: ns = xmlSearchNs(ctxt->myDoc, parent, name);
754: }
755: }
756: xmlSetNs(ctxt->node, ns);
757: }
758:
759: /**
760: * getNamespace:
1.16 daniel 761: * @ctx: the user data (XML parser context)
1.10 daniel 762: *
763: * Get the current element namespace.
764: */
765: xmlNsPtr
1.11 daniel 766: getNamespace(void *ctx)
1.10 daniel 767: {
1.11 daniel 768: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10 daniel 769: xmlNsPtr ret;
770:
771: #ifdef DEBUG_SAX
772: fprintf(stderr, "SAX.getNamespace()\n");
773: #endif
774: ret = ctxt->node->ns;
775: return(ret);
776: }
777:
778: /**
779: * checkNamespace:
1.16 daniel 780: * @ctx: the user data (XML parser context)
1.10 daniel 781: * @namespace: the namespace to check against
782: *
783: * Check that the current element namespace is the same as the
784: * one read upon parsing.
785: */
786: int
1.11 daniel 787: checkNamespace(void *ctx, CHAR *namespace)
1.10 daniel 788: {
1.11 daniel 789: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10 daniel 790: xmlNodePtr cur = ctxt->node;
791:
792: #ifdef DEBUG_SAX
793: fprintf(stderr, "SAX.checkNamespace(%s)\n", namespace);
794: #endif
795:
796: /*
797: * Check that the Name in the ETag is the same as in the STag.
798: */
799: if (namespace == NULL) {
800: if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
801: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
802: ctxt->sax->error(ctxt,
803: "End tags for %s don't hold the namespace %s\n",
804: cur->name, cur->ns->prefix);
805: ctxt->wellFormed = 0;
806: }
807: } else {
808: if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) {
809: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
810: ctxt->sax->error(ctxt,
811: "End tags %s holds a prefix %s not used by the open tag\n",
812: cur->name, namespace);
813: ctxt->wellFormed = 0;
814: } else if (strcmp(namespace, cur->ns->prefix)) {
815: if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
816: ctxt->sax->error(ctxt,
817: "Start and End tags for %s don't use the same namespaces: %s and %s\n",
818: cur->name, cur->ns->prefix, namespace);
819: ctxt->wellFormed = 0;
820: } else
821: return(1);
822: }
823: return(0);
824: }
825:
826: /**
827: * namespaceDecl:
1.16 daniel 828: * @ctx: the user data (XML parser context)
1.10 daniel 829: * @href: the namespace associated URN
830: * @prefix: the namespace prefix
831: *
832: * A namespace has been parsed.
833: */
834: void
1.11 daniel 835: namespaceDecl(void *ctx, const CHAR *href, const CHAR *prefix)
1.10 daniel 836: {
1.11 daniel 837: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10 daniel 838: #ifdef DEBUG_SAX
839: if (prefix == NULL)
840: fprintf(stderr, "SAX.namespaceDecl(%s, NULL)\n", href);
841: else
842: fprintf(stderr, "SAX.namespaceDecl(%s, %s)\n", href, prefix);
843: #endif
844: xmlNewNs(ctxt->node, href, prefix);
845: }
846:
847: /**
848: * comment:
1.16 daniel 849: * @ctx: the user data (XML parser context)
1.10 daniel 850: * @value: the comment content
851: *
852: * A comment has been parsed.
853: */
854: void
1.11 daniel 855: comment(void *ctx, const CHAR *value)
1.10 daniel 856: {
1.11 daniel 857: xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.17 daniel 858: xmlNodePtr ret;
859:
1.10 daniel 860: #ifdef DEBUG_SAX
861: fprintf(stderr, "SAX.comment(%s)\n", value);
862: #endif
1.17 daniel 863: ret = xmlNewDocComment(ctxt->myDoc, value);
864: xmlAddChild(ctxt->node, ret);
1.10 daniel 865: }
866:
1.18 daniel 867: /*
868: * Default handler for XML, builds the DOM tree
869: */
1.1 daniel 870: xmlSAXHandler xmlDefaultSAXHandler = {
1.10 daniel 871: internalSubset,
872: isStandalone,
873: hasInternalSubset,
874: hasExternalSubset,
1.1 daniel 875: resolveEntity,
1.10 daniel 876: getEntity,
877: entityDecl,
1.1 daniel 878: notationDecl,
1.10 daniel 879: attributeDecl,
880: elementDecl,
1.1 daniel 881: unparsedEntityDecl,
882: setDocumentLocator,
883: startDocument,
884: endDocument,
885: startElement,
886: endElement,
1.10 daniel 887: reference,
1.1 daniel 888: characters,
889: ignorableWhitespace,
890: processingInstruction,
1.10 daniel 891: comment,
1.1 daniel 892: xmlParserWarning,
893: xmlParserError,
1.2 daniel 894: xmlParserError,
1.20 daniel 895: getParameterEntity,
1.1 daniel 896: };
1.2 daniel 897:
1.5 daniel 898: /**
899: * xmlDefaultSAXHandlerInit:
900: *
901: * Initialize the default SAX handler
902: */
903: void
904: xmlDefaultSAXHandlerInit(void)
905: {
1.10 daniel 906: xmlDefaultSAXHandler.internalSubset = internalSubset;
907: xmlDefaultSAXHandler.isStandalone = isStandalone;
908: xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
909: xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
1.2 daniel 910: xmlDefaultSAXHandler.resolveEntity = resolveEntity;
1.10 daniel 911: xmlDefaultSAXHandler.getEntity = getEntity;
1.20 daniel 912: xmlDefaultSAXHandler.getParameterEntity = getParameterEntity;
1.10 daniel 913: xmlDefaultSAXHandler.entityDecl = entityDecl;
914: xmlDefaultSAXHandler.attributeDecl = attributeDecl;
915: xmlDefaultSAXHandler.elementDecl = elementDecl;
1.2 daniel 916: xmlDefaultSAXHandler.notationDecl = notationDecl;
917: xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
918: xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
919: xmlDefaultSAXHandler.startDocument = startDocument;
920: xmlDefaultSAXHandler.endDocument = endDocument;
921: xmlDefaultSAXHandler.startElement = startElement;
922: xmlDefaultSAXHandler.endElement = endElement;
1.10 daniel 923: xmlDefaultSAXHandler.reference = reference;
1.2 daniel 924: xmlDefaultSAXHandler.characters = characters;
925: xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
926: xmlDefaultSAXHandler.processingInstruction = processingInstruction;
1.10 daniel 927: xmlDefaultSAXHandler.comment = comment;
1.2 daniel 928: xmlDefaultSAXHandler.warning = xmlParserWarning;
929: xmlDefaultSAXHandler.error = xmlParserError;
930: xmlDefaultSAXHandler.fatalError = xmlParserError;
1.18 daniel 931: }
932:
933: /*
934: * Default handler for HTML, builds the DOM tree
935: */
936: xmlSAXHandler htmlDefaultSAXHandler = {
937: NULL,
938: NULL,
939: NULL,
940: NULL,
941: NULL,
942: getEntity,
943: NULL,
944: NULL,
945: NULL,
946: NULL,
947: NULL,
948: setDocumentLocator,
949: startDocument,
950: endDocument,
951: startElement,
952: endElement,
953: NULL,
954: characters,
955: ignorableWhitespace,
956: NULL,
957: comment,
958: xmlParserWarning,
959: xmlParserError,
960: xmlParserError,
1.20 daniel 961: getParameterEntity,
1.18 daniel 962: };
963:
964: /**
965: * htmlDefaultSAXHandlerInit:
966: *
967: * Initialize the default SAX handler
968: */
969: void
970: htmlDefaultSAXHandlerInit(void)
971: {
972: htmlDefaultSAXHandler.internalSubset = NULL;
973: htmlDefaultSAXHandler.isStandalone = NULL;
974: htmlDefaultSAXHandler.hasInternalSubset = NULL;
975: htmlDefaultSAXHandler.hasExternalSubset = NULL;
976: htmlDefaultSAXHandler.resolveEntity = NULL;
977: htmlDefaultSAXHandler.getEntity = getEntity;
1.20 daniel 978: htmlDefaultSAXHandler.getParameterEntity = NULL;
1.18 daniel 979: htmlDefaultSAXHandler.entityDecl = NULL;
980: htmlDefaultSAXHandler.attributeDecl = NULL;
981: htmlDefaultSAXHandler.elementDecl = NULL;
982: htmlDefaultSAXHandler.notationDecl = NULL;
983: htmlDefaultSAXHandler.unparsedEntityDecl = NULL;
984: htmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
985: htmlDefaultSAXHandler.startDocument = startDocument;
986: htmlDefaultSAXHandler.endDocument = endDocument;
987: htmlDefaultSAXHandler.startElement = startElement;
988: htmlDefaultSAXHandler.endElement = endElement;
989: htmlDefaultSAXHandler.reference = NULL;
990: htmlDefaultSAXHandler.characters = characters;
991: htmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
992: htmlDefaultSAXHandler.processingInstruction = NULL;
993: htmlDefaultSAXHandler.comment = comment;
994: htmlDefaultSAXHandler.warning = xmlParserWarning;
995: htmlDefaultSAXHandler.error = xmlParserError;
996: htmlDefaultSAXHandler.fatalError = xmlParserError;
1.2 daniel 997: }
Webmaster