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