~ubuntu-branches/ubuntu/edgy/sope/edgy

« back to all changes in this revision

Viewing changes to sope-xml/STXSaxDriver/STXSaxDriver.m

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Ley
  • Date: 2005-08-19 16:53:31 UTC
  • Revision ID: james.westby@ubuntu.com-20050819165331-hs683wz1osm708pw
Tags: upstream-4.4rc.2
ImportĀ upstreamĀ versionĀ 4.4rc.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  Copyright (C) 2000-2005 SKYRIX Software AG
 
3
 
 
4
  This file is part of SOPE.
 
5
 
 
6
  SOPE is free software; you can redistribute it and/or modify it under
 
7
  the terms of the GNU Lesser General Public License as published by the
 
8
  Free Software Foundation; either version 2, or (at your option) any
 
9
  later version.
 
10
 
 
11
  SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
 
12
  WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
13
  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 
14
  License for more details.
 
15
 
 
16
  You should have received a copy of the GNU Lesser General Public
 
17
  License along with SOPE; see the file COPYING.  If not, write to the
 
18
  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
19
  02111-1307, USA.
 
20
*/
 
21
 
 
22
#include "STXSaxDriver.h"
 
23
#include "StructuredText.h"
 
24
#include "StructuredTextList.h"
 
25
#include "StructuredTextListItem.h"
 
26
#include "StructuredTextLiteralBlock.h"
 
27
#include "StructuredTextHeader.h"
 
28
#include "StructuredTextParagraph.h"
 
29
#include <SaxObjC/XMLNamespaces.h>
 
30
#include "common.h"
 
31
 
 
32
static NSString *SaxDeclHandlerProperty =
 
33
  @"http://xml.org/sax/properties/declaration-handler";
 
34
static NSString *SaxLexicalHandlerProperty =
 
35
  @"http://xml.org/sax/properties/lexical-handler";
 
36
 
 
37
@interface NSObject(SAX)
 
38
- (void)produceSaxEventsOnSTXSaxDriver:(STXSaxDriver *)_sax;
 
39
@end
 
40
 
 
41
@implementation STXSaxDriver
 
42
 
 
43
static BOOL debugOn = NO;
 
44
 
 
45
+ (void)initialize {
 
46
  NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
 
47
  
 
48
  debugOn = [ud boolForKey:@"STXSaxDriverDebugEnabled"];
 
49
}
 
50
 
 
51
- (id)init {
 
52
  if ((self = [super init])) {
 
53
    self->attrs = [[SaxAttributes alloc] init];
 
54
  }
 
55
  return self;
 
56
}
 
57
 
 
58
- (void)dealloc {
 
59
  [self->context        release];
 
60
  [self->attrs          release];
 
61
  
 
62
  [self->lexicalHandler release];
 
63
  [self->contentHandler release];
 
64
  [self->errorHandler   release];
 
65
  [self->entityResolver release];
 
66
  [super dealloc];
 
67
}
 
68
 
 
69
/* properties */
 
70
 
 
71
- (void)setProperty:(NSString *)_name to:(id)_value {
 
72
  if ([_name isEqualToString:SaxLexicalHandlerProperty]) {
 
73
    [self->lexicalHandler autorelease];
 
74
    self->lexicalHandler = [_value retain];
 
75
    return;
 
76
  }
 
77
  if ([_name isEqualToString:SaxDeclHandlerProperty]) {
 
78
    return;
 
79
  }
 
80
  
 
81
  [SaxNotRecognizedException raise:@"PropertyException"
 
82
                             format:@"don't know property %@", _name];
 
83
}
 
84
- (id)property:(NSString *)_name {
 
85
  if ([_name isEqualToString:SaxLexicalHandlerProperty])
 
86
    return self->lexicalHandler;
 
87
  if ([_name isEqualToString:SaxDeclHandlerProperty])
 
88
    return nil;
 
89
  
 
90
  [SaxNotRecognizedException raise:@"PropertyException"
 
91
                             format:@"don't know property %@", _name];
 
92
  return nil;
 
93
}
 
94
 
 
95
/* features */
 
