Annotation of XML/SAX.c, revision 1.21

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

Webmaster