Annotation of XML/SAX.c, revision 1.59

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: 
1.32      daniel      9: 
1.39      daniel     10: #ifdef WIN32
                     11: #include "win32config.h"
                     12: #else
                     13: #include "config.h"
                     14: #endif
1.1       daniel     15: #include <stdio.h>
1.5       daniel     16: #include <stdlib.h>
1.57      daniel     17: #include <libxml/xmlmemory.h>
                     18: #include <libxml/tree.h>
                     19: #include <libxml/parser.h>
                     20: #include <libxml/parserInternals.h>
                     21: #include <libxml/valid.h>
                     22: #include <libxml/entities.h>
1.9       daniel     23: #include "xml-error.h"
1.57      daniel     24: #include <libxml/debugXML.h>
                     25: #include <libxml/xmlIO.h>
                     26: #include <libxml/SAX.h>
1.1       daniel     27: 
1.15      daniel     28: /* #define DEBUG_SAX */
1.26      daniel     29: /* #define DEBUG_SAX_TREE */
1.2       daniel     30: 
1.5       daniel     31: /**
                     32:  * getPublicId:
1.16      daniel     33:  * @ctx: the user data (XML parser context)
1.5       daniel     34:  *
1.1       daniel     35:  * Return the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
1.5       daniel     36:  *
1.34      daniel     37:  * Returns a xmlChar *
1.1       daniel     38:  */
1.34      daniel     39: const xmlChar *
1.11      daniel     40: getPublicId(void *ctx)
1.5       daniel     41: {
1.11      daniel     42:     /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
1.1       daniel     43:     return(NULL);
                     44: }
                     45: 
1.5       daniel     46: /**
                     47:  * getSystemId:
1.16      daniel     48:  * @ctx: the user data (XML parser context)
1.5       daniel     49:  *
1.12      daniel     50:  * Return the system ID, basically URL or filename e.g.
1.5       daniel     51:  * http://www.sgmlsource.com/dtds/memo.dtd
                     52:  *
1.34      daniel     53:  * Returns a xmlChar *
1.5       daniel     54:  */
1.34      daniel     55: const xmlChar *
1.11      daniel     56: getSystemId(void *ctx)
1.5       daniel     57: {
1.11      daniel     58:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.28      daniel     59:     return(BAD_CAST ctxt->input->filename); 
1.1       daniel     60: }
                     61: 
1.5       daniel     62: /**
                     63:  * getLineNumber:
1.16      daniel     64:  * @ctx: the user data (XML parser context)
1.5       daniel     65:  *
1.1       daniel     66:  * Return the line number of the current parsing point.
1.5       daniel     67:  *
1.8       daniel     68:  * Returns an int
1.1       daniel     69:  */
1.5       daniel     70: int
1.11      daniel     71: getLineNumber(void *ctx)
1.5       daniel     72: {
1.11      daniel     73:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.1       daniel     74:     return(ctxt->input->line);
                     75: }
1.5       daniel     76: 
                     77: /**
                     78:  * getColumnNumber:
1.16      daniel     79:  * @ctx: the user data (XML parser context)
1.5       daniel     80:  *
1.1       daniel     81:  * Return the column number of the current parsing point.
1.5       daniel     82:  *
1.8       daniel     83:  * Returns an int
1.1       daniel     84:  */
1.5       daniel     85: int
1.11      daniel     86: getColumnNumber(void *ctx)
1.5       daniel     87: {
1.11      daniel     88:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.1       daniel     89:     return(ctxt->input->col);
                     90: }
                     91: 
                     92: /*
                     93:  * The default SAX Locator.
                     94:  */
                     95: 
                     96: xmlSAXLocator xmlDefaultSAXLocator = {
                     97:     getPublicId, getSystemId, getLineNumber, getColumnNumber
                     98: };
                     99: 
1.5       daniel    100: /**
1.10      daniel    101:  * isStandalone:
1.16      daniel    102:  * @ctx: the user data (XML parser context)
1.10      daniel    103:  *
                    104:  * Is this document tagged standalone ?
                    105:  *
                    106:  * Returns 1 if true
                    107:  */
                    108: int
1.11      daniel    109: isStandalone(void *ctx)
1.10      daniel    110: {
1.11      daniel    111:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10      daniel    112:     return(ctxt->myDoc->standalone == 1);
                    113: }
                    114: 
                    115: /**
                    116:  * hasInternalSubset:
1.16      daniel    117:  * @ctx: the user data (XML parser context)
1.10      daniel    118:  *
                    119:  * Does this document has an internal subset
                    120:  *
                    121:  * Returns 1 if true
                    122:  */
                    123: int
1.11      daniel    124: hasInternalSubset(void *ctx)
1.10      daniel    125: {
1.11      daniel    126:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10      daniel    127:     return(ctxt->myDoc->intSubset != NULL);
                    128: }
                    129: 
                    130: /**
                    131:  * hasExternalSubset:
1.16      daniel    132:  * @ctx: the user data (XML parser context)
1.10      daniel    133:  *
                    134:  * Does this document has an external subset
                    135:  *
                    136:  * Returns 1 if true
                    137:  */
                    138: int
1.11      daniel    139: hasExternalSubset(void *ctx)
1.10      daniel    140: {
1.11      daniel    141:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10      daniel    142:     return(ctxt->myDoc->extSubset != NULL);
                    143: }
                    144: 
                    145: /**
1.19      veillard  146:  * internalSubset:
1.58      daniel    147:  * @ctx:  the user data (XML parser context)
                    148:  * @name:  the root element name
                    149:  * @ExternalID:  the external ID
                    150:  * @SystemID:  the SYSTEM ID (e.g. filename or URL)
1.10      daniel    151:  *
1.41      daniel    152:  * Callback on internal subset declaration.
1.10      daniel    153:  */
                    154: void
1.34      daniel    155: internalSubset(void *ctx, const xmlChar *name,
                    156:               const xmlChar *ExternalID, const xmlChar *SystemID)
