Annotation of XML/SAX.c, revision 1.20

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

Webmaster