Annotation of XML/SAX.c, revision 1.11

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

Webmaster