]> err.no Git - sope/blob - sope-xml/DOM/DOMSaxHandler.m
fixed a Tiger warning
[sope] / sope-xml / DOM / DOMSaxHandler.m
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 "DOMSaxHandler.h"
23 #include "DOMImplementation.h"
24 #include "DOMDocument.h"
25 #include "DOMElement.h"
26 #include "common.h"
27 #include <SaxObjC/SaxObjC.h>
28
29 @interface NSObject(LineInfoProtocol)
30 - (void)setLine:(int)_line;
31 @end
32
33 @implementation DOMSaxHandler
34
35 static BOOL printErrors = NO;
36
37 - (id)initWithDOMImplementation:(id)_domImpl {
38   if ((self = [super init])) {
39     self->dom = [_domImpl retain];
40     self->maxErrorCount = 100; // this also includes NPSOBJ in HTML !
41   }
42   return self;
43 }
44 - (id)init {
45   static id idom = nil;
46   
47   if (idom == nil)
48     idom = [[NGDOMImplementation alloc] init];
49   
50   return [self initWithDOMImplementation:idom];
51 }
52
53 - (void)dealloc {
54   [self->document release];
55   [self->dom      release];
56   [self->locator  release];
57   [self->fatals   release];
58   [self->errors   release];
59   [self->warnings release];
60   [super dealloc];
61 }
62
63 - (void)setDocumentLocator:(id<NSObject,SaxLocator>)_loc {
64   ASSIGN(self->locator, _loc);
65 }
66
67 - (id)document {
68   return self->document;
69 }
70
71 - (void)clear {
72   ASSIGN(self->document, (id)nil);
73   [self->fatals   removeAllObjects];
74   [self->errors   removeAllObjects];
75   [self->warnings removeAllObjects];
76   self->errorCount = 0;
77 }
78
79 - (int)errorCount {
80   return self->errorCount;
81 }
82 - (int)fatalErrorCount {
83   return [self->fatals count];
84 }
85 - (int)warningCount {
86   return [self->warnings count];
87 }
88 - (int)maxErrorCount {
89   return self->maxErrorCount;
90 }
91
92 - (NSArray *)warnings {
93   return [[self->warnings copy] autorelease];
94 }
95 - (NSArray *)errors {
96   return [[self->errors copy] autorelease];
97 }
98 - (NSArray *)fatalErrors {
99   return [[self->fatals copy] autorelease];
100 }
101
102 /* attributes */
103
104 - (id)_nodeForSaxAttrWithName:(NSString *)_name
105   namespace:(NSString *)_uri
106   rawName:(NSString *)_rawName
107   type:(NSString *)_saxType value:(NSString *)_saxValue
108 {
109   id attr;
110   NSString *nsPrefix;
111   
112   attr = [self->document createAttribute:_name namespaceURI:_uri];
113   if (attr == nil) 
114     return nil;
115   
116   nsPrefix = nil;
117   if (_uri) {
118     NSRange r;
119     
120     r = [_rawName rangeOfString:@":"];
121     if (r.length > 0)
122       nsPrefix = [_rawName substringToIndex:r.location];
123   }
124   
125   if (nsPrefix)
126     [attr setPrefix:nsPrefix];
127   
128   /* add content to attribute */
129   
130   if ([_saxType isEqualToString:@"CDATA"] || (_saxType == nil)) {
131     id content;
132
133     NSAssert(self->document, @"missing document object");
134     
135     if ((content = [self->document createTextNode:_saxValue]))
136       [attr appendChild:content];
137     else
138       NSLog(@"couldn't create text node !");
139   }
140   else
141     NSLog(@"unsupported sax attr type '%@' !", _saxType);
142   
143   return attr;
144 }
145
146 /* document */
147
148 - (void)startDocument {
149   id docType;
150   
151   [self->document release]; self->document = nil;
152   self->errorCount = 0;
153   self->tagDepth   = 0;
154   
155   docType = [self->dom createDocumentType:nil
156                        publicId:[self->locator publicId]
157                        systemId:[self->locator systemId]];
158   
159   self->document = [self->dom createDocumentWithName:nil
160                               namespaceURI:nil
161                               documentType:docType];
162   self->document = [self->document retain];
163   
164   //NSLog(@"started doc: %@", self->document);
165   
166   self->currentElement = self->document;
167 }
168 - (void)endDocument {
169   self->currentElement = nil;
170 }
171
172 - (void)startPrefixMapping:(NSString *)_prefix uri:(NSString *)_uri {
173   //printf("ns-map: %s=%s\n", [_prefix cString], [_uri cString]);
174 }
175 - (void)endPrefixMapping:(NSString *)_prefix {
176   //printf("ns-unmap: %s\n", [_prefix cString]);
177 }
178
179 - (void)startElement:(NSString *)_localName
180   namespace:(NSString *)_ns
181   rawName:(NSString *)_rawName
182   attributes:(id<SaxAttributes>)_attrs
183 {
184   id       elem;
185   NSString *nsPrefix;
186
187   self->tagDepth++;
188   elem = [self->document createElement:_localName namespaceURI:_ns];
189   if (elem == nil) {
190     NSLog(@"%s: couldn't create element for tag '%@'", __PRETTY_FUNCTION__,
191           _rawName);
192     return;
193   }
194   if ([elem respondsToSelector:@selector(setLine:)])
195     [elem setLine:[self->locator lineNumber]];
196   
197   if (_ns) {
198     NSRange r;
199     
200     r = [_rawName rangeOfString:@":"];
201     nsPrefix = (r.length > 0)
202       ? [_rawName substringToIndex:r.location]
203       : nil;
204   }
205   else
206     nsPrefix = nil;
207
208   if (nsPrefix)
209     [elem setPrefix:nsPrefix];
210   
211   NSAssert(self->currentElement, @"no current element !");
212   
213   [self->currentElement appendChild:elem];
214   self->currentElement = elem;
215
216   /* process attributes */
217   {
218     unsigned i, count;
219     
220     for (i = 0, count = [_attrs count]; i < count; i++) {
221       id attr;
222       
223       // NSLog(@"attr %@", [_attrs nameAtIndex:i]);
224       
225       attr = [self _nodeForSaxAttrWithName:[_attrs nameAtIndex:i]
226                    namespace:[_attrs uriAtIndex:i]
227                    rawName:[_attrs rawNameAtIndex:i]
228                    type:[_attrs typeAtIndex:i]
229                    value:[_attrs valueAtIndex:i]];
230       if (attr == nil) {
231         NSLog(@"couldn't create attribute for SAX attr %@, element %@",
232               attr, elem);
233         continue;
234       }
235       
236       /* add node to element */
237       
238       if ([elem setAttributeNodeNS:attr] == nil)
239         NSLog(@"couldn't add attribute %@ to element %@", attr, elem);
240     }
241   }
242 }
243 - (void)endElement:(NSString *)_localName
244   namespace:(NSString *)_ns
245   rawName:(NSString *)_rawName
246 {
247   id parent;
248
249   parent = [self->currentElement parentNode];
250 #if DEBUG
251   NSAssert1(parent, @"no parent for current element %@ !",
252             self->currentElement);
253 #endif
254   self->currentElement = parent;
255   self->tagDepth--;
256 }
257
258 - (void)characters:(unichar *)_chars length:(int)_len {
259   id       charNode;
260   NSString *data;
261   
262   data     = [[NSString alloc] initWithCharacters:_chars length:_len];
263   charNode = [self->document createTextNode:data];
264   [data release]; data = nil;
265   
266   [self->currentElement appendChild:charNode];
267 }
268 - (void)ignorableWhitespace:(unichar *)_chars length:(int)_len {
269 }
270
271 - (void)processingInstruction:(NSString *)_pi data:(NSString *)_data {
272   id piNode;
273
274   piNode = [self->document createProcessingInstruction:_pi data:_data];
275
276   [self->currentElement appendChild:piNode];
277 }
278
279 #if 0
280 - (xmlEntityPtr)getEntity:(NSString *)_name {
281   NSLog(@"get entity %@", _name);
282   return NULL;
283 }
284 - (xmlEntityPtr)getParameterEntity:(NSString *)_name {
285   NSLog(@"get para entity %@", _name);
286   return NULL;
287 }
288 #endif
289
290 /* lexical handler */
291
292 - (void)comment:(unichar *)_chars length:(int)_len {
293   id       commentNode;
294   NSString *data;
295   
296   if (_len == 0)
297     return;
298   
299   data = [[NSString alloc] initWithCharacters:_chars length:_len];
300   commentNode = [self->document createComment:data];
301   [data release]; data = nil;
302   
303   [self->currentElement appendChild:commentNode];
304 }
305
306 - (void)startDTD:(NSString *)_name
307   publicId:(NSString *)_pub
308   systemId:(NSString *)_sys
309 {
310   self->inDTD = YES;
311 }
312 - (void)endDTD {
313   self->inDTD = NO;
314 }
315
316 - (void)startCDATA {
317   self->inCDATA = YES;
318 }
319 - (void)endCDATA {
320   self->inCDATA = NO;
321 }
322
323 /* entities */
324
325 - (id)resolveEntityWithPublicId:(NSString *)_pubId
326   systemId:(NSString *)_sysId
327 {
328   NSLog(@"shall resolve entity with '%@' '%@'", _pubId, _sysId);
329   return nil;
330 }
331
332 /* errors */
333
334 - (void)warning:(SaxParseException *)_exception {
335   NSString *sysId;
336   int line;
337   
338   sysId = [[_exception userInfo] objectForKey:@"systemId"];
339   line  = [[[_exception userInfo] objectForKey:@"line"] intValue];
340   
341   NSLog(@"DOM XML WARNING(%@:%i): %@", sysId, line, [_exception reason]);
342
343   if (self->warnings == nil)
344     self->warnings = [[NSMutableArray alloc] initWithCapacity:32];
345   
346   if (_exception)
347     [self->warnings addObject:_exception];
348 }
349
350 - (void)error:(SaxParseException *)_exception {
351   self->errorCount++;
352   
353   if (printErrors) {
354     NSString *sysId;
355     int line;
356   
357     sysId = [[_exception userInfo] objectForKey:@"systemId"];
358     line  = [[[_exception userInfo] objectForKey:@"line"] intValue];
359     
360     NSLog(@"DOM XML ERROR(%@:%i[%@]): %@ (errcount=%i,max=%i)", sysId, line,
361           [[_exception userInfo] objectForKey:@"parser"],
362           [_exception reason],
363           self->errorCount, self->maxErrorCount);
364   }
365   
366   if (self->errors == nil)
367     self->errors = [[NSMutableArray alloc] initWithCapacity:32];
368   
369   if (_exception)
370     [self->errors addObject:_exception];
371 }
372
373 - (void)fatalError:(SaxParseException *)_exception {
374   NSString *sysId;
375   int line;
376   
377   sysId = [[_exception userInfo] objectForKey:@"systemId"];
378   line  = [[[_exception userInfo] objectForKey:@"line"] intValue];
379   
380   NSLog(@"DOM XML FATAL(%@:%i[%@]): %@", sysId, line,
381         [[_exception userInfo] objectForKey:@"parser"],
382         [_exception reason]);
383   
384   if (self->fatals == nil)
385     self->fatals = [[NSMutableArray alloc] initWithCapacity:32];
386   
387   if (_exception)
388     [self->fatals addObject:_exception];
389   
390   [_exception raise];
391 }
392
393 /* DTD */
394
395 - (void)notationDeclaration:(NSString *)_name
396   publicId:(NSString *)_pubId
397   systemId:(NSString *)_sysId
398 {
399   NSLog(@"decl: notation %@ pub=%@ sys=%@", _name, _pubId, _sysId);
400 }
401
402 - (void)unparsedEntityDeclaration:(NSString *)_name
403   publicId:(NSString *)_pubId
404   systemId:(NSString *)_sysId
405   notationName:(NSString *)_notName
406 {
407   NSLog(@"decl: unparsed entity %@ pub=%@ sys=%@ not=%@",
408         _name, _pubId, _sysId, _notName);
409 }
410
411 /* decl */
412
413 - (void)attributeDeclaration:(NSString *)_attributeName
414   elementName:(NSString *)_elementName
415   type:(NSString *)_type
416   defaultType:(NSString *)_defType
417   defaultValue:(NSString *)_defValue
418 {
419   NSLog(@"decl: attr %@[%@] type '%@' default '%@'[%@]",
420         _attributeName, _elementName, _type, _defValue, _defType);
421 }
422
423 - (void)elementDeclaration:(NSString *)_name contentModel:(NSString *)_model {
424   NSLog(@"decl: element %@ model %@", _name, _model);
425 }
426
427 - (void)externalEntityDeclaration:(NSString *)_name
428   publicId:(NSString *)_pub
429   systemId:(NSString *)_sys
430 {
431   NSLog(@"decl: e-entity %@ pub %@ sys %@", _name, _pub, _sys);
432 }
433
434 - (void)internalEntityDeclaration:(NSString *)_name value:(NSString *)_value {
435   NSLog(@"decl: i-entity %@ value %@", _name, _value);
436 }
437
438 @end /* DOMSaxHandler */
439
440
441 @implementation DOMSaxHandler(SubHandler)
442
443 - (unsigned)tagDepth {
444   return self->tagDepth;
445 }
446
447 - (id)object {
448   return [self document];
449 }
450
451 - (void)setNamespaces:(NSString *)_namespaces {
452   // not yet implemented
453 }
454
455 @end /* DOMSaxHandler(SubHandler) */