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