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

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

Webmaster