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