1.10      daniel    157: {
1.11      daniel    158:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10      daniel    159: #ifdef DEBUG_SAX
                    160:     fprintf(stderr, "SAX.internalSubset(%s, %s, %s)\n",
                    161:             name, ExternalID, SystemID);
                    162: #endif
                    163:     xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
1.49      daniel    164: }
                    165: 
                    166: /**
                    167:  * externalSubset:
                    168:  * @ctx: the user data (XML parser context)
1.58      daniel    169:  * @name:  the root element name
                    170:  * @ExternalID:  the external ID
                    171:  * @SystemID:  the SYSTEM ID (e.g. filename or URL)
1.49      daniel    172:  *
                    173:  * Callback on external subset declaration.
                    174:  */
                    175: void
                    176: externalSubset(void *ctx, const xmlChar *name,
                    177:               const xmlChar *ExternalID, const xmlChar *SystemID)
                    178: {
                    179:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
                    180: #ifdef DEBUG_SAX
                    181:     fprintf(stderr, "SAX.externalSubset(%s, %s, %s)\n",
                    182:             name, ExternalID, SystemID);
                    183: #endif
1.24      daniel    184:     if (((ExternalID != NULL) || (SystemID != NULL)) &&
                    185:         (ctxt->validate && ctxt->wellFormed && ctxt->myDoc)) {
                    186:        /*
                    187:         * Try to fetch and parse the external subset.
                    188:         */
1.49      daniel    189:        xmlParserInputPtr oldinput;
                    190:        int oldinputNr;
                    191:        int oldinputMax;
                    192:        xmlParserInputPtr *oldinputTab;
1.50      daniel    193:        int oldwellFormed;
1.24      daniel    194:        xmlParserInputPtr input = NULL;
                    195:        xmlCharEncoding enc;
                    196: 
                    197:        /*
                    198:         * Ask the Entity resolver to load the damn thing
                    199:         */
1.49      daniel    200:        if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
                    201:            input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
1.24      daniel    202:                                                SystemID);
                    203:        if (input == NULL) {
                    204:            return;
                    205:        }
                    206: 
1.50      daniel    207:        xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
                    208: 
1.49      daniel    209:        /*
                    210:         * make sure we won't destroy the main document context
                    211:         */
                    212:        oldinput = ctxt->input;
                    213:        oldinputNr = ctxt->inputNr;
                    214:        oldinputMax = ctxt->inputMax;
                    215:        oldinputTab = ctxt->inputTab;
1.50      daniel    216:        oldwellFormed = ctxt->wellFormed;
1.49      daniel    217: 
                    218:        ctxt->inputTab = (xmlParserInputPtr *)
                    219:                         xmlMalloc(5 * sizeof(xmlParserInputPtr));
                    220:        if (ctxt->inputTab == NULL) {
                    221:            ctxt->errNo = XML_ERR_NO_MEMORY;
                    222:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    223:                ctxt->sax->error(ctxt->userData, 
                    224:                     "externalSubset: out of memory\n");
                    225:            ctxt->errNo = XML_ERR_NO_MEMORY;
                    226:            ctxt->input = oldinput;
                    227:            ctxt->inputNr = oldinputNr;
                    228:            ctxt->inputMax = oldinputMax;
                    229:            ctxt->inputTab = oldinputTab;
                    230:            return;
                    231:        }
                    232:        ctxt->inputNr = 0;
                    233:        ctxt->inputMax = 5;
                    234:        ctxt->input = NULL;
                    235:        xmlPushInput(ctxt, input);
1.43      daniel    236: 
1.24      daniel    237:        /*
1.43      daniel    238:         * On the fly encoding conversion if needed
1.24      daniel    239:         */
1.49      daniel    240:        enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
                    241:        xmlSwitchEncoding(ctxt, enc);
1.24      daniel    242: 
                    243:        if (input->filename == NULL)
1.28      daniel    244:            input->filename = (char *) xmlStrdup(SystemID);
1.24      daniel    245:        input->line = 1;
                    246:        input->col = 1;
1.49      daniel    247:        input->base = ctxt->input->cur;
                    248:        input->cur = ctxt->input->cur;
1.24      daniel    249:        input->free = NULL;
                    250: 
                    251:        /*
                    252:         * let's parse that entity knowing it's an external subset.
                    253:         */
1.49      daniel    254:        xmlParseExternalSubset(ctxt, ExternalID, SystemID);
                    255: 
                    256:         /*
                    257:         * Free up the external entities
                    258:         */
1.24      daniel    259: 
1.49      daniel    260:        while (ctxt->inputNr > 1)
                    261:            xmlPopInput(ctxt);
                    262:        xmlFreeInputStream(ctxt->input);
                    263:         xmlFree(ctxt->inputTab);
                    264: 
                    265:        /*
                    266:         * Restore the parsing context of the main entity
                    267:         */
                    268:        ctxt->input = oldinput;
                    269:        ctxt->inputNr = oldinputNr;
                    270:        ctxt->inputMax = oldinputMax;
                    271:        ctxt->inputTab = oldinputTab;
1.52      daniel    272:        /* ctxt->wellFormed = oldwellFormed; */
1.12      daniel    273:     }
1.10      daniel    274: }
                    275: 
                    276: /**
1.5       daniel    277:  * resolveEntity:
1.16      daniel    278:  * @ctx: the user data (XML parser context)
1.5       daniel    279:  * @publicId: The public ID of the entity
                    280:  * @systemId: The system ID of the entity
                    281:  *
1.41      daniel    282:  * The entity loader, to control the loading of external entities,
                    283:  * the application can either:
                    284:  *    - override this resolveEntity() callback in the SAX block
                    285:  *    - or better use the xmlSetExternalEntityLoader() function to
                    286:  *      set up it's own entity resolution routine
1.5       daniel    287:  *
1.8       daniel    288:  * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
1.5       daniel    289:  */
                    290: xmlParserInputPtr
1.34      daniel    291: resolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
1.5       daniel    292: {
1.12      daniel    293:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.2       daniel    294: 
                    295: #ifdef DEBUG_SAX
                    296:     fprintf(stderr, "SAX.resolveEntity(%s, %s)\n", publicId, systemId);
                    297: #endif
1.5       daniel    298: 
1.41      daniel    299:     return(xmlLoadExternalEntity((const char *) systemId,
                    300:                                 (const char *) publicId, ctxt));
1.1       daniel    301: }
                    302: 
1.5       daniel    303: /**
1.10      daniel    304:  * getEntity:
1.16      daniel    305:  * @ctx: the user data (XML parser context)
1.10      daniel    306:  * @name: The entity name
                    307:  *
                    308:  * Get an entity by name
                    309:  *
1.13      daniel    310:  * Returns the xmlEntityPtr if found.
1.10      daniel    311:  */
                    312: xmlEntityPtr
1.34      daniel    313: getEntity(void *ctx, const xmlChar *name)
1.10      daniel    314: {
1.11      daniel    315:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10      daniel    316:     xmlEntityPtr ret;
                    317: 
                    318: #ifdef DEBUG_SAX
                    319:     fprintf(stderr, "SAX.getEntity(%s)\n", name);
                    320: #endif
                    321: 
                    322:     ret = xmlGetDocEntity(ctxt->myDoc, name);
                    323:     return(ret);
                    324: }
                    325: 
1.20      daniel    326: /**
                    327:  * getParameterEntity:
                    328:  * @ctx: the user data (XML parser context)
                    329:  * @name: The entity name
                    330:  *
                    331:  * Get a parameter entity by name
                    332:  *
                    333:  * Returns the xmlEntityPtr if found.
                    334:  */
                    335: xmlEntityPtr
1.34      daniel    336: getParameterEntity(void *ctx, const xmlChar *name)
1.20      daniel    337: {
                    338:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
                    339:     xmlEntityPtr ret;
                    340: 
                    341: #ifdef DEBUG_SAX
                    342:     fprintf(stderr, "SAX.getParameterEntity(%s)\n", name);
                    343: #endif
                    344: 
                    345:     ret = xmlGetParameterEntity(ctxt->myDoc, name);
                    346:     return(ret);
                    347: }
                    348: 
1.10      daniel    349: 
                    350: /**
                    351:  * entityDecl:
1.16      daniel    352:  * @ctx: the user data (XML parser context)
1.10      daniel    353:  * @name:  the entity name 
                    354:  * @type:  the entity type 
                    355:  * @publicId: The public ID of the entity
                    356:  * @systemId: The system ID of the entity
                    357:  * @content: the entity value (without processing).
                    358:  *
                    359:  * An entity definition has been parsed
                    360:  */
                    361: void
1.34      daniel    362: entityDecl(void *ctx, const xmlChar *name, int type,
                    363:           const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
1.10      daniel    364: {
1.11      daniel    365:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10      daniel    366: 
                    367: #ifdef DEBUG_SAX
                    368:     fprintf(stderr, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
                    369:             name, type, publicId, systemId, content);
                    370: #endif
1.50      daniel    371:     if (ctxt->inSubset == 1)
1.51      daniel    372:        xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
                    373:                              systemId, content);
1.50      daniel    374:     else if (ctxt->inSubset == 2)
1.51      daniel    375:        xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
                    376:                              systemId, content);
1.50      daniel    377:     else {
                    378:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    379:            ctxt->sax->error(ctxt, 
                    380:             "SAX.entityDecl(%s) called while not in subset\n", name);
                    381:     }
1.10      daniel    382: }
                    383: 
                    384: /**
                    385:  * attributeDecl:
1.16      daniel    386:  * @ctx: the user data (XML parser context)
1.58      daniel    387:  * @elem:  the name of the element
1.48      daniel    388:  * @fullname:  the attribute name 
1.10      daniel    389:  * @type:  the attribute type 
1.58      daniel    390:  * @def:  the type of default value
                    391:  * @defaultValue: the attribute default value
                    392:  * @tree:  the tree of enumerated value set
1.10      daniel    393:  *
                    394:  * An attribute definition has been parsed
                    395:  */
                    396: void
