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