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