96
 
 
97
- (void)setFeature:(NSString *)_name to:(BOOL)_value {
 
98
  return;
 
99
#if 0 // be tolerant
 
100
  [SaxNotRecognizedException raise:@"FeatureException"
 
101
                             format:@"don't know feature %@", _name];
 
102
#endif
 
103
}
 
104
- (BOOL)feature:(NSString *)_name {
 
105
  return NO;
 
106
}
 
107
 
 
108
/* handlers */
 
109
 
 
110
- (void)setContentHandler:(id<NSObject,SaxContentHandler>)_handler {
 
111
  [self->contentHandler autorelease];
 
112
  self->contentHandler = [_handler retain];
 
113
}
 
114
- (id<NSObject,SaxContentHandler>)contentHandler {
 
115
  return self->contentHandler;
 
116
}
 
117
 
 
118
- (void)setLexicalHandler:(id<NSObject,SaxLexicalHandler>)_handler {
 
119
  [self->lexicalHandler autorelease];
 
120
  self->lexicalHandler = [_handler retain];
 
121
}
 
122
- (id<NSObject,SaxLexicalHandler>)lexicalHandler {
 
123
  return self->lexicalHandler;
 
124
}
 
125
 
 
126
- (void)setDTDHandler:(id<NSObject,SaxDTDHandler>)_handler {
 
127
}
 
128
- (id<NSObject,SaxDTDHandler>)dtdHandler {
 
129
  return nil;
 
130
}
 
131
 
 
132
- (void)setErrorHandler:(id<NSObject,SaxErrorHandler>)_handler {
 
133
  [self->errorHandler autorelease];
 
134
  self->errorHandler = [_handler retain];
 
135
}
 
136
- (id<NSObject,SaxErrorHandler>)errorHandler {
 
137
  return self->errorHandler;
 
138
}
 
139
 
 
140
- (void)setEntityResolver:(id<NSObject,SaxEntityResolver>)_handler {
 
141
  [self->entityResolver autorelease];
 
142
  self->entityResolver = [_handler retain];
 
143
}
 
144
- (id<NSObject,SaxEntityResolver>)entityResolver {
 
145
  return self->entityResolver;
 
146
}
 
147
 
 
148
/* support */
 
149
 
 
150
- (void)_beginTag:(NSString *)_tag {
 
151
  [self->contentHandler startElement:_tag namespace:XMLNS_XHTML rawName:_tag
 
152
                        attributes:nil /* id<SaxAttributes> */];
 
153
}
 
154
- (void)_endTag:(NSString *)_tag {
 
155
  [self->contentHandler endElement:_tag namespace:XMLNS_XHTML rawName:_tag];
 
156
}
 
157
- (void)_characters:(NSString *)_chars {
 
158
  unichar      *buf;
 
159
  unsigned int len;
 
160
  
 
161
  if ((len = [_chars length]) == 0) // TODO: may or may not be correct
 
162
    return;
 
163
  
 
164
  buf = calloc(len + 4, sizeof(unichar)); // TODO: cache/reuse buffer
 
165
  [_chars getCharacters:buf];
 
166
  
 
167
  [self->contentHandler characters:buf length:len];
 
168
  if (buf) free(buf);
 
169
}
 
170
 
 
171
/* STX delegate */
 
172
 
 
173
- (NSString *)insertText:(NSString *)_txt inContext:(NSDictionary *)_ctx {
 
174
  if (debugOn) NSLog(@"        insert text: (len=%d)", [_txt length]);
 
175
  [self _beginTag:@"p"];
 
176
  [self _characters:_txt];
 
177
  [self _endTag:@"p"];
 
178
  return nil;
 
179
}
 
180
 
 
181
- (NSString *)insertItalics:(NSString *)_txt inContext:(NSDictionary *)_ctx {
 
182
  if (debugOn) NSLog(@"        insert italics: (len=%d)", [_txt length]);
 
183
  [self _beginTag:@"em"];
 
184
  [self _characters:_txt];
 
185
  [self _endTag:@"em"];
 
186
  return nil;
 
187
}
 
