Annotation of libwww/Library/src/HTXML.c, revision 2.6

2.1       frystyk     1: /*
                      2: **     LIBWWW STREAM WRAPPER FOR EXPAT XML PARSER
                      3: **
                      4: **     (c) COPYRIGHT MIT 1995.
                      5: **     Please first read the full copyright statement in the file COPYRIGH.
2.6     ! frystyk     6: **     @(#) $Id: HTXML.c,v 2.5 1999/04/12 15:01:52 frystyk Exp $
2.1       frystyk     7: **
                      8: **     This module requires expat in order to compile/link
                      9: */
                     10: 
                     11: /* Library include files */
                     12: #include "wwwsys.h"
                     13: #include "WWWUtil.h"
                     14: #include "WWWCore.h"
2.5       frystyk    15: #include "SGML.h"
2.2       frystyk    16: #include "HTXML.h"                                      /* Implemented here */
2.1       frystyk    17: 
2.2       frystyk    18: #define XML_MAX_ATTRIBUTES 50
2.1       frystyk    19: 
                     20: struct _HTStream {
                     21:     const HTStreamClass *      isa;
                     22:     int                                state;
                     23:     HTRequest *                        request;
2.2       frystyk    24:     HTStream *                  target;
                     25:     HTStructuredClass *         actions;       
                     26:     HTStructured *              starget;       
2.1       frystyk    27:     XML_Parser                         xmlstream;
2.2       frystyk    28:     SGML_dtd *                  dtd;
                     29:     XML_StartElementHandler     xml_start_element;
                     30:     XML_EndElementHandler       xml_end_element;
                     31:     XML_CharacterDataHandler    xml_character_data;
                     32:     XML_DefaultHandler          xml_default_handler;
                     33:     void *                      xml_user_data;
2.1       frystyk    34: };
                     35: 
2.6     ! frystyk    36: /* @@@ SHould not be global but controlled by name spaces @@@ */
        !            37: PRIVATE HTXMLCallback_new *    XMLInstance = NULL;
        !            38: PRIVATE void *                 XMLInstanceContext = NULL;
2.2       frystyk    39: 
2.1       frystyk    40: /* ------------------------------------------------------------------------- */
                     41: 
                     42: PRIVATE int HTXML_flush (HTStream * me)
                     43: {
2.2       frystyk    44:     if(me->target)
                     45:        return (*me->target->isa->flush)(me->target);
                     46:     else if (me->starget)
                     47:        return (*me->actions->flush)(me->starget);
                     48:     return HT_OK;
2.1       frystyk    49: }
                     50: 
                     51: PRIVATE int HTXML_free (HTStream * me)
                     52: {
                     53:     int status = HT_OK;
                     54:     XML_ParserFree(me->xmlstream);
2.2       frystyk    55:     if (me->target) {
                     56:        if ((status = (*me->target->isa->_free)(me->target)) == HT_WOULD_BLOCK)
                     57:            return HT_WOULD_BLOCK;
                     58:     } else if(me->starget) {
                     59:       if ((status = (*me->actions->_free)(me->starget)) == HT_WOULD_BLOCK)
                     60:            return HT_WOULD_BLOCK;
                     61:     }
2.3       frystyk    62:     HTTRACE(XML_TRACE, "XML Parser.. FREEING...\n");
2.1       frystyk    63:     HT_FREE(me);
                     64:     return status;
                     65: }
                     66: 
                     67: PRIVATE int HTXML_abort (HTStream * me, HTList * e)
                     68: {
2.3       frystyk    69:     HTTRACE(XML_TRACE, "XML Parser.. ABORTING...\n");
2.1       frystyk    70:     XML_ParserFree(me->xmlstream);
2.2       frystyk    71:     if (me->target)    
                     72:        (*me->target->isa->abort)(me->target, NULL);
                     73:     else if (me->starget)      
                     74:        (*me->actions->abort)(me->starget, e);
2.1       frystyk    75:     HT_FREE(me);
                     76:     return HT_ERROR;
                     77: }
                     78: 
                     79: PRIVATE int HTXML_write (HTStream * me, const char * buf, int len)
                     80: {
                     81:     if (me->state == HT_OK) {
                     82:        int status = XML_Parse(me->xmlstream, buf, len, 0);
                     83:        if (!status) {
2.3       frystyk    84:            HTTRACE(XML_TRACE, "XML Parser..  `%s\'\n" _
2.2       frystyk    85:                    (char *)XML_ErrorString(XML_GetErrorCode(me->xmlstream)));
2.1       frystyk    86:            me->state = HT_ERROR;
                     87:        }
                     88:     }
2.4       frystyk    89: 
                     90:     /* 
                     91:     **  We don't want to return an error here as this kills
                     92:     **  a potential pipeline of requests we might have
                     93:     */
                     94:     return HT_OK;
2.1       frystyk    95: }
                     96: 
                     97: PRIVATE int HTXML_putCharacter (HTStream * me, char c)
                     98: {
                     99:     return HTXML_write(me, &c, 1);
                    100: }
                    101: 
                    102: PRIVATE int HTXML_putString (HTStream * me, const char * s)
                    103: {
                    104:     return HTXML_write(me, s, (int) strlen(s));
                    105: }
                    106: 
