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 35static 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 : (NSString *)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:(NSUInteger)_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:(NSUInteger)_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- (NSUInteger)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) */ 456