]> err.no Git - sope/blob - skyrix-xml/pyxSAXDriver/pyxSAXDriver.m
added svn:keywords and svn:ignore where appropriate. removed CVS artifacts.
[sope] / skyrix-xml / pyxSAXDriver / pyxSAXDriver.m
1 /*
2   Copyright (C) 2000-2003 SKYRIX Software AG
3
4   This file is part of OGo
5
6   OGo 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   OGo 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 OGo; 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 // $Id$
22
23 #include "pyxSAXDriver.h"
24 #include <SaxObjC/SaxException.h>
25 #include <SaxObjC/SaxAttributes.h>
26 #include <SaxObjC/SaxDocumentHandler.h>
27 #import <Foundation/Foundation.h>
28
29 #if NeXT_Foundation_LIBRARY || APPLE_Foundation_LIBRARY
30 #  include <FoundationExt/NSObjectMacros.h>
31 #  include <FoundationExt/MissingMethods.h>
32 #endif
33
34 static NSString *SaxDeclHandlerProperty =
35   @"http://xml.org/sax/properties/declaration-handler";
36 static NSString *SaxLexicalHandlerProperty =
37   @"http://xml.org/sax/properties/lexical-handler";
38 #if 0
39 static NSString *SaxDOMNodeProperty =
40   @"http://xml.org/sax/properties/dom-node";
41 static NSString *SaxXMLStringProperty =
42   @"http://xml.org/sax/properties/xml-string";
43 #endif
44
45 @implementation pyxSAXDriver
46
47 - (id)init {
48   self->nsStack = [[NSMutableArray alloc] init];
49   
50   /* feature defaults */
51   self->fNamespaces        = YES;
52   self->fNamespacePrefixes = NO;
53   
54   return self;
55 }
56
57 - (void)dealloc {
58   RELEASE(self->nsStack);
59   RELEASE(self->attrs);
60
61   RELEASE(self->declHandler);
62   RELEASE(self->lexicalHandler);
63   RELEASE(self->contentHandler);
64   RELEASE(self->dtdHandler);
65   RELEASE(self->errorHandler);
66   RELEASE(self->entityResolver);
67   [super dealloc];
68 }
69
70 /* properties */
71
72 - (void)setProperty:(NSString *)_name to:(id)_value {
73   if ([_name isEqualToString:SaxLexicalHandlerProperty]) {
74     ASSIGN(self->lexicalHandler, _value);
75     return;
76   }
77   if ([_name isEqualToString:SaxDeclHandlerProperty]) {
78     ASSIGN(self->declHandler, _value);
79     return;
80   }
81   
82   [SaxNotRecognizedException raise:@"PropertyException"
83                              format:@"don't know property %@", _name];
84 }
85 - (id)property:(NSString *)_name {
86   if ([_name isEqualToString:SaxLexicalHandlerProperty])
87     return self->lexicalHandler;
88   if ([_name isEqualToString:SaxDeclHandlerProperty])
89     return self->declHandler;
90   
91   [SaxNotRecognizedException raise:@"PropertyException"
92                              format:@"don't know property %@", _name];
93   return nil;
94 }
95
96 /* features */
97
98 - (void)setFeature:(NSString *)_name to:(BOOL)_value {
99   if ([_name isEqualToString:@"http://xml.org/sax/features/namespaces"]) {
100     self->fNamespaces = _value;
101     return;
102   }
103   
104   if ([_name isEqualToString:
105                @"http://xml.org/sax/features/namespace-prefixes"]) {
106     self->fNamespacePrefixes = _value;
107     return;
108   }
109
110   [SaxNotRecognizedException raise:@"FeatureException"
111                              format:@"don't know feature %@", _name];
112 }
113 - (BOOL)feature:(NSString *)_name {
114   if ([_name isEqualToString:@"http://xml.org/sax/features/namespaces"])
115     return self->fNamespaces;
116   
117   if ([_name isEqualToString:
118                @"http://xml.org/sax/features/namespace-prefixes"])
119     return self->fNamespacePrefixes;
120   
121   [SaxNotRecognizedException raise:@"FeatureException"
122                              format:@"don't know feature %@", _name];
123   return NO;
124 }
125
126 /* handlers */
127
128 #if 0
129 - (void)setDocumentHandler:(id<NSObject,SaxDocumentHandler>)_handler {
130   SaxDocumentHandlerAdaptor *a;
131
132   a = [[SaxDocumentHandlerAdaptor alloc] initWithDocumentHandler:_handler];
133   [self setContentHandler:a];
134   RELEASE(a);
135 }
136 #endif
137
138 - (void)setDTDHandler:(id<NSObject,SaxDTDHandler>)_handler {
139   ASSIGN(self->dtdHandler, _handler);
140 }
141 - (id<NSObject,SaxDTDHandler>)dtdHandler {
142   return self->dtdHandler;
143 }
144
145 - (void)setErrorHandler:(id<NSObject,SaxErrorHandler>)_handler {
146   ASSIGN(self->errorHandler, _handler);
147 }
148 - (id<NSObject,SaxErrorHandler>)errorHandler {
149   return self->errorHandler;
150 }
151
152 - (void)setEntityResolver:(id<NSObject,SaxEntityResolver>)_handler {
153   ASSIGN(self->entityResolver, _handler);
154 }
155 - (id<NSObject,SaxEntityResolver>)entityResolver {
156   return self->entityResolver;
157 }
158
159 - (void)setContentHandler:(id<NSObject,SaxContentHandler>)_handler {
160   ASSIGN(self->contentHandler, _handler);
161 }
162 - (id<NSObject,SaxContentHandler>)contentHandler {
163   return self->contentHandler;
164 }
165
166 /* parsing */
167
168 - (void)parseFromSource:(id)_source {
169   NSAutoreleasePool *pool;
170   NSArray *lines;
171   
172   if ([_source isKindOfClass:[NSString class]]) {
173     lines = [_source componentsSeparatedByString:@"\n"];
174   }
175   else if ([_source isKindOfClass:[NSData class]]) {
176     _source = [[NSString alloc] 
177                 initWithData:_source
178                 encoding:[NSString defaultCStringEncoding]];
179     lines = [_source componentsSeparatedByString:@"\n"];
180     RELEASE(_source);
181   }
182   else {
183     SaxParseException *e;
184     NSDictionary      *ui;
185     
186     ui = [NSDictionary dictionaryWithObjectsAndKeys:
187                          _source ? _source : @"<nil>", @"source",
188                          self,                         @"parser",
189                          nil];
190     
191     e = (id)[SaxParseException exceptionWithName:@"SaxIOException"
192                                reason:@"can't handle data-source"
193                                userInfo:ui];
194     
195     [self->errorHandler fatalError:e];
196     return;
197   }
198   
199   pool = [[NSAutoreleasePool alloc] init];
200
201   /* start parsing lines */
202   {
203     NSEnumerator *e;
204     NSString *line;
205     
206     e = [lines objectEnumerator];
207     while ((line = [e nextObject])) {
208     recheck:
209       if ([line hasPrefix:@"("]) {
210         NSMutableDictionary *ns = nil;
211         NSString *startTag;
212         NSDictionary *nsDict = nil;
213
214         /* not yet finished ! */
215         
216         startTag = [line substringFromIndex:1];
217         line = [e nextObject];
218         while ([line hasPrefix:@"A"]) {
219           /* attribute */
220           NSString *rawName, *value;
221           unsigned idx;
222           
223           line = [line substringFromIndex:1];
224           
225           if ((idx = [line indexOfString:@" "]) == NSNotFound) {
226             value   = @"";
227             rawName = line;
228           }
229           else {
230             rawName = [line substringToIndex:idx];
231             value   = [line substringFromIndex:(idx + 1)];
232           }
233           
234           if ([rawName hasPrefix:@"xmlns"]) {
235             /* a namespace declaration */
236             if (ns == nil) ns = [[NSMutableDictionary alloc] init];
237             
238             if ([rawName hasPrefix:@"xmlns:"]) {
239               /* eg <x xmlns:nl="http://www.w3.org"/> */
240               NSString *prefix, *uri;
241               
242               prefix = [rawName substringFromIndex:6];
243               uri    = value;
244               
245               [ns setObject:uri forKey:prefix];
246
247               if (self->fNamespaces)
248                 [self->contentHandler startPrefixMapping:prefix uri:uri];
249             }
250             else {
251               /* eg <x xmlns="http://www.w3.org"/> */
252               [ns setObject:value forKey:@":"];
253             }
254           }
255         }
256         /* start tag finished */
257         nsDict = [ns copy];
258         RELEASE(ns); ns = nil;
259         
260         /* manage namespace stack */
261   
262         if (nsDict == nil)
263           nsDict = [NSDictionary dictionary];
264         
265         [self->nsStack addObject:nsDict];
266
267         /* to be completed ! */
268         
269         if (line != nil)
270           goto recheck;
271       }
272     }
273   }
274   
275   RELEASE(pool);
276 }
277
278 - (void)parseFromSystemId:(NSString *)_sysId {
279   NSString *s;
280
281   /* _sysId is a URI */
282   if (![_sysId hasPrefix:@"file://"]) {
283     SaxParseException *e;
284     NSDictionary      *ui;
285     
286     ui = [NSDictionary dictionaryWithObjectsAndKeys:
287                          _sysId ? _sysId : @"<nil>", @"systemID",
288                          self,                       @"parser",
289                          nil];
290     
291     e = (id)[SaxParseException exceptionWithName:@"SaxIOException"
292                                reason:@"can't handle system-id"
293                                userInfo:ui];
294     
295     [self->errorHandler fatalError:e];
296     return;
297   }
298
299   /* cut off file:// */
300   _sysId = [_sysId substringFromIndex:7];
301   
302   /* start parsing .. */
303   if ((s = [NSString stringWithContentsOfFile:_sysId]))
304     [self parseFromSource:s];
305 }
306
307 /* entities */
308
309 - (NSString *)replacementStringForEntityNamed:(NSString *)_entityName {
310   //NSLog(@"get entity: %@", _entityName);
311   return [[@"&amp;" stringByAppendingString:_entityName]
312                     stringByAppendingString:@";"];
313 }
314
315 /* namespace support */
316
317 - (NSString *)nsUriForPrefix:(NSString *)_prefix {
318   NSEnumerator *e;
319   NSDictionary *ns;
320   
321   e = [self->nsStack reverseObjectEnumerator];
322   while ((ns = [e nextObject])) {
323     NSString *uri;
324     
325     if ((uri = [ns objectForKey:_prefix]))
326       return uri;
327   }
328   return nil;
329 }
330
331 - (NSString *)defaultNamespace {
332   return [self nsUriForPrefix:@":"];
333 }
334
335 @end /* pyxSAXDriver */