2.2       frystyk   107: PRIVATE BOOL set_attributes_values(HTTag *tag,BOOL *present,char **value,
                    108:                                   const char *nameatt,const char *valueatt)
                    109: {
                    110:     if(tag && nameatt && valueatt) {
                    111:        int i;
                    112:        HTAttr *attributes= tag->attributes;
                    113:        for(i = 0; i< tag->number_of_attributes ; i++) {
                    114:            if(!strcasecomp(attributes[i].name,nameatt)) {
                    115:                present[i] = TRUE;
                    116:                value[i] = (char *)valueatt;
                    117:                return TRUE;
                    118:            }
                    119:        }
                    120:     }
                    121:     return FALSE;
                    122: }
                    123: 
                    124: PRIVATE void start_element(HTStream *  me,
                    125:                           const XML_Char *name,
                    126:                           const XML_Char **atts)
                    127: {
                    128:     int element_number = 
                    129:        SGML_findElementNumber((SGML_dtd *)me->dtd,(char *)name);
                    130:     if(element_number >= 0) {
                    131:        HTTag *tag = SGML_findTag (me->dtd,element_number);
                    132:        int i = 0;  
                    133:        BOOL present[XML_MAX_ATTRIBUTES];
                    134:        const char *value[XML_MAX_ATTRIBUTES];
                    135:        memset((void *) present, '\0', XML_MAX_ATTRIBUTES);
                    136:        memset((void *) value, '\0', XML_MAX_ATTRIBUTES*sizeof(char *));
                    137: 
                    138:        while(atts[i]) {
                    139:           set_attributes_values(tag,present,(char **)value,atts[i],atts[i+1]);
                    140:            i+=2;
                    141:            /* attributes that are not in the dtd will be lost */
                    142:        }
                    143:        (*me->actions->start_element)
                    144:            (me->starget,element_number,present,value); 
                    145:     } else {
                    146:        /* elements that are not in the dtd will be lost */     
                    147:     }
                    148: }
                    149: 
                    150: PRIVATE void end_element(HTStream * me, const XML_Char *name)
                    151: {
                    152:     int element_number = SGML_findElementNumber(me->dtd,(char *)name);
                    153: 
                    154:     if(element_number > 0) {
                    155:        (*me->actions->end_element)(me->starget, element_number);
                    156:     } else {
                    157:        /* elements that are not in the dtd will be lost */     
                    158:     }
                    159: }
                    160: PRIVATE void character_data(HTStream *me, const XML_Char *s, int len)
                    161: {
                    162:     (*me->actions->put_block)(me->starget, s, len);
                    163: }
                    164: 
                    165: PRIVATE void default_handler(HTStream *me, const XML_Char *s, int len)
                    166: {
                    167:     if(s[0] == '&' && s[len-1]==';') {
                    168:        (*me->actions->unparsed_entity)(me->starget, s,len);
                    169:     } else {
                    170:        /* characters that can not be parsed are lost */
                    171:     }
                    172: }
                    173: 
