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

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.3     ! frystyk     6: **     @(#) $Id: HTXML.c,v 2.2 1999/02/22 01:04:24 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.2       frystyk    15: #include "HTXML.h"                                      /* Implemented here */
                     16: #include "SGML.h"
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:     }
                     87:     return me->state;
                     88: }
                     89: 
                     90: PRIVATE int HTXML_putCharacter (HTStream * me, char c)
                     91: {
                     92:     return HTXML_write(me, &c, 1);
                     93: }
                     94: 
                     95: PRIVATE int HTXML_putString (HTStream * me, const char * s)
                     96: {
                     97:     return HTXML_write(me, s, (int) strlen(s));
                     98: }
                     99: 
2.2       frystyk   100: PRIVATE BOOL set_attributes_values(HTTag *tag,BOOL *present,char **value,
                    101:                                   const char *nameatt,const char *valueatt)
                    102: {
                    103:     if(tag && nameatt && valueatt) {
                    104:        int i;
                    105:        HTAttr *attributes= tag->attributes;
                    106:        for(i = 0; i< tag->number_of_attributes ; i++) {
                    107:            if(!strcasecomp(attributes[i].name,nameatt)) {
                    108:                present[i] = TRUE;
                    109:                value[i] = (char *)valueatt;
                    110:                return TRUE;
                    111:            }
                    112:        }
                    113:     }
                    114:     return FALSE;
                    115: }
                    116: 
                    117: PRIVATE void start_element(HTStream *  me,
                    118:                           const XML_Char *name,
                    119:                           const XML_Char **atts)
                    120: {
                    121:     int element_number = 
                    122:        SGML_findElementNumber((SGML_dtd *)me->dtd,(char *)name);
                    123:     if(element_number >= 0) {
                    124:        HTTag *tag = SGML_findTag (me->dtd,element_number);
                    125:        int i = 0;  
                    126:        BOOL present[XML_MAX_ATTRIBUTES];
                    127:        const char *value[XML_MAX_ATTRIBUTES];
                    128:        memset((void *) present, '\0', XML_MAX_ATTRIBUTES);
                    129:        memset((void *) value, '\0', XML_MAX_ATTRIBUTES*sizeof(char *));
                    130: 
                    131:        while(atts[i]) {
                    132:           set_attributes_values(tag,present,(char **)value,atts[i],atts[i+1]);
                    133:            i+=2;
                    134:            /* attributes that are not in the dtd will be lost */
                    135:        }
                    136:        (*me->actions->start_element)
                    137:            (me->starget,element_number,present,value); 
                    138:     } else {
                    139:        /* elements that are not in the dtd will be lost */     
                    140:     }
                    141: }
                    142: 
                    143: PRIVATE void end_element(HTStream * me, const XML_Char *name)
                    144: {
                    145:     int element_number = SGML_findElementNumber(me->dtd,(char *)name);
                    146: 
                    147:     if(element_number > 0) {
                    148:        (*me->actions->end_element)(me->starget, element_number);
                    149:     } else {
                    150:        /* elements that are not in the dtd will be lost */     
                    151:     }
                    152: }
                    153: PRIVATE void character_data(HTStream *me, const XML_Char *s, int len)
                    154: {
                    155:     (*me->actions->put_block)(me->starget, s, len);
                    156: }
                    157: 
                    158: PRIVATE void default_handler(HTStream *me, const XML_Char *s, int len)
                    159: {
                    160:     if(s[0] == '&' && s[len-1]==';') {
                    161:        (*me->actions->unparsed_entity)(me->starget, s,len);
                    162:     } else {
                    163:        /* characters that can not be parsed are lost */
                    164:     }
                    165: }
                    166: 