1.48      daniel    397: attributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
1.34      daniel    398:               int type, int def, const xmlChar *defaultValue,
1.10      daniel    399:              xmlEnumerationPtr tree)
                    400: {
1.11      daniel    401:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.21      daniel    402:     xmlAttributePtr attr;
1.48      daniel    403:     xmlChar *name = NULL, *prefix = NULL;
1.10      daniel    404: 
                    405: #ifdef DEBUG_SAX
                    406:     fprintf(stderr, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
1.48      daniel    407:             elem, fullname, type, def, defaultValue);
1.10      daniel    408: #endif
1.48      daniel    409:     name = xmlSplitQName(ctxt, fullname, &prefix);
1.50      daniel    410:     if (ctxt->inSubset == 1)
                    411:        attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
1.48      daniel    412:                                name, prefix, type, def, defaultValue, tree);
1.50      daniel    413:     else if (ctxt->inSubset == 2)
                    414:        attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
                    415:                                name, prefix, type, def, defaultValue, tree);
                    416:     else {
                    417:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    418:            ctxt->sax->error(ctxt, 
                    419:             "SAX.attributeDecl(%s) called while not in subset\n", name);
                    420:        return;
                    421:     }
1.21      daniel    422:     if (attr == 0) ctxt->valid = 0;
1.23      daniel    423:     if (ctxt->validate && ctxt->wellFormed &&
                    424:         ctxt->myDoc && ctxt->myDoc->intSubset)
1.21      daniel    425:        ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
                    426:                                                attr);
1.48      daniel    427:     if (prefix != NULL)
                    428:        xmlFree(prefix);
                    429:     if (name != NULL)
                    430:        xmlFree(name);
1.10      daniel    431: }
                    432: 
                    433: /**
                    434:  * elementDecl:
1.16      daniel    435:  * @ctx: the user data (XML parser context)
1.10      daniel    436:  * @name:  the element name 
                    437:  * @type:  the element type 
1.58      daniel    438:  * @content: the element value tree
1.10      daniel    439:  *
                    440:  * An element definition has been parsed
                    441:  */
                    442: void
1.34      daniel    443: elementDecl(void *ctx, const xmlChar *name, int type,
1.10      daniel    444:            xmlElementContentPtr content)
                    445: {
1.11      daniel    446:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.50      daniel    447:     xmlElementPtr elem = NULL;
1.10      daniel    448: 
                    449: #ifdef DEBUG_SAX
                    450:     fprintf(stderr, "SAX.elementDecl(%s, %d, ...)\n",
1.48      daniel    451:             fullname, type);
1.10      daniel    452: #endif
1.21      daniel    453:     
1.50      daniel    454:     if (ctxt->inSubset == 1)
                    455:        elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
1.21      daniel    456:                              name, type, content);
1.50      daniel    457:     else if (ctxt->inSubset == 2)
                    458:        elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
                    459:                              name, type, content);
                    460:     else {
                    461:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    462:            ctxt->sax->error(ctxt, 
                    463:             "SAX.elementDecl(%s) called while not in subset\n", name);
                    464:        return;
                    465:     }
                    466:     if (elem == NULL) ctxt->valid = 0;
1.23      daniel    467:     if (ctxt->validate && ctxt->wellFormed &&
                    468:         ctxt->myDoc && ctxt->myDoc->intSubset)
1.21      daniel    469:        ctxt->valid &= xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
1.10      daniel    470: }
                    471: 
                    472: /**
1.5       daniel    473:  * notationDecl:
1.16      daniel    474:  * @ctx: the user data (XML parser context)
1.5       daniel    475:  * @name: The name of the notation
                    476:  * @publicId: The public ID of the entity
                    477:  * @systemId: The system ID of the entity
                    478:  *
1.1       daniel    479:  * What to do when a notation declaration has been parsed.
                    480:  */
1.5       daniel    481: void
1.34      daniel    482: notationDecl(void *ctx, const xmlChar *name,
                    483:             const xmlChar *publicId, const xmlChar *systemId)
1.5       daniel    484: {
1.11      daniel    485:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.50      daniel    486:     xmlNotationPtr nota = NULL;
1.21      daniel    487: 
1.2       daniel    488: #ifdef DEBUG_SAX
                    489:     fprintf(stderr, "SAX.notationDecl(%s, %s, %s)\n", name, publicId, systemId);
                    490: #endif
1.21      daniel    491: 
1.50      daniel    492:     if (ctxt->inSubset == 1)
                    493:        nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
                    494:                               publicId, systemId);
                    495:     else if (ctxt->inSubset == 2)
                    496:        nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
1.21      daniel    497:                               publicId, systemId);
1.50      daniel    498:     else {
                    499:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    500:            ctxt->sax->error(ctxt, 
                    501:             "SAX.notationDecl(%s) called while not in subset\n", name);
                    502:        return;
                    503:     }
                    504:     if (nota == NULL) ctxt->valid = 0;
1.23      daniel    505:     if (ctxt->validate && ctxt->wellFormed &&
                    506:         ctxt->myDoc && ctxt->myDoc->intSubset)
1.21      daniel    507:        ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
                    508:                                               nota);
1.1       daniel    509: }
                    510: 
1.5       daniel    511: /**
                    512:  * unparsedEntityDecl:
1.16      daniel    513:  * @ctx: the user data (XML parser context)
1.5       daniel    514:  * @name: The name of the entity
                    515:  * @publicId: The public ID of the entity
                    516:  * @systemId: The system ID of the entity
                    517:  * @notationName: the name of the notation
                    518:  *
1.1       daniel    519:  * What to do when an unparsed entity declaration is parsed
                    520:  */
1.5       daniel    521: void
1.34      daniel    522: unparsedEntityDecl(void *ctx, const xmlChar *name,
                    523:                   const xmlChar *publicId, const xmlChar *systemId,
                    524:                   const xmlChar *notationName)
1.5       daniel    525: {
1.28      daniel    526:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.2       daniel    527: #ifdef DEBUG_SAX
                    528:     fprintf(stderr, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
                    529:             name, publicId, systemId, notationName);
                    530: #endif
1.28      daniel    531:     if (ctxt->validate && ctxt->wellFormed &&
                    532:         ctxt->myDoc && ctxt->myDoc->intSubset)
                    533:        ctxt->valid &= xmlValidateNotationUse(&ctxt->vctxt, ctxt->myDoc,
                    534:                                              notationName);
                    535:     xmlAddDocEntity(ctxt->myDoc, name,
                    536:                     XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
                    537:                    publicId, systemId, notationName);
1.1       daniel    538: }
                    539: 
1.5       daniel    540: /**
                    541:  * setDocumentLocator:
1.16      daniel    542:  * @ctx: the user data (XML parser context)
1.5       daniel    543:  * @loc: A SAX Locator
                    544:  *
1.1       daniel    545:  * Receive the document locator at startup, actually xmlDefaultSAXLocator
                    546:  * Everything is available on the context, so this is useless in our case.
                    547:  */
1.5       daniel    548: void
1.11      daniel    549: setDocumentLocator(void *ctx, xmlSAXLocatorPtr loc)
1.5       daniel    550: {
1.11      daniel    551:     /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
1.2       daniel    552: #ifdef DEBUG_SAX
                    553:     fprintf(stderr, "SAX.setDocumentLocator()\n");
                    554: #endif
1.1       daniel    555: }
                    556: 
1.5       daniel    557: /**
                    558:  * startDocument:
1.16      daniel    559:  * @ctx: the user data (XML parser context)
1.5       daniel    560:  *
1.1       daniel    561:  * called when the document start being processed.
                    562:  */