188
 
 
189
- (NSString *)insertUnderline:(NSString *)_txt inContext:(NSDictionary *)_ctx {
 
190
  if (debugOn) NSLog(@"        insert underline: (len=%d)", [_txt length]);
 
191
  [self _beginTag:@"u"];
 
192
  [self _characters:_txt];
 
193
  [self _endTag:@"u"];
 
194
  return nil;
 
195
}
 
196
 
 
197
- (NSString *)insertBold:(NSString *)_txt inContext:(NSDictionary *)_ctx {
 
198
  if (debugOn) NSLog(@"        insert bold: (len=%d)", [_txt length]);
 
199
  [self _beginTag:@"strong"];
 
200
  [self _characters:_txt];
 
201
  [self _endTag:@"strong"];
 
202
  return nil;
 
203
}
 
204
 
 
205
- (NSString *)insertPreformatted:(NSString *)_txt
 
206
  inContext:(NSDictionary *)_ctx 
 
207
{
 
208
  [self _beginTag:@"pre"];
 
209
  [self _characters:_txt];
 
210
  [self _endTag:@"pre"];
 
211
  return nil;
 
212
}
 
213
 
 
214
- (NSString *)insertLink:(NSString *)_txt 
 
215
  withUrl:(NSString *)_url target:(NSString *)_target 
 
216
  inContext:(NSDictionary *)_ctx 
 
217
{
 
218
  // TODO: need to generate SaxAttributes here
 
219
  
 
220
  [self->attrs clear];
 
221
  [self->attrs 
 
222
       addAttribute:@"href" uri:XMLNS_XHTML rawName:@"href"
 
223
       type:@"CDATA" value:_url];
 
224
  if ([_target length] > 0) {
 
225
    [self->attrs
 
226
         addAttribute:@"target" uri:XMLNS_XHTML rawName:@"target"
 
227
         type:@"CDATA" value:_target];
 
228
  }
 
229
 
 
230
  [self->contentHandler startElement:@"a" namespace:XMLNS_XHTML rawName:@"a"
 
231
                        attributes:self->attrs];
 
232
  [self _characters:_txt];
 
233
  [self _endTag:@"a"];
 
234
 
 
235
  // if we return nil, the content will be generated as if it didn't match
 
236
  // if we return an empty string, a zero-length string is reported
 
237
  return @""; 
 
238
}
 
239
 
 
240
- (NSString *)insertEmail:(NSString *)_txt withAddress:(NSString *)_link 
 
241
  inContext:(NSDictionary *)_ctx 
 
242
{
 
243
  // TODO: check&implement
 
244
#if 0
 
245
  [NSString stringWithFormat:@"<a href=\"%@\">%@</a>", anAddress, _txt];
 
246
#endif
 
247
  return _txt;
 
248
}
 
249
 
 
250
- (NSString *)insertImage:(NSString *)_title withUrl:(NSString *)_src
 
251
  inContext:(NSDictionary *)_ctx 
 
252
{
 
253
  // TODO: check&implement
 
254
#if 0
 
255
  [NSString stringWithFormat:@"<img src=\"%@\" title=\"%@\" />", anUrl, _txt];
 
256
#endif
 
257
  return _title;
 
258
}
 
259
 
 
260
- (NSString *)insertExtrapolaLink:(NSString *)_txt
 
261
  parameters:(NSDictionary *)_paras
 
262
  withTarget:(NSString *)_target
 
263
  inContext:(NSDictionary *)_ctx 
 
264
{
 
265
  // TODO: do we want to support that?
 
266
  if (debugOn) NSLog(@"insert extrapola link: %@", _txt);
 
267
  [self _characters:_txt];
 
268
  return nil;
 
269
}
 
270
 
 
271
- (NSString *)insertDynamicKey:(NSString *)_k inContext:(NSDictionary *)_ctx {
 
272
  // TODO: what to do here?
 
273
  return [_ctx objectForKey:_k];
 
274
}
 
275
 
 
276
- (NSString *)insertPreprocessedTextForKey:(NSString *)_k 
 
277
  inContext:(NSDictionary *)_ctx 
 
278
{
 
279
  // TODO: what to do here?
 
280
  return [_ctx objectForKey:_k];
 
281
}
 
