Annotation of XML/SAX.c, revision 1.16

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

Webmaster