1.5       daniel    563: void
1.11      daniel    564: startDocument(void *ctx)
1.5       daniel    565: {
1.11      daniel    566:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10      daniel    567:     xmlDocPtr doc;
                    568: 
1.2       daniel    569: #ifdef DEBUG_SAX
                    570:     fprintf(stderr, "SAX.startDocument()\n");
                    571: #endif
1.10      daniel    572:     doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
                    573:     if (doc != NULL) {
                    574:        if (ctxt->encoding != NULL)
                    575:            doc->encoding = xmlStrdup(ctxt->encoding);
                    576:        else
                    577:            doc->encoding = NULL;
                    578:        doc->standalone = ctxt->standalone;
                    579:     }
1.1       daniel    580: }
                    581: 
1.5       daniel    582: /**
                    583:  * endDocument:
1.16      daniel    584:  * @ctx: the user data (XML parser context)
1.5       daniel    585:  *
1.1       daniel    586:  * called when the document end has been detected.
                    587:  */
1.5       daniel    588: void
1.11      daniel    589: endDocument(void *ctx)
1.5       daniel    590: {
1.31      daniel    591:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.2       daniel    592: #ifdef DEBUG_SAX
                    593:     fprintf(stderr, "SAX.endDocument()\n");
                    594: #endif
1.31      daniel    595:     if (ctxt->validate && ctxt->wellFormed &&
                    596:         ctxt->myDoc && ctxt->myDoc->intSubset)
                    597:        ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
1.59    ! daniel    598: 
        !           599:     /*
        !           600:      * Grab the encoding if it was added on-the-fly
        !           601:      */
        !           602:     if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
        !           603:        (ctxt->myDoc->encoding == NULL)) {
        !           604:        ctxt->myDoc->encoding = ctxt->encoding;
        !           605:        ctxt->encoding = NULL;
        !           606:     }
1.1       daniel    607: }
                    608: 
1.5       daniel    609: /**
1.10      daniel    610:  * attribute:
1.16      daniel    611:  * @ctx: the user data (XML parser context)
1.58      daniel    612:  * @fullname:  The attribute name, including namespace prefix
1.10      daniel    613:  * @value:  The attribute value
                    614:  *
                    615:  * Handle an attribute that has been read by the parser.
                    616:  * The default handling is to convert the attribute into an
                    617:  * DOM subtree and past it in a new xmlAttr element added to
                    618:  * the element.
                    619:  */
                    620: void
1.34      daniel    621: attribute(void *ctx, const xmlChar *fullname, const xmlChar *value)
1.10      daniel    622: {
1.11      daniel    623:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10      daniel    624:     xmlAttrPtr ret;
1.34      daniel    625:     xmlChar *name;
                    626:     xmlChar *ns;
1.56      daniel    627:     xmlChar *nval;
1.29      daniel    628:     xmlNsPtr namespace;
1.10      daniel    629: 
                    630: /****************
                    631: #ifdef DEBUG_SAX
                    632:     fprintf(stderr, "SAX.attribute(%s, %s)\n", fullname, value);
                    633: #endif
                    634:  ****************/
                    635:     /*
                    636:      * Split the full name into a namespace prefix and the tag name
                    637:      */
1.48      daniel    638:     name = xmlSplitQName(ctxt, fullname, &ns);
1.10      daniel    639: 
                    640:     /*
1.55      daniel    641:      * Do the last stave of the attribute normalization
                    642:      */
1.56      daniel    643:     nval = xmlValidNormalizeAttributeValue(ctxt->myDoc,
                    644:                               ctxt->node, fullname, value);
                    645:     if (nval != NULL)
                    646:        value = nval;
1.55      daniel    647: 
                    648:     /*
1.10      daniel    649:      * Check whether it's a namespace definition
                    650:      */
                    651:     if ((ns == NULL) &&
                    652:         (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
                    653:         (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
                    654:        /* a default namespace definition */
                    655:        xmlNewNs(ctxt->node, value, NULL);
                    656:        if (name != NULL) 
1.30      daniel    657:            xmlFree(name);
1.55      daniel    658:        if (nval != NULL)
                    659:            xmlFree(nval);
1.10      daniel    660:        return;
                    661:     }
                    662:     if ((ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
                    663:         (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
1.54      daniel    664:        /*
                    665:         * Validate also for namespace decls, they are attributes from
                    666:         * an XML-1.0 perspective
                    667:         TODO ... doesn't map well with current API
                    668:         if (ctxt->validate && ctxt->wellFormed &&
                    669:            ctxt->myDoc && ctxt->myDoc->intSubset)
                    670:            ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
                    671:                                               ctxt->node, ret, value);
                    672:         */
1.10      daniel    673:        /* a standard namespace definition */
                    674:        xmlNewNs(ctxt->node, value, name);
1.30      daniel    675:        xmlFree(ns);
1.10      daniel    676:        if (name != NULL) 
1.30      daniel    677:            xmlFree(name);
1.55      daniel    678:        if (nval != NULL)
                    679:            xmlFree(nval);
1.10      daniel    680:        return;
                    681:     }
                    682: 
1.38      daniel    683:     if (ns != NULL)
                    684:        namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
                    685:     else {
                    686:        namespace = NULL;
                    687:     }
                    688: 
1.29      daniel    689:     /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
                    690:     ret = xmlNewNsProp(ctxt->node, namespace, name, NULL);
1.22      daniel    691: 
1.26      daniel    692:     if (ret != NULL) {
1.46      daniel    693:         if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
                    694:            xmlNodePtr tmp;
                    695: 
1.44      daniel    696:            ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
1.46      daniel    697:            tmp = ret->children;
                    698:            while (tmp != NULL) {
                    699:                tmp->parent = (xmlNodePtr) ret;
                    700:                if (tmp->next == NULL)
                    701:                    ret->last = tmp;
                    702:                tmp = tmp->next;
                    703:            }
                    704:        } else {
1.44      daniel    705:            ret->children = xmlNewDocText(ctxt->myDoc, value);
1.46      daniel    706:            ret->last = ret->children;
                    707:            if (ret->children != NULL)
                    708:                ret->children->parent = (xmlNodePtr) ret;
                    709:        }
1.26      daniel    710:     }
1.22      daniel    711: 
1.56      daniel    712:     if (ctxt->validate && ctxt->wellFormed &&
                    713:         ctxt->myDoc && ctxt->myDoc->intSubset) {
                    714:        
                    715:        /*
                    716:         * If we don't substitute entities, the validation should be
                    717:         * done on a value with replaced entities anyway.
                    718:         */
                    719:         if (!ctxt->replaceEntities) {
                    720:            xmlChar *val;
                    721: 
                    722:            ctxt->depth++;
                    723:            val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
                    724:                                          0,0,0);
                    725:            ctxt->depth--;
                    726:            if (val == NULL)
                    727:                ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
                    728:                                ctxt->myDoc, ctxt->node, ret, value);
                    729:            else {
                    730:                ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
                    731:                                ctxt->myDoc, ctxt->node, ret, val);
                    732:                 xmlFree(val);
                    733:            }
                    734:        } else {
                    735:            ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
1.22      daniel    736:                                               ctxt->node, ret, value);
1.56      daniel    737:        }
                    738:     } else {
1.26      daniel    739:         /*
                    740:         * when validating, the ID registration is done at the attribute
                    741:         * validation level. Otherwise we have to do specific handling here.
                    742:         */
                    743:        if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
                    744:            xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
1.31      daniel    745:        else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
                    746:            xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
1.26      daniel    747:     }
1.22      daniel    748: 
1.55      daniel    749:     if (nval != NULL)
                    750:        xmlFree(nval);
1.10      daniel    751:     if (name != NULL) 
1.30      daniel    752:        xmlFree(name);
1.10      daniel    753:     if (ns != NULL) 
1.30      daniel    754:        xmlFree(ns);
1.10      daniel    755: }
                    756: 
                    757: /**
1.5       daniel    758:  * startElement:
1.16      daniel    759:  * @ctx: the user data (XML parser context)
1.58      daniel    760:  * @fullname:  The element name, including namespace prefix
1.10      daniel    761:  * @atts:  An array of name/value attributes pairs, NULL terminated
1.5       daniel    762:  *
1.1       daniel    763:  * called when an opening tag has been processed.
                    764:  */