282
 
 
283
/* generating element events */
 
284
 
 
285
- (void)produceSaxEventsForParagraph:(StructuredTextParagraph *)_p {
 
286
  NSString *s;
 
287
  
 
288
  if (debugOn) NSLog(@"      produce SAX events for paragraph: %@", _p);
 
289
  
 
290
  s = [_p textParsedWithDelegate:(id)self inContext:self->context];
 
291
  if ([s length] > 0) [self _characters:s];
 
292
}
 
293
 
 
294
- (void)produceSaxEventsForHeader:(StructuredTextHeader *)_h {
 
295
  NSString *tagName, *s;
 
296
  
 
297
  if (debugOn) NSLog(@"      produce SAX events for header: %@", _h);
 
298
  
 
299
  switch ([_h level]) {
 
300
  case 1: tagName = @"h1"; break;
 
301
  case 2: tagName = @"h2"; break;
 
302
  case 3: tagName = @"h3"; break;
 
303
  case 4: tagName = @"h4"; break;
 
304
  case 5: tagName = @"h5"; break;
 
305
  case 6: tagName = @"h6"; break;
 
306
  default:
 
307
    tagName = [@"h" stringByAppendingFormat:@"%d", [_h level]];
 
308
    break;
 
309
  }
 
310
  
 
311
  [self _beginTag:tagName];
 
312
  if ((s = [_h textParsedWithDelegate:(id)self inContext:self->context]))
 
313
    [self _characters:s];
 
314
  [self _endTag:tagName];
 
315
  
 
316
  [self produceSaxEventsForElements:[_h elements]];
 
317
}
 
318
 
 
319
- (void)produceSaxEventsForList:(StructuredTextList *)_list {
 
320
  NSString *tagName;
 
321
  
 
322
  if (debugOn) NSLog(@"      produce SAX events for list: %@", _list);
 
323
  switch ([_list typology]) {
 
324
    case StructuredTextList_BULLET:     tagName = @"ul"; break;
 
325
    case StructuredTextList_ENUMERATED: tagName = @"ol"; break;
 
326
    case StructuredTextList_DEFINITION: tagName = @"dl"; break;
 
327
    default: tagName = nil;
 
328
  }
 
329
  
 
330
  [self _beginTag:tagName];
 
331
  [self produceSaxEventsForElements:[_list elements]];
 
332
  [self _endTag:tagName];
 
333
}
 
334
 
 
335
- (void)produceSaxEventsForListItem:(StructuredTextListItem *)_item {
 
336
  NSString *s;
 
337
  int typology;
 
338
  
 
339
  if (debugOn) NSLog(@"        produce SAX events for item: %@", _item);
 
340
  
 
341
  typology = [[_item list] typology];
 
342
 
 
343
  if (typology == StructuredTextList_DEFINITION) {
 
344
    [self _beginTag:@"dt"];
 
345
    if ((s = [_item titleParsedWithDelegate:(id)self inContext:self->context]))
 
346
      [self _characters:s];
 
347
    [self _endTag:@"dt"];
 
348
  }
 
349
  
 
350
  switch (typology) {
 
351
    case StructuredTextList_BULLET:     [self _beginTag:@"li"]; break;
 
352
    case StructuredTextList_ENUMERATED: [self _beginTag:@"li"]; break;
 
353
    case StructuredTextList_DEFINITION: [self _beginTag:@"dd"]; break;
 
354
  }
 
355
  
 
356
  if ((s = [_item textParsedWithDelegate:(id)self inContext:self->context])) {
 
357
    if (debugOn) NSLog(@"          chars: %d", [s length]);
 
358
    [self _characters:s];
 
359
  }
 
360
  
 
361
    if (debugOn) NSLog(@"          elems: %d", [[_item elements] count]);
 
362
  [self produceSaxEventsForElements:[_item elements]];
 
363
  
 
364
  switch (typology) {
 
365
    case StructuredTextList_BULLET:     [self _endTag:@"li"]; break;
 
366
    case StructuredTextList_ENUMERATED: [self _endTag:@"li"]; break;
 
367
    case StructuredTextList_DEFINITION: [self _endTag:@"dd"]; break;
 
368
  }
 
369
}
 
