|
1 "{ Package: 'stx:goodies/xmlsuite/core' }" |
|
2 |
|
3 "{ NameSpace: XMLv2 }" |
|
4 |
|
5 XMLReader subclass:#ExpatXMLReader |
|
6 instanceVariableNames:'parser inCDataSection' |
|
7 classVariableNames:'' |
|
8 poolDictionaries:'' |
|
9 category:'XML Suite-SAX2-XMLReaders' |
|
10 ! |
|
11 |
|
12 !ExpatXMLReader primitiveDefinitions! |
|
13 %{ |
|
14 |
|
15 /* |
|
16 * includes, defines, structure definitions |
|
17 * and typedefs come here. |
|
18 */ |
|
19 |
|
20 #include <stdio.h> |
|
21 #include <expat.h> |
|
22 |
|
23 #define CHUNK_SIZE 8192 |
|
24 |
|
25 /* |
|
26 # define EXPAT_DEBUG(args) printf("ExpatXMLReader [debug]") ; printf args |
|
27 /**/ |
|
28 /**/ |
|
29 # define EXPAT_DEBUG(args) |
|
30 /**/ |
|
31 |
|
32 #if defined (__BORLANDC__) |
|
33 # define __PRETTY_FUNCTION__ "__PRETTY_FUNCTION__ not available" |
|
34 #endif |
|
35 |
|
36 |
|
37 #define EXPAT_DEBUG_ENTER EXPAT_DEBUG((" Entering %s\n",__PRETTY_FUNCTION__)) |
|
38 #define EXPAT_DEBUG_LEAVE EXPAT_DEBUG((" Leaving %s\n",__PRETTY_FUNCTION__)) |
|
39 |
|
40 /* |
|
41 HACK for development. If you write thode functions in |
|
42 "Primitive functions" field, functions are not fileouted |
|
43 when you "accept" primitive method in browser, so |
|
44 C compiler can't compile native code using those methods. |
|
45 */ |
|
46 struct { |
|
47 OBJ* this_object; |
|
48 } user_data; |
|
49 |
|
50 |
|
51 static void XMLCALL |
|
52 startElement(void* readerPointer, const XML_Char* nameStr, const XML_Char** attributes) { |
|
53 OBJ reader; |
|
54 OBJ attArray = nil; |
|
55 OBJ attName,attValue; |
|
56 OBJ name = nil; |
|
57 int i; |
|
58 EXPAT_DEBUG_ENTER; |
|
59 for ( i = 0; attributes[i]; i += 2 ); /* compute length of att array */ |
|
60 EXPAT_DEBUG((" Element tiplet is %s\n",nameStr)); |
|
61 EXPAT_DEBUG((" Number of attributes is %d\n",i)); |
|
62 if ( i > 0 ) { /* there are some attributes */ |
|
63 attArray = __ARRAY_NEW_INT(i); |
|
64 EXPAT_DEBUG((" Attribute array allocated. Entering fill loop\n")); |
|
65 for ( i = 0; attributes[i]; i += 2 ) {/* fill att array */ |
|
66 EXPAT_DEBUG((" Processing attribute %s value %s\n",attributes[i],attributes[i+1])); |
|
67 __PROTECT__(attArray); |
|
68 attName = __MKSTRING(attributes[i]); |
|
69 __PROTECT__(attName); |
|
70 attValue = __MKSTRING(attributes[i+1]); |
|
71 __UNPROTECT__(attName); |
|
72 __UNPROTECT__(attArray); /* unprotect */ |
|
73 __ArrayInstPtr(attArray)->a_element[i] = attName; |
|
74 __STORE(attArray,attName); /* string may be different memory space than array */ |
|
75 __ArrayInstPtr(attArray)->a_element[i+1] = attValue; |
|
76 __STORE(attArray,attValue); /* string may be different memory space than array */ |
|
77 } |
|
78 EXPAT_DEBUG((" Attribute array filled\n")); |
|
79 } |
|
80 __PROTECT__(attArray); |
|
81 name = __MKSTRING(nameStr); |
|
82 __UNPROTECT__(attArray); |
|
83 reader = **(OBJ**)readerPointer; |
|
84 EXPAT_DEBUG((" Reader is at %x, sending #expatStartElement:attributes:\n",reader)); |
|
85 __SSEND2(reader, @symbol(expatStartElement:attributes:),0, name, attArray); |
|
86 EXPAT_DEBUG_LEAVE; |
|
87 } |
|
88 |
|
89 static void XMLCALL |
|
90 endElement(void* readerPointer, const XML_Char* nameStr) { |
|
91 OBJ reader; |
|
92 OBJ name; |
|
93 EXPAT_DEBUG_ENTER; |
|
94 name = __MKSTRING(nameStr); |
|
95 reader = **(OBJ**)readerPointer; |
|
96 __SSEND1(reader, @symbol(expatEndElement:),0, name); |
|
97 EXPAT_DEBUG_LEAVE; |
|
98 } |
|
99 |
|
100 static void XMLCALL |
|
101 startNSPrefixMapping(void* readerPointer, const XML_Char* prefixStr, const XML_Char* uriStr) { |
|
102 OBJ reader = **(OBJ**)readerPointer; |
|
103 OBJ prefix; |
|
104 OBJ uri; |
|
105 EXPAT_DEBUG_ENTER; |
|
106 prefix = __MKSTRING(prefixStr); |
|
107 uri = __MKSTRING(uriStr); |
|
108 reader = **(OBJ**)readerPointer; |
|
109 __SSEND2(reader, @symbol(expatStartPrefix:mappingTo:),0, uri, prefix); |
|
110 EXPAT_DEBUG_LEAVE; |
|
111 } |
|
112 |
|
113 static void XMLCALL |
|
114 endNSPrefixMapping(void* readerPointer, const XML_Char* prefixStr) { |
|
115 OBJ reader; |
|
116 OBJ prefix; |
|
117 EXPAT_DEBUG_ENTER; |
|
118 prefix = __MKSTRING(prefixStr); |
|
119 reader = **(OBJ**)readerPointer; |
|
120 __SSEND1(reader, @symbol(expatEndPrefixMapping:),0, prefix); |
|
121 EXPAT_DEBUG_LEAVE; |
|
122 } |
|
123 |
|
124 static void XMLCALL |
|
125 xmlProlog(void* readerPointer, const XML_Char* verStr, const XML_Char* encStr, int standInt) { |
|
126 OBJ reader; |
|
127 OBJ version; |
|
128 OBJ encoding; |
|
129 OBJ standalone; |
|
130 EXPAT_DEBUG_ENTER; |
|
131 if (verStr == NULL) { |
|
132 version = __MKSTRING("1.0"); |
|
133 } else { |
|
134 version = __MKSTRING(verStr); |
|
135 } |
|
136 if (encStr == NULL) { |
|
137 encoding = nil; |
|
138 } else { |
|
139 encoding = __MKSTRING(encStr); |
|
140 } |
|
141 standalone = __MKINT(standInt); |
|
142 |
|
143 reader = **(OBJ**)readerPointer; |
|
144 __SSEND3(reader, @symbol(expatPrologVersion:encoding:standalone:), |
|
145 0, version, encoding, standalone); |
|
146 EXPAT_DEBUG_LEAVE; |
|
147 } |
|
148 |
|
149 |
|
150 |
|
151 |
|
152 static void XMLCALL |
|
153 characters(void* readerPointer, const XML_Char* charStr, int charLen) { |
|
154 OBJ reader = **(OBJ**)readerPointer; |
|
155 OBJ chars; |
|
156 EXPAT_DEBUG_ENTER; |
|
157 chars = __MKSTRING_L(charStr,charLen); |
|
158 reader = **(OBJ**)readerPointer; |
|
159 __SSEND1(reader, @symbol(expatCharacters:),0, chars); |
|
160 EXPAT_DEBUG_LEAVE; |
|
161 } |
|
162 |
|
163 static void XMLCALL |
|
164 startCDataSection(void* readerPointer) { |
|
165 OBJ reader; |
|
166 EXPAT_DEBUG_ENTER; |
|
167 reader = **(OBJ**)readerPointer; |
|
168 __SSEND1(reader, @symbol(expatInCDataSection:),0,true); |
|
169 EXPAT_DEBUG_LEAVE; |
|
170 } |
|
171 |
|
172 static void XMLCALL |
|
173 endCDataSection(void* readerPointer) { |
|
174 OBJ reader; |
|
175 EXPAT_DEBUG_ENTER; |
|
176 reader = **(OBJ**)readerPointer; |
|
177 __SSEND1(reader, @symbol(expatInCDataSection:),0,false); |
|
178 EXPAT_DEBUG_LEAVE; |
|
179 } |
|
180 |
|
181 static void XMLCALL |
|
182 errorOccuredWhenParsing(XML_Parser p) { |
|
183 OBJ reader; |
|
184 OBJ errorString; |
|
185 EXPAT_DEBUG_ENTER; |
|
186 errorString = __MKSTRING(XML_ErrorString(XML_GetErrorCode(p))); |
|
187 reader = **(OBJ**)XML_GetUserData(p); |
|
188 __SSEND4(reader, @symbol(expatParseError:code:line:column:), 0, |
|
189 errorString, |
|
190 _MKSMALLINT(XML_GetErrorCode(p)), |
|
191 _MKSMALLINT(XML_GetCurrentLineNumber(p)), |
|
192 _MKSMALLINT(XML_GetCurrentColumnNumber(p))); |
|
193 EXPAT_DEBUG_LEAVE; |
|
194 } |
|
195 |
|
196 static void XMLCALL |
|
197 processingInstruction(void* readerPointer, const XML_Char* targetStr, const XML_Char* dataStr) { |
|
198 OBJ reader; |
|
199 OBJ target; |
|
200 OBJ data; |
|
201 EXPAT_DEBUG_ENTER; |
|
202 target = __MKSTRING(targetStr); |
|
203 data = __MKSTRING(dataStr); |
|
204 reader = **(OBJ**)readerPointer; |
|
205 __SSEND2(reader, @symbol(expatPI:data:),0, target,data); |
|
206 EXPAT_DEBUG_LEAVE; |
|
207 } |
|
208 |
|
209 static void XMLCALL |
|
210 comment(void* readerPointer, const XML_Char* commentStr) { |
|
211 OBJ reader; |
|
212 OBJ comment; |
|
213 EXPAT_DEBUG_ENTER; |
|
214 comment = __MKSTRING(commentStr); |
|
215 reader = **(OBJ**)readerPointer; |
|
216 __SSEND1(reader, @symbol(expatComment:),0, comment); |
|
217 EXPAT_DEBUG_LEAVE; |
|
218 } |
|
219 |
|
220 static int XMLCALL |
|
221 unknownEncodingHandler(void *readerPointer, |
|
222 const XML_Char *name, |
|
223 XML_Encoding *info) |
|
224 { |
|
225 OBJ reader; |
|
226 OBJ mapArray; |
|
227 int i; |
|
228 int size; |
|
229 EXPAT_DEBUG_ENTER; |
|
230 reader = **(OBJ**)readerPointer; |
|
231 EXPAT_DEBUG((" Unknown encoding %s encountered\n")); |
|
232 mapArray = __SSEND1(reader, @symbol(expatUnknownEncoding:), 0, __MKSTRING(name)); |
|
233 if (! __isArray(mapArray)) goto error; |
|
234 EXPAT_DEBUG((" Got map!\n")); |
|
235 size = (256 < __arraySize(mapArray) ? 256 : __arraySize(mapArray)); |
|
236 for (i = 0; i < size; i++) { |
|
237 if (__isInteger(__ArrayInstPtr(mapArray)->a_element[i])) { |
|
238 info->map[i] = __intVal(__ArrayInstPtr(mapArray)->a_element[i]); |
|
239 EXPAT_DEBUG((" map[%d] = %d;\n", i, info->map[i])); |
|
240 } else { |
|
241 EXPAT_DEBUG((" Non-integer value in the map array!")); |
|
242 goto error; |
|
243 } |
|
244 } |
|
245 info->convert = NULL; |
|
246 info->release = NULL; |
|
247 EXPAT_DEBUG((" OK, return 1\n")); |
|
248 EXPAT_DEBUG_LEAVE; |
|
249 return 1; |
|
250 error: |
|
251 EXPAT_DEBUG((" FAIL, return 0\n")); |
|
252 EXPAT_DEBUG_LEAVE; |
|
253 return 0; |
|
254 |
|
255 } |
|
256 |
|
257 |
|
258 |
|
259 %} |
|
260 ! ! |
|
261 |
|
262 !ExpatXMLReader primitiveVariables! |
|
263 %{ |
|
264 |
|
265 /* |
|
266 * any local C variables |
|
267 * come here (please, define as static) |
|
268 */ |
|
269 |
|
270 |
|
271 |
|
272 %} |
|
273 ! ! |
|
274 |
|
275 |
|
276 !ExpatXMLReader class methodsFor:'testing'! |
|
277 |
|
278 isAvailable |
|
279 " |
|
280 self isAvailable |
|
281 " |
|
282 |
|
283 ^self perform:#primitiveIsAvailable ifNotUnderstood:[false] |
|
284 |
|
285 "Created: / 29-10-2006 / 22:37:05 / janfrog" |
|
286 "Modified: / 12-04-2007 / 21:31:39 / janfrog" |
|
287 ! |
|
288 |
|
289 primitiveIsAvailable |
|
290 |
|
291 %{ |
|
292 RETURN(true); |
|
293 %}. |
|
294 ^false |
|
295 |
|
296 "Created: / 09-02-2007 / 17:44:42 / janfrog" |
|
297 ! ! |
|
298 |
|
299 !ExpatXMLReader methodsFor:'SAX2 interface - Locator'! |
|
300 |
|
301 getColumnNumber |
|
302 "Superclass says that I am responsible to implement this method" |
|
303 |
|
304 ^self primitiveGetCurrentColumnNumber |
|
305 |
|
306 "Created: / 19-05-2005 / 09:43:25 / masca" |
|
307 ! |
|
308 |
|
309 getLineNumber |
|
310 "Superclass says that I am responsible to implement this method" |
|
311 |
|
312 ^self primitiveGetCurrentLineNumber |
|
313 |
|
314 "Created: / 19-05-2005 / 09:43:37 / masca" |
|
315 ! ! |
|
316 |
|
317 !ExpatXMLReader methodsFor:'expat events'! |
|
318 |
|
319 expatCharacters:aString |
|
320 |
|
321 | handler | |
|
322 handler := self getContentHandler. |
|
323 (inCDataSection and:[handler respondsTo:#cDataSection:]) |
|
324 ifTrue:[^handler cDataSection:aString]. |
|
325 |
|
326 (aString allSatisfy:[:char|char isXMLWhiteSpace]) |
|
327 ifTrue:[handler ignorableWhitespace:aString] |
|
328 ifFalse:[handler characters:aString] |
|
329 |
|
330 "Created: / 17-04-2005 / 09:06:07 / janfrog" |
|
331 "Modified: / 28-12-2005 / 16:18:15 / janfrog" |
|
332 ! |
|
333 |
|
334 expatComment:aString |
|
335 |
|
336 | handler | |
|
337 |
|
338 handler := self getContentHandler. |
|
339 (handler respondsTo:#comment:) |
|
340 ifTrue:[handler comment:aString] |
|
341 |
|
342 "Created: / 17-04-2005 / 13:33:10 / janfrog" |
|
343 "Modified: / 28-12-2005 / 16:18:00 / janfrog" |
|
344 ! |
|
345 |
|
346 expatEndDocument |
|
347 |
|
348 self getContentHandler endDocument |
|
349 |
|
350 "Created: / 17-04-2005 / 09:32:14 / janfrog" |
|
351 ! |
|
352 |
|
353 expatEndDocumentFragment |
|
354 |
|
355 self getContentHandler endDocumentFragment |
|
356 |
|
357 "Created: / 23-04-2005 / 14:16:39 / janfrog" |
|
358 ! |
|
359 |
|
360 expatEndElement:name |
|
361 "name = String" |
|
362 |
|
363 |nodeName| |
|
364 |
|
365 nodeName := self nodeNameFromExpatExpandedElementName:name. |
|
366 self getContentHandler |
|
367 endElement:nodeName localName |
|
368 namespace:nodeName ns |
|
369 prefix:nodeName prefix |
|
370 |
|
371 "Created: / 16-04-2005 / 21:36:24 / janfrog" |
|
372 "Modified: / 29-09-2006 / 10:24:59 / janfrog" |
|
373 ! |
|
374 |
|
375 expatEndPrefixMapping:prefix |
|
376 |
|
377 self getContentHandler endPrefixMapping:prefix |
|
378 |
|
379 "Created: / 17-04-2005 / 08:48:23 / janfrog" |
|
380 ! |
|
381 |
|
382 expatInCDataSection: aBoolean |
|
383 |
|
384 inCDataSection := aBoolean |
|
385 |
|
386 "Created: / 28-12-2005 / 13:49:31 / janfrog" |
|
387 "Modified: / 28-12-2005 / 16:18:04 / janfrog" |
|
388 ! |
|
389 |
|
390 expatPI:target data:data |
|
391 |
|
392 self getContentHandler processingInstruction:target data:data. |
|
393 |
|
394 "Created: / 17-04-2005 / 13:32:50 / janfrog" |
|
395 ! |
|
396 |
|
397 expatParseError:msg code:code line:line column:column |
|
398 |
|
399 | error | |
|
400 |
|
401 error := SAXParseError new |
|
402 errorString:'Parse error at line ',line printString,' col ',column printString,' #',code printString,': ',msg; |
|
403 line:line; |
|
404 col:column. |
|
405 self primitiveFreeExpatParser. |
|
406 self getErrorHandler fatalError:error. |
|
407 |
|
408 "Created: / 17-04-2005 / 09:54:19 / janfrog" |
|
409 "Modified: / 21-04-2005 / 19:41:59 / janfrog" |
|
410 ! |
|
411 |
|
412 expatPrologVersion: vers encoding: enc standalone: stand |
|
413 |
|
414 xmlVersion := vers. |
|
415 xmlEncoding := enc. |
|
416 standalone := stand == 1 |
|
417 |
|
418 "Created: / 28-12-2005 / 16:18:14 / janfrog" |
|
419 ! |
|
420 |
|
421 expatStartDocument |
|
422 |
|
423 self getContentHandler startDocument |
|
424 |
|
425 "Created: / 17-04-2005 / 09:32:03 / janfrog" |
|
426 ! |
|
427 |
|
428 expatStartDocumentFragment |
|
429 |
|
430 self getContentHandler startDocumentFragment |
|
431 |
|
432 "Created: / 23-04-2005 / 14:16:24 / janfrog" |
|
433 ! |
|
434 |
|
435 expatStartElement:name attributes:attArray |
|
436 "name = String |
|
437 attArray = array of strings. could be nil -> no attributes" |
|
438 |
|
439 |nodeName attributes| |
|
440 |
|
441 nodeName := self nodeNameFromExpatExpandedElementName:name. |
|
442 attributes := attArray |
|
443 ifNil:[ Attributes empty ] |
|
444 ifNotNil:[ |
|
445 self attributesFromExpatAttArray:attArray inScopeOfNodeName:nodeName |
|
446 ]. |
|
447 self getContentHandler |
|
448 startElement:nodeName localName |
|
449 namespace:nodeName ns |
|
450 prefix:nodeName prefix |
|
451 attributes:attributes |
|
452 |
|
453 "Created: / 16-04-2005 / 21:36:33 / janfrog" |
|
454 "Modified: / 29-09-2006 / 10:24:25 / janfrog" |
|
455 ! |
|
456 |
|
457 expatStartPrefix:prefix mappingTo:uri |
|
458 |
|
459 self getContentHandler startPrefix:prefix mappingTo:uri |
|
460 |
|
461 "Created: / 17-04-2005 / 08:47:52 / janfrog" |
|
462 ! |
|
463 |
|
464 expatUnknownEncoding: aString |
|
465 |
|
466 | encoder | |
|
467 encoder := CharacterEncoder encoderFor: aString. |
|
468 (encoder isKindOf: CharacterEncoderImplementations::SingleByteEncoder) |
|
469 ifFalse:[^nil "multibyte encoders not supported"]. |
|
470 ^( ( 0 to: 255 ) collect: [:c|encoder decode:c] ) asArray |
|
471 |
|
472 "Modified: / 27-10-2008 / 19:09:57 / Jan Vrany <vranyj1@fel.cvut.cz>" |
|
473 |
|
474 ! ! |
|
475 |
|
476 !ExpatXMLReader methodsFor:'expat primitives'! |
|
477 |
|
478 primitiveChunkSize |
|
479 "Return chunk size" |
|
480 |
|
481 %{ |
|
482 RETURN(_MKSMALLINT(CHUNK_SIZE)); |
|
483 %} |
|
484 |
|
485 "Created: / 21-04-2005 / 19:38:18 / janfrog" |
|
486 ! |
|
487 |
|
488 primitiveCreateExpatParser |
|
489 "Creates and initialize expat parser" |
|
490 |
|
491 %{ |
|
492 XML_Parser p; |
|
493 OBJ** data; |
|
494 OBJ parserAddress; |
|
495 p = XML_ParserCreateNS(NULL,'|'); |
|
496 if (p != NULL) { |
|
497 data = (OBJ**)malloc(sizeof (OBJ**)); |
|
498 EXPAT_DEBUG((" Allocating data=0x%x\n", data)); |
|
499 *data = (OBJ*)malloc(sizeof (OBJ*)); |
|
500 EXPAT_DEBUG((" Allocating *data=0x%x\n", *data)); |
|
501 **data = self; |
|
502 EXPAT_DEBUG((" Parser is **data=0x%x\n", **data)); |
|
503 XML_SetUserData(p,data); |
|
504 __ADD_REFCELL(*data); |
|
505 XML_SetElementHandler(p, startElement, endElement); |
|
506 XML_SetStartNamespaceDeclHandler(p, startNSPrefixMapping); |
|
507 XML_SetEndNamespaceDeclHandler(p, endNSPrefixMapping); |
|
508 XML_SetCharacterDataHandler(p, characters); |
|
509 XML_SetCommentHandler(p, comment); |
|
510 XML_SetProcessingInstructionHandler(p, processingInstruction); |
|
511 XML_SetStartCdataSectionHandler(p, startCDataSection); |
|
512 XML_SetEndCdataSectionHandler(p, endCDataSection); |
|
513 XML_SetXmlDeclHandler(p, xmlProlog); |
|
514 XML_SetUnknownEncodingHandler(p, unknownEncodingHandler, data); |
|
515 XML_SetReturnNSTriplet(p,1); |
|
516 |
|
517 /* Store parser into instance variable */ |
|
518 parserAddress = (__MKEXTERNALADDRESS(p)); |
|
519 __INST(parser) = parserAddress; |
|
520 __STORE(self, parserAddress); |
|
521 |
|
522 |
|
523 RETURN(self) |
|
524 } |
|
525 %}. |
|
526 SAXError raiseErrorString:'Cannot create expat parser' |
|
527 |
|
528 "Created: / 21-04-2005 / 19:00:58 / janfrog" |
|
529 "Modified: / 28-12-2005 / 16:18:15 / janfrog" |
|
530 ! |
|
531 |
|
532 primitiveFreeExpatParser |
|
533 "Frees previously created expat parser" |
|
534 |
|
535 %{ |
|
536 OBJ** data; |
|
537 XML_Parser p; |
|
538 if (__isExternalAddress(__INST(parser))) { |
|
539 p = __externalAddressVal(__INST(parser)); |
|
540 data = (OBJ**)XML_GetUserData(p); |
|
541 __REMOVE_REFCELL(*data); |
|
542 EXPAT_DEBUG((" Parser is **data=0x%x\n", **data)); |
|
543 EXPAT_DEBUG((" Freeing *data=0x%x\n", *data)); |
|
544 free(*data); |
|
545 EXPAT_DEBUG((" Freeing data=0x%x\n", data)); |
|
546 free(data); |
|
547 XML_ParserFree(p); |
|
548 } |
|
549 %}. |
|
550 parser := nil. |
|
551 |
|
552 "Created: / 21-04-2005 / 19:03:20 / janfrog" |
|
553 "Modified: / 11-08-2005 / 21:49:24 / janfrog" |
|
554 ! |
|
555 |
|
556 primitiveGetCurrentColumnNumber |
|
557 "Frees previously created expat parser" |
|
558 |
|
559 %{ |
|
560 OBJ** data; |
|
561 XML_Parser p; |
|
562 if (__isExternalAddress(__INST(parser))) { |
|
563 p = __externalAddressVal(__INST(parser)); |
|
564 RETURN(_MKSMALLINT(XML_GetCurrentColumnNumber(p))); |
|
565 } |
|
566 %}. |
|
567 ^nil |
|
568 |
|
569 "Created: / 02-05-2005 / 12:03:19 / janfrog" |
|
570 "Modified: / 11-08-2005 / 21:31:33 / janfrog" |
|
571 ! |
|
572 |
|
573 primitiveGetCurrentLineNumber |
|
574 "Frees previously created expat parser" |
|
575 |
|
576 %{ |
|
577 OBJ** data; |
|
578 XML_Parser p; |
|
579 if (__isExternalAddress(__INST(parser))) { |
|
580 p = __externalAddressVal(__INST(parser)); |
|
581 RETURN(_MKSMALLINT(XML_GetCurrentLineNumber(p))); |
|
582 } |
|
583 %}. |
|
584 ^nil |
|
585 |
|
586 "Created: / 02-05-2005 / 12:03:30 / janfrog" |
|
587 "Modified: / 11-08-2005 / 21:31:54 / janfrog" |
|
588 ! |
|
589 |
|
590 primitiveParseChunk:anExternalBytes len:anInteger |
|
591 "Frees previously created expat parser" |
|
592 |
|
593 %{ |
|
594 unsigned char* chunk; |
|
595 int chunkLen = __intVal(anInteger); |
|
596 XML_Parser p; |
|
597 EXPAT_DEBUG((" In #primitiveParseChunk:#[...] len:%d\n",chunkLen)); |
|
598 if (__isExternalAddress(__INST(parser))) { |
|
599 p = __externalAddressVal(__INST(parser)); |
|
600 } |
|
601 if (__isExternalBytesLike(anExternalBytes)) { |
|
602 chunk = __externalAddressVal(anExternalBytes); |
|
603 if ( |
|
604 XML_Parse(p, chunk, chunkLen, 0) |
|
605 == XML_STATUS_ERROR |
|
606 ) { |
|
607 errorOccuredWhenParsing(p); |
|
608 RETURN(false); |
|
609 } |
|
610 } else { |
|
611 RETURN(false); |
|
612 } |
|
613 EXPAT_DEBUG((" ...finished\n")); |
|
614 %}. |
|
615 ^true |
|
616 |
|
617 "Created: / 21-04-2005 / 20:09:08 / janfrog" |
|
618 "Modified: / 06-10-2006 / 13:08:55 / janfrog" |
|
619 ! ! |
|
620 |
|
621 !ExpatXMLReader methodsFor:'expat utilities'! |
|
622 |
|
623 attributesFromExpatAttArray:anArray inScopeOfNodeName:ownerNodeName |
|
624 |
|
625 | attributes nodeName att | |
|
626 |
|
627 anArray isEmpty ifTrue:[^Attributes empty]. |
|
628 attributes := Attributes new. |
|
629 |
|
630 anArray pairWiseDo:[:name :value | |
|
631 nodeName := self |
|
632 nodeNameFromExpatExpandedAttributeName:name |
|
633 inScopeOfNodeName:ownerNodeName. |
|
634 att := Attr named:nodeName value:value. |
|
635 attributes add:att |
|
636 ]. |
|
637 ^attributes |
|
638 |
|
639 "Created: / 11-08-2005 / 22:08:47 / janfrog" |
|
640 "Modified: / 29-09-2006 / 10:22:46 / janfrog" |
|
641 ! |
|
642 |
|
643 nodeNameFromExpatExpandedAttributeName:expandedName inScopeOfNodeName:ownerNodeName |
|
644 |
|
645 | a | |
|
646 a := expandedName tokensBasedOn:$|. |
|
647 |
|
648 (a size = 1) ifTrue:[ |
|
649 ^NodeName new |
|
650 prefix:ownerNodeName prefix; |
|
651 ns:ownerNodeName ns; |
|
652 localName:a first |
|
653 ] ifFalse:[ |
|
654 ^NodeName new |
|
655 prefix:a third; |
|
656 ns:a first; |
|
657 localName:a second. |
|
658 ] |
|
659 |
|
660 "Created: / 11-08-2005 / 22:08:47 / janfrog" |
|
661 "Modified: / 29-09-2006 / 10:25:26 / janfrog" |
|
662 ! |
|
663 |
|
664 nodeNameFromExpatExpandedElementName:expandedName |
|
665 |
|
666 | a | |
|
667 a := expandedName tokensBasedOn:$|. |
|
668 |
|
669 (a size = 2) ifTrue:[ |
|
670 ^NodeName new |
|
671 prefix:''; |
|
672 ns:a first; |
|
673 localName:a second |
|
674 ]. |
|
675 (a size = 3) ifTrue:[ |
|
676 ^NodeName new |
|
677 prefix:a third; |
|
678 ns:a first; |
|
679 localName:a second |
|
680 ]. |
|
681 ^NodeName new |
|
682 prefix:''; |
|
683 ns:''; |
|
684 localName:expandedName |
|
685 |
|
686 "Created: / 11-08-2005 / 22:08:47 / janfrog" |
|
687 "Modified: / 06-10-2006 / 09:42:08 / janfrog" |
|
688 ! ! |
|
689 |
|
690 !ExpatXMLReader methodsFor:'initialization'! |
|
691 |
|
692 initialize |
|
693 |
|
694 super initialize. |
|
695 inCDataSection := false. |
|
696 |
|
697 "Created: / 28-12-2005 / 16:18:06 / janfrog" |
|
698 ! ! |
|
699 |
|
700 !ExpatXMLReader methodsFor:'parsing'! |
|
701 |
|
702 parseFragmentStream:aStream |
|
703 |
|
704 | chunk chunkSize bytesRead fragmentHeader fragmentFooter | |
|
705 aStream isReadable ifFalse:[ |
|
706 self getErrorHandler fatalError: |
|
707 (SAXError withMessage:'Stream is not readable') |
|
708 ]. |
|
709 chunk := ExternalBytes new:(chunkSize := self primitiveChunkSize). |
|
710 fragmentHeader := '<?xml version="1.0" ?><fragment>' . |
|
711 fragmentFooter := '</fragment>'. |
|
712 self primitiveCreateExpatParser. |
|
713 aStream binary. |
|
714 self expatStartDocumentFragment. |
|
715 [ |
|
716 chunk replaceBytesFrom:1 to:fragmentHeader size with:fragmentHeader startingAt:0. |
|
717 |
|
718 (self primitiveParseChunk:fragmentHeader len:fragmentHeader size) ifFalse:[ |
|
719 self getErrorHandler fatalError:(SAXError withMessage:'Hmm...cannot parse'). |
|
720 self primitiveFreeExpatParser. |
|
721 ^self |
|
722 ]. |
|
723 [aStream atEnd] whileFalse:[ |
|
724 aStream readWait. |
|
725 bytesRead := aStream nextBytes:chunkSize into:chunk. |
|
726 (self primitiveParseChunk:chunk len:bytesRead) ifFalse:[ |
|
727 self getErrorHandler fatalError:(SAXError withMessage:'Hmm...cannot parse'). |
|
728 self primitiveFreeExpatParser. |
|
729 ^self |
|
730 ] |
|
731 ]. |
|
732 chunk replaceBytesFrom:1 to:fragmentFooter size with:fragmentFooter startingAt:0. |
|
733 (self primitiveParseChunk:chunk len:fragmentFooter size) ifFalse:[ |
|
734 self getErrorHandler fatalError:(SAXError withMessage:'Hmm...cannot parse'). |
|
735 self primitiveFreeExpatParser. |
|
736 ^self |
|
737 ]. |
|
738 self expatEndDocumentFragment. |
|
739 ] ensure:[ |
|
740 self primitiveFreeExpatParser. |
|
741 chunk free |
|
742 ]. |
|
743 |
|
744 "Created: / 23-04-2005 / 14:16:13 / janfrog" |
|
745 "Modified: / 15-07-2010 / 16:30:50 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
746 |
|
747 ! |
|
748 |
|
749 parseStream:aStream |
|
750 |
|
751 | chunk chunkSize bytesRead | |
|
752 aStream isReadable ifFalse:[ |
|
753 self getErrorHandler fatalError: |
|
754 (SAXError withMessage:'Stream is not readable') |
|
755 ]. |
|
756 chunk := ExternalBytes new:(chunkSize := self primitiveChunkSize). |
|
757 [ |
|
758 self primitiveCreateExpatParser. |
|
759 aStream binary. |
|
760 self expatStartDocument. |
|
761 [aStream atEnd] whileFalse:[ |
|
762 aStream readWait. |
|
763 bytesRead := aStream nextBytes:chunkSize into:chunk. |
|
764 (self primitiveParseChunk:chunk len:bytesRead) ifFalse:[ |
|
765 self getErrorHandler fatalError:(SAXError withMessage:'Hmm...cannot parse'). |
|
766 self primitiveFreeExpatParser. |
|
767 ] |
|
768 ]. |
|
769 self expatEndDocument. |
|
770 ] ensure: [ |
|
771 self primitiveFreeExpatParser. |
|
772 chunk free |
|
773 ] |
|
774 |
|
775 "Created: / 21-04-2005 / 19:37:05 / janfrog" |
|
776 "Modified: / 15-07-2010 / 09:29:39 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
777 ! ! |
|
778 |
|
779 !ExpatXMLReader class methodsFor:'documentation'! |
|
780 |
|
781 version |
|
782 ^ '$Id$' |
|
783 |
|
784 ! |
|
785 |
|
786 version_SVN |
|
787 ^ '$Id$' |
|
788 ! ! |
|
789 |