1.5       daniel    765: void
1.34      daniel    766: startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
1.5       daniel    767: {
1.11      daniel    768:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10      daniel    769:     xmlNodePtr ret;
                    770:     xmlNodePtr parent = ctxt->node;
                    771:     xmlNsPtr ns;
1.34      daniel    772:     xmlChar *name;
                    773:     xmlChar *prefix;
                    774:     const xmlChar *att;
                    775:     const xmlChar *value;
1.10      daniel    776:     int i;
                    777: 
1.2       daniel    778: #ifdef DEBUG_SAX
1.10      daniel    779:     fprintf(stderr, "SAX.startElement(%s)\n", fullname);
1.2       daniel    780: #endif
1.33      daniel    781: 
                    782:     /*
                    783:      * First check on validity:
                    784:      */
                    785:     if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) && 
                    786:         ((ctxt->myDoc->intSubset == NULL) ||
                    787:         ((ctxt->myDoc->intSubset->notations == NULL) && 
                    788:          (ctxt->myDoc->intSubset->elements == NULL) &&
                    789:          (ctxt->myDoc->intSubset->attributes == NULL) && 
                    790:          (ctxt->myDoc->intSubset->entities == NULL)))) {
                    791:        if (ctxt->vctxt.error != NULL) {
                    792:             ctxt->vctxt.error(ctxt->vctxt.userData,
                    793:              "Validation failed: no DTD found !\n");
                    794:        }
                    795:        ctxt->validate = 0;
                    796:     }
                    797:        
                    798: 
1.10      daniel    799:     /*
                    800:      * Split the full name into a namespace prefix and the tag name
                    801:      */
1.48      daniel    802:     name = xmlSplitQName(ctxt, fullname, &prefix);
1.10      daniel    803: 
                    804: 
                    805:     /*
                    806:      * Note : the namespace resolution is deferred until the end of the
                    807:      *        attributes parsing, since local namespace can be defined as
                    808:      *        an attribute at this level.
                    809:      */
                    810:     ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL);
                    811:     if (ret == NULL) return;
1.44      daniel    812:     if (ctxt->myDoc->children == NULL) {
1.26      daniel    813: #ifdef DEBUG_SAX_TREE
                    814:        fprintf(stderr, "Setting %s as root\n", name);
                    815: #endif
1.45      daniel    816:         xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1.26      daniel    817:     } else if (parent == NULL) {
1.44      daniel    818:         parent = ctxt->myDoc->children;
1.26      daniel    819:     }
1.10      daniel    820: 
                    821:     /*
                    822:      * We are parsing a new node.
                    823:      */
1.26      daniel    824: #ifdef DEBUG_SAX_TREE
                    825:     fprintf(stderr, "pushing(%s)\n", name);
                    826: #endif
1.10      daniel    827:     nodePush(ctxt, ret);
                    828: 
                    829:     /*
                    830:      * Link the child element
                    831:      */
1.26      daniel    832:     if (parent != NULL) {
                    833:         if (parent->type == XML_ELEMENT_NODE) {
                    834: #ifdef DEBUG_SAX_TREE
                    835:            fprintf(stderr, "adding child %s to %s\n", name, parent->name);
                    836: #endif
                    837:            xmlAddChild(parent, ret);
                    838:        } else {
                    839: #ifdef DEBUG_SAX_TREE
                    840:            fprintf(stderr, "adding sibling %s to ", name);
                    841:            xmlDebugDumpOneNode(stderr, parent, 0);
                    842: #endif
                    843:            xmlAddSibling(parent, ret);
                    844:        }
                    845:     }
1.10      daniel    846: 
1.54      daniel    847:     /*
                    848:      * If it's the Document root, finish the Dtd validation and
                    849:      * check the document root element for validity
                    850:      */
                    851:     if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
                    852:        ctxt->valid &= xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
                    853:        ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
                    854:        ctxt->vctxt.finishDtd = 1;
                    855:     }
1.10      daniel    856:     /*
1.29      daniel    857:      * process all the attributes whose name start with "xml"
1.10      daniel    858:      */
                    859:     if (atts != NULL) {
                    860:         i = 0;
                    861:        att = atts[i++];
                    862:        value = atts[i++];
                    863:         while ((att != NULL) && (value != NULL)) {
1.29      daniel    864:            if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l'))
                    865:                attribute(ctxt, att, value);
                    866: 
                    867:            att = atts[i++];
                    868:            value = atts[i++];
                    869:        }
                    870:     }
                    871: 
                    872:     /*
                    873:      * process all the other attributes
                    874:      */
                    875:     if (atts != NULL) {
                    876:         i = 0;
                    877:        att = atts[i++];
                    878:        value = atts[i++];
                    879:         while ((att != NULL) && (value != NULL)) {
                    880:            if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l'))
                    881:                attribute(ctxt, att, value);
1.10      daniel    882: 
                    883:            /*
                    884:             * Next ones
                    885:             */
                    886:            att = atts[i++];
                    887:            value = atts[i++];
                    888:        }
                    889:     }
                    890: 
                    891:     /*
                    892:      * Search the namespace, note that since the attributes have been
                    893:      * processed, the local namespaces are available.
                    894:      */
                    895:     ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
                    896:     if ((ns == NULL) && (parent != NULL))
                    897:        ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
                    898:     xmlSetNs(ret, ns);
                    899: 
                    900:     if (prefix != NULL)
1.30      daniel    901:        xmlFree(prefix);
1.10      daniel    902:     if (name != NULL)
1.30      daniel    903:        xmlFree(name);
1.10      daniel    904: 
1.1       daniel    905: }
                    906: 
1.5       daniel    907: /**
                    908:  * endElement:
1.16      daniel    909:  * @ctx: the user data (XML parser context)
1.5       daniel    910:  * @name:  The element name
                    911:  *
1.1       daniel    912:  * called when the end of an element has been detected.
                    913:  */
1.5       daniel    914: void
1.34      daniel    915: endElement(void *ctx, const xmlChar *name)
1.5       daniel    916: {
1.11      daniel    917:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10      daniel    918:     xmlParserNodeInfo node_info;
                    919:     xmlNodePtr cur = ctxt->node;
                    920: 
1.2       daniel    921: #ifdef DEBUG_SAX
1.10      daniel    922:     if (name == NULL)
                    923:         fprintf(stderr, "SAX.endElement(NULL)\n");
                    924:     else
                    925:        fprintf(stderr, "SAX.endElement(%s)\n", name);
                    926: #endif
                    927:     
                    928:     /* Capture end position and add node */
                    929:     if (cur != NULL && ctxt->record_info) {
                    930:       node_info.end_pos = ctxt->input->cur - ctxt->input->base;
                    931:       node_info.end_line = ctxt->input->line;
                    932:       node_info.node = cur;
                    933:       xmlParserAddNodeInfo(ctxt, &node_info);
                    934:     }
                    935: 
1.23      daniel    936:     if (ctxt->validate && ctxt->wellFormed &&
                    937:         ctxt->myDoc && ctxt->myDoc->intSubset)
1.22      daniel    938:         ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
                    939:                                             cur);
                    940: 
                    941:     
1.10      daniel    942:     /*
                    943:      * end of parsing of this node.
                    944:      */
1.26      daniel    945: #ifdef DEBUG_SAX_TREE
                    946:     fprintf(stderr, "popping(%s)\n", cur->name);
                    947: #endif
1.10      daniel    948:     nodePop(ctxt);
1.1       daniel    949: }
                    950: 
1.5       daniel    951: /**
1.10      daniel    952:  * reference:
1.16      daniel    953:  * @ctx: the user data (XML parser context)
1.10      daniel    954:  * @name:  The entity name
1.5       daniel    955:  *
1.10      daniel    956:  * called when an entity reference is detected. 
1.5       daniel    957:  */
                    958: void
