Annotation of libwww/Library/src/HTXML.c, revision 2.4
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.4 ! frystyk 6: ** @(#) $Id: HTXML.c,v 2.3 1999/02/22 22:10:12 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: }
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