370
 
 
371
- (void)produceSaxEventsForLiteralBlock:(StructuredTextLiteralBlock *)_block {
 
372
  [self _beginTag:@"pre"];
 
373
  [self _characters:[_block text]];
 
374
  [self _endTag:@"pre"];
 
375
}
 
376
 
 
377
/* generating events */
 
378
 
 
379
- (void)produceSaxEventsForElement:(id)_element {
 
380
  if (debugOn) NSLog(@"    produce SAX events for element: %@", _element);
 
381
 
 
382
  if (_element == nil)
 
383
    return;
 
384
  
 
385
  if ([_element respondsToSelector:@selector(produceSaxEventsOnSTXSaxDriver:)])
 
386
    [_element produceSaxEventsOnSTXSaxDriver:self];
 
387
  else {
 
388
    NSLog(@"Note: cannot handle STX element: %@", _element);
 
389
  }
 
390
}
 
391
 
 
392
- (void)produceSaxEventsForElements:(NSArray *)_elems {
 
393
  unsigned int i, c;
 
394
  
 
395
  if (debugOn)
 
396
    NSLog(@"  produce SAX events for elements: %d", [_elems count]);
 
397
  for (i = 0, c = [_elems count]; i < c; i++) {
 
398
    id currentObject;
 
399
    
 
400
    currentObject = [_elems objectAtIndex:i];
 
401
    if (debugOn) NSLog(@"   element[%d]/%d: %@", i, c, currentObject);
 
402
    [self produceSaxEventsForElement:currentObject];
 
403
  }
 
404
}
 
405
 
 
406
- (void)produceSaxEventsForStructuredTextDocument:(StructuredTextDocument *)_d{
 
407
  if (debugOn) NSLog(@"  produce SAX events for document: %@", _d);
 
408
  [self produceSaxEventsForElements:[_d bodyElements]];
 
409
}
 
410
 
 
411
- (void)produceSaxEventsForStructuredText:(StructuredText *)_stx 
 
412
  systemId:(NSString *)_sysId
 
413
{
 
414
  if (debugOn) NSLog(@"produce SAX events for: %@", _stx);
 
415
  
 
416
  [self->contentHandler startDocument];
 
417
  
 
418
  [self produceSaxEventsForStructuredTextDocument:[_stx document]];
 
419
 
 
420
  [self->contentHandler endDocument];
 
421
}
 
422
 
 
423
/* parsing */
 
424
 
 
425
- (void)parseFromString:(NSString *)_str systemId:(NSString *)_sysId {
 
426
  StructuredText *stx;
 
427
  
 
428
  if (_sysId == nil) _sysId = @"<string>";
 
429
  stx = [[[StructuredText alloc] initWithString:_str] autorelease];
 
430
  
 
431
  if (debugOn) NSLog(@"%s: %@: %@", __PRETTY_FUNCTION__, _sysId, stx);
 
432
  [self produceSaxEventsForStructuredText:stx systemId:_sysId];
 
433
}
 
434
 
 
435
- (void)parseFromData:(NSData *)_data systemId:(NSString *)_sysId {
 
436
  NSString *s;
 
437
  
 
438
  if (_sysId == nil) _sysId = @"<data>";
 
439
  s = [[NSString alloc] initWithData:_data encoding:NSISOLatin1StringEncoding];
 
440
  s = [s autorelease];
 
441
  
 
442
  [self parseFromString:s systemId:_sysId];
 
443
}
 