1.34      daniel    959: reference(void *ctx, const xmlChar *name)
1.5       daniel    960: {
1.11      daniel    961:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10      daniel    962:     xmlNodePtr ret;
                    963: 
1.5       daniel    964: #ifdef DEBUG_SAX
1.10      daniel    965:     fprintf(stderr, "SAX.reference(%s)\n", name);
1.5       daniel    966: #endif
1.42      daniel    967:     if (name[0] == '#')
                    968:        ret = xmlNewCharRef(ctxt->myDoc, name);
                    969:     else
                    970:        ret = xmlNewReference(ctxt->myDoc, name);
1.26      daniel    971: #ifdef DEBUG_SAX_TREE
                    972:     fprintf(stderr, "add reference %s to %s \n", name, ctxt->node->name);
                    973: #endif
1.10      daniel    974:     xmlAddChild(ctxt->node, ret);
1.5       daniel    975: }
                    976: 
                    977: /**
                    978:  * characters:
1.16      daniel    979:  * @ctx: the user data (XML parser context)
1.34      daniel    980:  * @ch:  a xmlChar string
                    981:  * @len: the number of xmlChar
1.5       daniel    982:  *
1.1       daniel    983:  * receiving some chars from the parser.
                    984:  * Question: how much at a time ???
                    985:  */
1.5       daniel    986: void
1.34      daniel    987: characters(void *ctx, const xmlChar *ch, int len)
1.5       daniel    988: {
1.11      daniel    989:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.2       daniel    990:     xmlNodePtr lastChild;
                    991: 
                    992: #ifdef DEBUG_SAX
1.10      daniel    993:     fprintf(stderr, "SAX.characters(%.30s, %d)\n", ch, len);
1.2       daniel    994: #endif
                    995:     /*
                    996:      * Handle the data if any. If there is no child
                    997:      * add it as content, otherwise if the last child is text,
                    998:      * concatenate it, else create a new node of type text.
                    999:      */
                   1000: 
1.36      daniel   1001:     if (ctxt->node == NULL) {
                   1002: #ifdef DEBUG_SAX_TREE
                   1003:        fprintf(stderr, "add chars: ctxt->node == NULL !\n");
                   1004: #endif
                   1005:         return;
                   1006:     }
1.2       daniel   1007:     lastChild = xmlGetLastChild(ctxt->node);
1.26      daniel   1008: #ifdef DEBUG_SAX_TREE
                   1009:     fprintf(stderr, "add chars to %s \n", ctxt->node->name);
                   1010: #endif
1.2       daniel   1011:     if (lastChild == NULL)
1.10      daniel   1012:        xmlNodeAddContentLen(ctxt->node, ch, len);
1.2       daniel   1013:     else {
                   1014:        if (xmlNodeIsText(lastChild))
1.10      daniel   1015:            xmlTextConcat(lastChild, ch, len);
1.2       daniel   1016:        else {
1.10      daniel   1017:            lastChild = xmlNewTextLen(ch, len);
1.2       daniel   1018:            xmlAddChild(ctxt->node, lastChild);
                   1019:        }
                   1020:     }
1.1       daniel   1021: }
                   1022: 
1.5       daniel   1023: /**
                   1024:  * ignorableWhitespace:
1.16      daniel   1025:  * @ctx: the user data (XML parser context)
1.34      daniel   1026:  * @ch:  a xmlChar string
                   1027:  * @len: the number of xmlChar
1.5       daniel   1028:  *
1.1       daniel   1029:  * receiving some ignorable whitespaces from the parser.
                   1030:  * Question: how much at a time ???
                   1031:  */
1.5       daniel   1032: void
1.34      daniel   1033: ignorableWhitespace(void *ctx, const xmlChar *ch, int len)
1.5       daniel   1034: {
1.11      daniel   1035:     /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
1.2       daniel   1036: #ifdef DEBUG_SAX
1.10      daniel   1037:     fprintf(stderr, "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len);
1.2       daniel   1038: #endif
1.1       daniel   1039: }
                   1040: 
1.5       daniel   1041: /**
                   1042:  * processingInstruction:
1.16      daniel   1043:  * @ctx: the user data (XML parser context)
1.5       daniel   1044:  * @target:  the target name
                   1045:  * @data: the PI data's
                   1046:  *
                   1047:  * A processing instruction has been parsed.
                   1048:  */
                   1049: void
1.34      daniel   1050: processingInstruction(void *ctx, const xmlChar *target,
                   1051:                       const xmlChar *data)
1.5       daniel   1052: {
1.26      daniel   1053:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
                   1054:     xmlNodePtr ret;
                   1055:     xmlNodePtr parent = ctxt->node;
                   1056: 
1.2       daniel   1057: #ifdef DEBUG_SAX
                   1058:     fprintf(stderr, "SAX.processingInstruction(%s, %s)\n", target, data);
                   1059: #endif
1.26      daniel   1060: 
                   1061:     ret = xmlNewPI(target, data);
                   1062:     if (ret == NULL) return;
1.53      daniel   1063:     parent = ctxt->node;
                   1064: 
                   1065:     if (ctxt->inSubset == 1) {
                   1066:        xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
                   1067:        return;
                   1068:     } else if (ctxt->inSubset == 2) {
                   1069:        xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
                   1070:        return;
                   1071:     }
                   1072:     if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
1.26      daniel   1073: #ifdef DEBUG_SAX_TREE
                   1074:            fprintf(stderr, "Setting PI %s as root\n", target);
                   1075: #endif
1.45      daniel   1076:         xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1.53      daniel   1077:        return;
1.26      daniel   1078:     }
1.53      daniel   1079:     if (parent->type == XML_ELEMENT_NODE) {
1.26      daniel   1080: #ifdef DEBUG_SAX_TREE
1.53      daniel   1081:        fprintf(stderr, "adding PI %s child to %s\n", target, parent->name);
1.26      daniel   1082: #endif
1.53      daniel   1083:        xmlAddChild(parent, ret);
                   1084:     } else {
1.26      daniel   1085: #ifdef DEBUG_SAX_TREE
1.53      daniel   1086:        fprintf(stderr, "adding PI %s sibling to ", target);
                   1087:        xmlDebugDumpOneNode(stderr, parent, 0);
1.26      daniel   1088: #endif
1.53      daniel   1089:        xmlAddSibling(parent, ret);
1.26      daniel   1090:     }
1.1       daniel   1091: }
                   1092: 
1.10      daniel   1093: /**
                   1094:  * globalNamespace:
1.16      daniel   1095:  * @ctx: the user data (XML parser context)
1.10      daniel   1096:  * @href:  the namespace associated URN
                   1097:  * @prefix: the namespace prefix
                   1098:  *
                   1099:  * An old global namespace has been parsed.
                   1100:  */
                   1101: void
1.34      daniel   1102: globalNamespace(void *ctx, const xmlChar *href, const xmlChar *prefix)
1.10      daniel   1103: {
1.11      daniel   1104:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10      daniel   1105: #ifdef DEBUG_SAX
                   1106:     fprintf(stderr, "SAX.globalNamespace(%s, %s)\n", href, prefix);
                   1107: #endif
                   1108:     xmlNewGlobalNs(ctxt->myDoc, href, prefix);
                   1109: }
                   1110: 
                   1111: /**
                   1112:  * setNamespace:
1.16      daniel   1113:  * @ctx: the user data (XML parser context)
1.10      daniel   1114:  * @name:  the namespace prefix
                   1115:  *
                   1116:  * Set the current element namespace.
                   1117:  */