2.1       frystyk   167: PRIVATE const HTStreamClass HTXMLClass =
                    168: {              
                    169:     "xml",
                    170:     HTXML_flush,
                    171:     HTXML_free,
                    172:     HTXML_abort,
                    173:     HTXML_putCharacter,
                    174:     HTXML_putString,
                    175:     HTXML_write
                    176: }; 
                    177: 
                    178: PUBLIC HTStream * HTXML_new (HTRequest *       request,
                    179:                             void *             param,
                    180:                             HTFormat           input_format,
                    181:                             HTFormat           output_format,
                    182:                             HTStream *         output_stream)
                    183: {
                    184:     HTStream * me = NULL;
                    185:     HTCharset charset = HTResponse_charset (HTRequest_response(request));
                    186:     if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
                    187:        HT_OUTOFMEM("HTXML_new");
                    188:     me->isa = &HTXMLClass;
                    189:     me->state = HT_OK;
                    190:     me->request = request;
                    191:     me->target = output_stream ? output_stream : HTErrorStream();
                    192: 
                    193:     /* Now create the XML parser instance */
                    194:     if ((me->xmlstream = XML_ParserCreate(HTAtom_name(charset))) == NULL) {
                    195:        HT_FREE(me);
                    196:        return HTErrorStream();
                    197:     }
2.3     ! frystyk   198:     HTTRACE(XML_TRACE, "XML Parser.. Stream created\n");
2.2       frystyk   199:     
                    200:     /* Call the stream callback handler (if any) with this new stream */
                    201:     if (newInstance)
                    202:        (*newInstance)(me, request, output_format, output_stream, me->xmlstream);
                    203: 
2.1       frystyk   204:     return me;
2.2       frystyk   205: }
                    206: 
                    207: PUBLIC BOOL HTXMLCallback_registerNew (HTXMLCallback_new * me)
                    208: {
                    209:     newInstance = me;
                    210:     return YES;
                    211: }
                    212: 
                    213: PUBLIC HTStream * HTXMLStructured_new (const SGML_dtd * dtd, HTStructured * starget)
                    214: {
                    215:     HTStream * me = NULL;
                    216:     if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
                    217:        HT_OUTOFMEM("HTXML_new");
                    218:     me->isa = &HTXMLClass;
                    219:     me->state = HT_OK;
                    220:     me->starget = starget;
                    221:     me->dtd = (SGML_dtd *)dtd; 
                    222:     me->actions = (HTStructuredClass*)(((HTStream*)starget)->isa);
                    223: 
                    224:     /* Now create the XML parser instance */
                    225:     if ((me->xmlstream = XML_ParserCreate(NULL)) == NULL) {
                    226:        HT_FREE(me);
                    227:        return HTErrorStream();
                    228:     }
                    229:     XML_SetUserData(me->xmlstream,me);
                    230:     XML_SetElementHandler(me->xmlstream,
                    231:                          (XML_StartElementHandler)start_element, 
                    232:                          (XML_EndElementHandler)end_element);
                    233:     XML_SetCharacterDataHandler(me->xmlstream,  
                    234:                                (XML_CharacterDataHandler)character_data);
                    235:     XML_SetDefaultHandler(me->xmlstream,
                    236:                          (XML_DefaultHandler)default_handler);
                    237: 
2.3     ! frystyk   238:     HTTRACE(XML_TRACE, "XML Parser.. Stream created\n");
2.2       frystyk   239:     return me;
                    240: }
                    241: 
                    242: PUBLIC BOOL HTXMLStructured_setHandlers (HTStream *                    me,
                    243:                                         XML_StartElementHandler        start,
                    244:                                         XML_EndElementHandler          end, 
                    245:                                         XML_CharacterDataHandler       char_data,
                    246:                                         XML_DefaultHandler             def_handler)
                    247: {
                    248:     if(me) {
                    249:        me->xml_start_element = start;
                    250:        me->xml_end_element = end;
                    251:        me->xml_character_data = char_data;
                    252:        me->xml_default_handler = def_handler;
                    253:        XML_SetElementHandler(me->xmlstream,start,end);
                    254:        XML_SetCharacterDataHandler(me->xmlstream,char_data);
                    255:        XML_SetDefaultHandler(me->xmlstream,def_handler);
                    256:        return YES;
                    257:     }
                    258:     return NO;
                    259: }
                    260:                        
                    261: PUBLIC BOOL HTXMLStructured_setUserData(HTStream *me, void *user_data)
                    262: {
                    263:     if(me) {
                    264:        me->xml_user_data = user_data;
                    265:        XML_SetUserData(me->xmlstream,me->xml_user_data);
                    266:        return YES;
                    267:     }
                    268:     return NO;
2.1       frystyk   269: }

Webmaster