444
 
 
445
- (void)parseFromNSURL:(NSURL *)_url systemId:(NSString *)_sysId {
 
446
  NSData *data;
 
447
  
 
448
  if (_sysId == nil) 
 
449
    _sysId = [_url absoluteString];
 
450
  
 
451
  if ((data = [_url resourceDataUsingCache:NO]) == nil) {
 
452
    SaxParseException *e;
 
453
    NSDictionary      *ui;
 
454
    
 
455
    ui = [NSDictionary dictionaryWithObjectsAndKeys:
 
456
                         _url   ? _url   : (id)@"<nil>", @"url",
 
457
                         _sysId ? _sysId : (id)@"<nil>", @"publicId",
 
458
                         self,                           @"parser",
 
459
                         nil];
 
460
    
 
461
    e = (id)[SaxParseException exceptionWithName:@"SaxIOException"
 
462
                               reason:@"could not retrieve URL content"
 
463
                               userInfo:ui];
 
464
    [self->errorHandler fatalError:e];
 
465
    return;
 
466
  }
 
467
  
 
468
  [self parseFromData:data systemId:_sysId];
 
469
}
 
470
 
 
471
- (void)parseFromSource:(id)_source systemId:(NSString *)_sysId {
 
472
  if (_source == nil) {
 
473
    /* no source ??? */
 
474
    SaxParseException *e;
 
475
    NSDictionary      *ui;
 
476
    
 
477
    ui = [NSDictionary dictionaryWithObjectsAndKeys:
 
478
                         _sysId ? _sysId : (id)@"<nil>", @"publicId",
 
479
                         self,                           @"parser",
 
480
                         nil];
 
481
    
 
482
    e = (id)[SaxParseException exceptionWithName:@"SaxIOException"
 
483
                               reason:@"missing source for parsing!"
 
484
                               userInfo:ui];
 
485
    [self->errorHandler fatalError:e];
 
486
    return;
 
487
  }
 
488
  
 
489
  if ([_source isKindOfClass:[NSString class]]) {
 
490
    [self parseFromString:_source systemId:_sysId];
 
491
    return;
 
492
  }
 
493
 
 
494
  if ([_source isKindOfClass:[NSURL class]]) {
 
495
    [self parseFromNSURL:_source systemId:_sysId];
 
496
    return;
 
497
  }
 
498
  
 
499
  if ([_source isKindOfClass:[NSData class]]) {
 
500
    [self parseFromData:_source systemId:_sysId];
 
501
    return;
 
502
  }
 
503
  
 
504
  {
 
505
    SaxParseException *e;
 
506
    NSDictionary      *ui;
 
507
    
 
508
    ui = [NSDictionary dictionaryWithObjectsAndKeys:
 
509
                         _source ? _source : @"<nil>", @"source",
 
510
                         _sysId  ? _sysId  : @"<nil>", @"publicId",
 
511
                         self,                         @"parser",
 
512
                         nil];
 
513
    
 
514
    e = (id)[SaxParseException exceptionWithName:@"SaxIOException"
 
515
                               reason:@"can not handle data-source"
 
516
                               userInfo:ui];
 
517
    
 
518
    [self->errorHandler fatalError:e];
 
519
    return;
 
520
  }
 
521
}
 
522
 
 
523
- (void)parseFromSource:(id)_source {
 
524
  [self parseFromSource:_source systemId:nil];
 
525
}
 
526
- (void)parseFromSystemId:(NSString *)_sysId {
 
527
  NSURL *url;
 
528
 
 
529
  if ([_sysId length] == 0) {
 
530
    SaxParseException *e;
 
531
    NSDictionary *ui;
 
532
    
 
533
    ui = [NSDictionary dictionaryWithObjectsAndKeys:self, @"parser", nil];
 
534
    e = (id)[SaxParseException exceptionWithName:@"SaxIOException"
 
535
                               reason:@"missing system-id for parsing!"
 
536
                               userInfo:ui];
 
537
    [self->errorHandler fatalError:e];
 
538
    return;
 
539
  }
 
540
  
 
541
  if ([_sysId rangeOfString:@"://"].length == 0) {
 
542
    /* not a URL */
 
543
    if (![_sysId isAbsolutePath])
 
544
      _sysId = [[NSFileManager defaultManager] currentDirectoryPath];
 
545
    url = [[[NSURL alloc] initFileURLWithPath:_sysId] autorelease];
 
546
  }
 
547
  else
 
548
    url = [NSURL URLWithString:_sysId];
 
549
  
 
550
  [self parseFromSource:url systemId:_sysId];
 
551
}
 
552
 
 
553
@end /* STXSaxDriver */