1.58      daniel   1118: 
1.10      daniel   1119: void
1.34      daniel   1120: setNamespace(void *ctx, const xmlChar *name)
1.10      daniel   1121: {
1.11      daniel   1122:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10      daniel   1123:     xmlNsPtr ns;
                   1124:     xmlNodePtr parent;
                   1125: 
                   1126: #ifdef DEBUG_SAX
                   1127:     fprintf(stderr, "SAX.setNamespace(%s)\n", name);
                   1128: #endif
                   1129:     ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name);
                   1130:     if (ns == NULL) { /* ctxt->node may not have a parent yet ! */
                   1131:         if (ctxt->nodeNr >= 2) {
                   1132:            parent = ctxt->nodeTab[ctxt->nodeNr - 2];
                   1133:            if (parent != NULL)
                   1134:                ns = xmlSearchNs(ctxt->myDoc, parent, name);
                   1135:        }
                   1136:     }
                   1137:     xmlSetNs(ctxt->node, ns);
                   1138: }
                   1139: 
                   1140: /**
                   1141:  * getNamespace:
1.16      daniel   1142:  * @ctx: the user data (XML parser context)
1.10      daniel   1143:  *
                   1144:  * Get the current element namespace.
1.58      daniel   1145:  *
                   1146:  * Returns the xmlNsPtr or NULL if none
1.10      daniel   1147:  */
1.58      daniel   1148: 
1.10      daniel   1149: xmlNsPtr
1.11      daniel   1150: getNamespace(void *ctx)
1.10      daniel   1151: {
1.11      daniel   1152:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10      daniel   1153:     xmlNsPtr ret;
                   1154: 
                   1155: #ifdef DEBUG_SAX
                   1156:     fprintf(stderr, "SAX.getNamespace()\n");
                   1157: #endif
                   1158:     ret = ctxt->node->ns;
                   1159:     return(ret);
                   1160: }
                   1161: 
                   1162: /**
                   1163:  * checkNamespace:
1.16      daniel   1164:  * @ctx: the user data (XML parser context)
1.10      daniel   1165:  * @namespace: the namespace to check against
                   1166:  *
                   1167:  * Check that the current element namespace is the same as the
                   1168:  * one read upon parsing.
1.58      daniel   1169:  *
                   1170:  * Returns 1 if true 0 otherwise
1.10      daniel   1171:  */
1.58      daniel   1172: 
1.10      daniel   1173: int
1.34      daniel   1174: checkNamespace(void *ctx, xmlChar *namespace)
1.10      daniel   1175: {
1.11      daniel   1176:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10      daniel   1177:     xmlNodePtr cur = ctxt->node;
                   1178: 
                   1179: #ifdef DEBUG_SAX
                   1180:     fprintf(stderr, "SAX.checkNamespace(%s)\n", namespace);
                   1181: #endif
                   1182: 
                   1183:     /*
                   1184:      * Check that the Name in the ETag is the same as in the STag.
                   1185:      */
                   1186:     if (namespace == NULL) {
                   1187:         if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
                   1188:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1189:                ctxt->sax->error(ctxt, 
                   1190:                 "End tags for %s don't hold the namespace %s\n",
                   1191:                                 cur->name, cur->ns->prefix);
                   1192:            ctxt->wellFormed = 0;
                   1193:        }
                   1194:     } else {
                   1195:         if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) {
                   1196:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1197:                ctxt->sax->error(ctxt, 
                   1198:                 "End tags %s holds a prefix %s not used by the open tag\n",
                   1199:                                 cur->name, namespace);
                   1200:            ctxt->wellFormed = 0;
1.28      daniel   1201:        } else if (xmlStrcmp(namespace, cur->ns->prefix)) {
1.10      daniel   1202:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1203:                ctxt->sax->error(ctxt, 
                   1204:     "Start and End tags for %s don't use the same namespaces: %s and %s\n",
                   1205:                                 cur->name, cur->ns->prefix, namespace);
                   1206:            ctxt->wellFormed = 0;
                   1207:        } else
                   1208:            return(1);
                   1209:     }
                   1210:     return(0);
                   1211: }
                   1212: 
                   1213: /**
                   1214:  * namespaceDecl:
1.16      daniel   1215:  * @ctx: the user data (XML parser context)
1.10      daniel   1216:  * @href:  the namespace associated URN
                   1217:  * @prefix: the namespace prefix
                   1218:  *
                   1219:  * A namespace has been parsed.
                   1220:  */
                   1221: void
1.34      daniel   1222: namespaceDecl(void *ctx, const xmlChar *href, const xmlChar *prefix)
1.10      daniel   1223: {
1.11      daniel   1224:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.10      daniel   1225: #ifdef DEBUG_SAX
                   1226:     if (prefix == NULL)
                   1227:        fprintf(stderr, "SAX.namespaceDecl(%s, NULL)\n", href);
                   1228:     else
                   1229:        fprintf(stderr, "SAX.namespaceDecl(%s, %s)\n", href, prefix);
                   1230: #endif
                   1231:     xmlNewNs(ctxt->node, href, prefix);
                   1232: }
                   1233: 
                   1234: /**
                   1235:  * comment:
1.16      daniel   1236:  * @ctx: the user data (XML parser context)
1.10      daniel   1237:  * @value:  the comment content
                   1238:  *
                   1239:  * A comment has been parsed.
                   1240:  */
                   1241: void
1.34      daniel   1242: comment(void *ctx, const xmlChar *value)
1.10      daniel   1243: {
1.11      daniel   1244:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.17      daniel   1245:     xmlNodePtr ret;
1.27      daniel   1246:     xmlNodePtr parent = ctxt->node;
1.17      daniel   1247: 
1.10      daniel   1248: #ifdef DEBUG_SAX
                   1249:     fprintf(stderr, "SAX.comment(%s)\n", value);
                   1250: #endif
1.17      daniel   1251:     ret = xmlNewDocComment(ctxt->myDoc, value);
1.27      daniel   1252:     if (ret == NULL) return;
                   1253: 
1.53      daniel   1254:     if (ctxt->inSubset == 1) {
                   1255:        xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
                   1256:        return;
                   1257:     } else if (ctxt->inSubset == 2) {
                   1258:        xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
                   1259:        return;
                   1260:     }
                   1261:     if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
1.27      daniel   1262: #ifdef DEBUG_SAX_TREE
                   1263:            fprintf(stderr, "Setting comment as root\n");
                   1264: #endif
1.45      daniel   1265:         xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1.53      daniel   1266:        return;
1.27      daniel   1267:     }
1.53      daniel   1268:     if (parent->type == XML_ELEMENT_NODE) {
1.27      daniel   1269: #ifdef DEBUG_SAX_TREE
1.53      daniel   1270:        fprintf(stderr, "adding comment child to %s\n", parent->name);
1.27      daniel   1271: #endif
1.53      daniel   1272:        xmlAddChild(parent, ret);
                   1273:     } else {
1.27      daniel   1274: #ifdef DEBUG_SAX_TREE
1.53      daniel   1275:        fprintf(stderr, "adding comment sibling to ");
                   1276:        xmlDebugDumpOneNode(stderr, parent, 0);
1.27      daniel   1277: #endif
1.53      daniel   1278:        xmlAddSibling(parent, ret);
1.27      daniel   1279:     }
1.25      daniel   1280: }
                   1281: 
                   1282: /**
                   1283:  * cdataBlock:
                   1284:  * @ctx: the user data (XML parser context)
                   1285:  * @value:  The pcdata content
                   1286:  * @len:  the block length
                   1287:  *
                   1288:  * called when a pcdata block has been parsed
                   1289:  */
                   1290: void
1.34      daniel   1291: cdataBlock(void *ctx, const xmlChar *value, int len)
1.25      daniel   1292: {
                   1293:     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1.40      daniel   1294:     xmlNodePtr ret, lastChild;
1.25      daniel   1295: 
                   1296: #ifdef DEBUG_SAX
1.26      daniel   1297:     fprintf(stderr, "SAX.pcdata(%.10s, %d)\n", value, len);
1.25      daniel   1298: #endif
1.40      daniel   1299:     lastChild = xmlGetLastChild(ctxt->node);
                   1300: #ifdef DEBUG_SAX_TREE
                   1301:     fprintf(stderr, "add chars to %s \n", ctxt->node->name);
                   1302: #endif
                   1303:     if ((lastChild != NULL) &&
                   1304:         (lastChild->type == XML_CDATA_SECTION_NODE)) {
                   1305:        xmlTextConcat(lastChild, value, len);
                   1306:     } else {
                   1307:        ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
                   1308:        xmlAddChild(ctxt->node, ret);
                   1309:     }
1.10      daniel   1310: }
                   1311: 