2.1       frystyk   174: PRIVATE const HTStreamClass HTXMLClass =
                    175: {              
                    176:     "xml",
                    177:     HTXML_flush,
                    178:     HTXML_free,
                    179:     HTXML_abort,
                    180:     HTXML_putCharacter,
                    181:     HTXML_putString,
                    182:     HTXML_write
                    183: }; 
                    184: 
                    185: PUBLIC HTStream * HTXML_new (HTRequest *       request,
                    186:                             void *             param,
                    187:                             HTFormat           input_format,
                    188:                             HTFormat           output_format,
                    189:                             HTStream *         output_stream)
                    190: {
                    191:     HTStream * me = NULL;
                    192:     HTCharset charset = HTResponse_charset (HTRequest_response(request));
                    193:     if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
                    194:        HT_OUTOFMEM("HTXML_new");
                    195:     me->isa = &HTXMLClass;
                    196:     me->state = HT_OK;
                    197:     me->request = request;
                    198:     me->target = output_stream ? output_stream : HTErrorStream();
                    199: 
                    200:     /* Now create the XML parser instance */
                    201:     if ((me->xmlstream = XML_ParserCreate(HTAtom_name(charset))) == NULL) {
                    202:        HT_FREE(me);
                    203:        return HTErrorStream();
                    204:     }
2.3       frystyk   205:     HTTRACE(XML_TRACE, "XML Parser.. Stream created\n");
2.2       frystyk   206:     
                    207:     /* Call the stream callback handler (if any) with this new stream */
2.6     ! frystyk   208:     if (XMLInstance)
        !           209:        (*XMLInstance)(me, request, output_format, output_stream, me->xmlstream, XMLInstanceContext);
2.2       frystyk   210: 
2.1       frystyk   211:     return me;
2.2       frystyk   212: }
                    213: 
2.6     ! frystyk   214: PUBLIC BOOL HTXMLCallback_registerNew (HTXMLCallback_new * me, void * context)
2.2       frystyk   215: {
2.6     ! frystyk   216:     XMLInstance = me;
        !           217:     XMLInstanceContext = context;
2.2       frystyk   218:     return YES;
                    219: }
                    220: 
                    221: PUBLIC HTStream * HTXMLStructured_new (const SGML_dtd * dtd, HTStructured * starget)
                    222: {
                    223:     HTStream * me = NULL;
                    224:     if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
                    225:        HT_OUTOFMEM("HTXML_new");
                    226:     me->isa = &HTXMLClass;
                    227:     me->state = HT_OK;
                    228:     me->starget = starget;
                    229:     me->dtd = (SGML_dtd *)dtd; 
                    230:     me->actions = (HTStructuredClass*)(((HTStream*)starget)->isa);
                    231: 
                    232:     /* Now create the XML parser instance */
                    233:     if ((me->xmlstream = XML_ParserCreate(NULL)) == NULL) {
                    234:        HT_FREE(me);
                    235:        return HTErrorStream();
                    236:     }
                    237:     XML_SetUserData(me->xmlstream,me);
                    238:     XML_SetElementHandler(me->xmlstream,
                    239:                          (XML_StartElementHandler)start_element, 
                    240:                          (XML_EndElementHandler)end_element);
                    241:     XML_SetCharacterDataHandler(me->xmlstream,  
                    242:                                (XML_CharacterDataHandler)character_data);
                    243:     XML_SetDefaultHandler(me->xmlstream,
                    244:                          (XML_DefaultHandler)default_handler);
                    245: 
2.3       frystyk   246:     HTTRACE(XML_TRACE, "XML Parser.. Stream created\n");
2.2       frystyk   247:     return me;
                    248: }
                    249: 
                    250: PUBLIC BOOL HTXMLStructured_setHandlers (HTStream *                    me,
                    251:                                         XML_StartElementHandler        start,
                    252:                                         XML_EndElementHandler          end, 
                    253:                                         XML_CharacterDataHandler       char_data,
                    254:                                         XML_DefaultHandler             def_handler)
                    255: {
                    256:     if(me) {
                    257:        me->xml_start_element = start;
                    258:        me->xml_end_element = end;
                    259:        me->xml_character_data = char_data;
                    260:        me->xml_default_handler = def_handler;
                    261:        XML_SetElementHandler(me->xmlstream,start,end);
                    262:        XML_SetCharacterDataHandler(me->xmlstream,char_data);
                    263:        XML_SetDefaultHandler(me->xmlstream,def_handler);
                    264:        return YES;
                    265:     }
                    266:     return NO;
                    267: }
                    268:                        
                    269: PUBLIC BOOL HTXMLStructured_setUserData(HTStream *me, void *user_data)
                    270: {
                    271:     if(me) {
                    272:        me->xml_user_data = user_data;
                    273:        XML_SetUserData(me->xmlstream,me->xml_user_data);
                    274:        return YES;
                    275:     }
                    276:     return NO;
2.1       frystyk   277: }

Webmaster