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