1.18      daniel   1312: /*
                   1313:  * Default handler for XML, builds the DOM tree
                   1314:  */
1.1       daniel   1315: xmlSAXHandler xmlDefaultSAXHandler = {
1.10      daniel   1316:     internalSubset,
                   1317:     isStandalone,
                   1318:     hasInternalSubset,
                   1319:     hasExternalSubset,
1.1       daniel   1320:     resolveEntity,
1.10      daniel   1321:     getEntity,
                   1322:     entityDecl,
1.1       daniel   1323:     notationDecl,
1.10      daniel   1324:     attributeDecl,
                   1325:     elementDecl,
1.1       daniel   1326:     unparsedEntityDecl,
                   1327:     setDocumentLocator,
                   1328:     startDocument,
                   1329:     endDocument,
                   1330:     startElement,
                   1331:     endElement,
1.10      daniel   1332:     reference,
1.1       daniel   1333:     characters,
                   1334:     ignorableWhitespace,
                   1335:     processingInstruction,
1.10      daniel   1336:     comment,
1.1       daniel   1337:     xmlParserWarning,
                   1338:     xmlParserError,
1.2       daniel   1339:     xmlParserError,
1.20      daniel   1340:     getParameterEntity,
1.25      daniel   1341:     cdataBlock,
1.49      daniel   1342:     externalSubset,
1.1       daniel   1343: };
1.2       daniel   1344: 
1.5       daniel   1345: /**
                   1346:  * xmlDefaultSAXHandlerInit:
                   1347:  *
                   1348:  * Initialize the default SAX handler
                   1349:  */
                   1350: void
                   1351: xmlDefaultSAXHandlerInit(void)
                   1352: {
1.10      daniel   1353:     xmlDefaultSAXHandler.internalSubset = internalSubset;
1.49      daniel   1354:     xmlDefaultSAXHandler.externalSubset = externalSubset;
1.10      daniel   1355:     xmlDefaultSAXHandler.isStandalone = isStandalone;
                   1356:     xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
                   1357:     xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
1.2       daniel   1358:     xmlDefaultSAXHandler.resolveEntity = resolveEntity;
1.10      daniel   1359:     xmlDefaultSAXHandler.getEntity = getEntity;
1.20      daniel   1360:     xmlDefaultSAXHandler.getParameterEntity = getParameterEntity;
1.10      daniel   1361:     xmlDefaultSAXHandler.entityDecl = entityDecl;
                   1362:     xmlDefaultSAXHandler.attributeDecl = attributeDecl;
                   1363:     xmlDefaultSAXHandler.elementDecl = elementDecl;
1.2       daniel   1364:     xmlDefaultSAXHandler.notationDecl = notationDecl;
                   1365:     xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
                   1366:     xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
                   1367:     xmlDefaultSAXHandler.startDocument = startDocument;
                   1368:     xmlDefaultSAXHandler.endDocument = endDocument;
                   1369:     xmlDefaultSAXHandler.startElement = startElement;
                   1370:     xmlDefaultSAXHandler.endElement = endElement;
1.10      daniel   1371:     xmlDefaultSAXHandler.reference = reference;
1.2       daniel   1372:     xmlDefaultSAXHandler.characters = characters;
1.25      daniel   1373:     xmlDefaultSAXHandler.cdataBlock = cdataBlock;
1.2       daniel   1374:     xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
                   1375:     xmlDefaultSAXHandler.processingInstruction = processingInstruction;
1.10      daniel   1376:     xmlDefaultSAXHandler.comment = comment;
1.47      daniel   1377:     if (xmlGetWarningsDefaultValue == 0)
                   1378:        xmlDefaultSAXHandler.warning = NULL;
                   1379:     else
                   1380:        xmlDefaultSAXHandler.warning = xmlParserWarning;
1.2       daniel   1381:     xmlDefaultSAXHandler.error = xmlParserError;
                   1382:     xmlDefaultSAXHandler.fatalError = xmlParserError;
1.18      daniel   1383: }
                   1384: 
                   1385: /*
                   1386:  * Default handler for HTML, builds the DOM tree
                   1387:  */
                   1388: xmlSAXHandler htmlDefaultSAXHandler = {
                   1389:     NULL,
                   1390:     NULL,
                   1391:     NULL,
                   1392:     NULL,
                   1393:     NULL,
                   1394:     getEntity,
                   1395:     NULL,
                   1396:     NULL,
                   1397:     NULL,
                   1398:     NULL,
                   1399:     NULL,
                   1400:     setDocumentLocator,
                   1401:     startDocument,
                   1402:     endDocument,
                   1403:     startElement,
                   1404:     endElement,
                   1405:     NULL,
                   1406:     characters,
                   1407:     ignorableWhitespace,
                   1408:     NULL,
                   1409:     comment,
                   1410:     xmlParserWarning,
                   1411:     xmlParserError,
                   1412:     xmlParserError,
1.20      daniel   1413:     getParameterEntity,
1.25      daniel   1414:     NULL,
1.49      daniel   1415:     NULL,
1.18      daniel   1416: };
                   1417: 
                   1418: /**
                   1419:  * htmlDefaultSAXHandlerInit:
                   1420:  *
                   1421:  * Initialize the default SAX handler
                   1422:  */
                   1423: void
                   1424: htmlDefaultSAXHandlerInit(void)
                   1425: {
                   1426:     htmlDefaultSAXHandler.internalSubset = NULL;
1.49      daniel   1427:     htmlDefaultSAXHandler.externalSubset = NULL;
1.18      daniel   1428:     htmlDefaultSAXHandler.isStandalone = NULL;
                   1429:     htmlDefaultSAXHandler.hasInternalSubset = NULL;
                   1430:     htmlDefaultSAXHandler.hasExternalSubset = NULL;
                   1431:     htmlDefaultSAXHandler.resolveEntity = NULL;
                   1432:     htmlDefaultSAXHandler.getEntity = getEntity;
1.20      daniel   1433:     htmlDefaultSAXHandler.getParameterEntity = NULL;
1.18      daniel   1434:     htmlDefaultSAXHandler.entityDecl = NULL;
                   1435:     htmlDefaultSAXHandler.attributeDecl = NULL;
                   1436:     htmlDefaultSAXHandler.elementDecl = NULL;
                   1437:     htmlDefaultSAXHandler.notationDecl = NULL;
                   1438:     htmlDefaultSAXHandler.unparsedEntityDecl = NULL;
                   1439:     htmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
                   1440:     htmlDefaultSAXHandler.startDocument = startDocument;
                   1441:     htmlDefaultSAXHandler.endDocument = endDocument;
                   1442:     htmlDefaultSAXHandler.startElement = startElement;
                   1443:     htmlDefaultSAXHandler.endElement = endElement;
                   1444:     htmlDefaultSAXHandler.reference = NULL;
                   1445:     htmlDefaultSAXHandler.characters = characters;
1.25      daniel   1446:     htmlDefaultSAXHandler.cdataBlock = NULL;
1.18      daniel   1447:     htmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
                   1448:     htmlDefaultSAXHandler.processingInstruction = NULL;
                   1449:     htmlDefaultSAXHandler.comment = comment;
                   1450:     htmlDefaultSAXHandler.warning = xmlParserWarning;
                   1451:     htmlDefaultSAXHandler.error = xmlParserError;
                   1452:     htmlDefaultSAXHandler.fatalError = xmlParserError;
1.2       daniel   1453: }

Webmaster