PageRenderTime 42ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 1ms

/sope-xml/samples/PlistSaxDriver/PlistSaxDriver.m

http://sope-appserver.googlecode.com/
Objective C | 430 lines | 313 code | 90 blank | 27 comment | 42 complexity | c66ff2be906f702712709089955b65a4 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0
  1. /*
  2. Copyright (C) 2000-2005 SKYRIX Software AG
  3. This file is part of SOPE.
  4. SOPE is free software; you can redistribute it and/or modify it under
  5. the terms of the GNU Lesser General Public License as published by the
  6. Free Software Foundation; either version 2, or (at your option) any
  7. later version.
  8. SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
  9. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10. FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
  11. License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with SOPE; see the file COPYING. If not, write to the
  14. Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
  15. 02111-1307, USA.
  16. */
  17. #import <Foundation/NSObject.h>
  18. #include <SaxObjC/SaxXMLReader.h>
  19. #include <SaxObjC/SaxContentHandler.h>
  20. #include <SaxObjC/SaxDTDHandler.h>
  21. #include <SaxObjC/SaxErrorHandler.h>
  22. #include <SaxObjC/SaxEntityResolver.h>
  23. #include <SaxObjC/SaxLexicalHandler.h>
  24. #include <SaxObjC/SaxLocator.h>
  25. #include <SaxObjC/SaxDeclHandler.h>
  26. #include <expat.h>
  27. @class NSMutableArray, NSMutableDictionary;
  28. @class SaxAttributes;
  29. @interface PlistSaxDriver : NSObject < SaxXMLReader >
  30. {
  31. @private
  32. id<NSObject,SaxContentHandler> contentHandler;
  33. id<NSObject,SaxErrorHandler> errorHandler;
  34. /* features */
  35. BOOL fNamespaces;
  36. BOOL fNamespacePrefixes;
  37. NSString *plistNamespace;
  38. }
  39. @end
  40. #include <SaxObjC/SaxException.h>
  41. #include <SaxObjC/SaxDocumentHandlerAdaptor.h>
  42. #include <NGExtensions/NGExtensions.h>
  43. #include "common.h"
  44. @interface NSObject(Walking)
  45. - (void)_walkWithPlistSaxDriver:(PlistSaxDriver *)_driver;
  46. @end
  47. @interface PlistSaxDriver(Privates)
  48. - (void)_walkDictionary:(NSDictionary *)_dict;
  49. - (void)_walkArray:(NSArray *)_dict;
  50. - (void)_walkData:(NSData *)_dict;
  51. - (void)_walkString:(NSString *)_dict;
  52. @end
  53. @implementation PlistSaxDriver
  54. - (void)dealloc {
  55. RELEASE(self->contentHandler);
  56. RELEASE(self->errorHandler);
  57. [super dealloc];
  58. }
  59. /* properties */
  60. - (void)setProperty:(NSString *)_name to:(id)_value {
  61. return;
  62. [SaxNotRecognizedException raise:@"PropertyException"
  63. format:@"don't know property %@", _name];
  64. }
  65. - (id)property:(NSString *)_name {
  66. return nil;
  67. [SaxNotRecognizedException raise:@"PropertyException"
  68. format:@"don't know property %@", _name];
  69. return nil;
  70. }
  71. /* features */
  72. - (void)setFeature:(NSString *)_name to:(BOOL)_value {
  73. if ([_name isEqualToString:@"http://xml.org/sax/features/namespaces"]) {
  74. self->fNamespaces = _value;
  75. return;
  76. }
  77. if ([_name isEqualToString:
  78. @"http://xml.org/sax/features/namespace-prefixes"]) {
  79. self->fNamespacePrefixes = _value;
  80. return;
  81. }
  82. [SaxNotRecognizedException raise:@"FeatureException"
  83. format:@"don't know feature %@", _name];
  84. }
  85. - (BOOL)feature:(NSString *)_name {
  86. if ([_name isEqualToString:@"http://xml.org/sax/features/namespaces"])
  87. return self->fNamespaces;
  88. if ([_name isEqualToString:
  89. @"http://xml.org/sax/features/namespace-prefixes"])
  90. return self->fNamespacePrefixes;
  91. if ([_name isEqualToString:
  92. @"http://www.skyrix.com/sax/features/predefined-namespaces"])
  93. return NO;
  94. [SaxNotRecognizedException raise:@"FeatureException"
  95. format:@"don't know feature %@", _name];
  96. return NO;
  97. }
  98. /* handlers */
  99. - (void)setDocumentHandler:(id<NSObject,SaxDocumentHandler>)_handler {
  100. SaxDocumentHandlerAdaptor *a;
  101. a = [[SaxDocumentHandlerAdaptor alloc] initWithDocumentHandler:_handler];
  102. [self setContentHandler:a];
  103. RELEASE(a);
  104. }
  105. - (void)setDTDHandler:(id<NSObject,SaxDTDHandler>)_handler {
  106. }
  107. - (id<NSObject,SaxDTDHandler>)dtdHandler {
  108. return nil;
  109. }
  110. - (void)setErrorHandler:(id<NSObject,SaxErrorHandler>)_handler {
  111. ASSIGN(self->errorHandler, _handler);
  112. }
  113. - (id<NSObject,SaxErrorHandler>)errorHandler {
  114. return self->errorHandler;
  115. }
  116. - (void)setEntityResolver:(id<NSObject,SaxEntityResolver>)_handler {
  117. }
  118. - (id<NSObject,SaxEntityResolver>)entityResolver {
  119. return nil;
  120. }
  121. - (void)setContentHandler:(id<NSObject,SaxContentHandler>)_handler {
  122. ASSIGN(self->contentHandler, _handler);
  123. }
  124. - (id<NSObject,SaxContentHandler>)contentHandler {
  125. return self->contentHandler;
  126. }
  127. /* walking the list */
  128. - (NSString *)plistNamespace {
  129. return nil;
  130. }
  131. - (void)_writeString:(id)_s {
  132. unsigned len;
  133. _s = [_s stringValue];
  134. if ((len = [_s length]) == 0) return;
  135. if (len == 1) {
  136. unichar c[2];
  137. [_s getCharacters:&(c[0])];
  138. c[1] = '\0';
  139. [self->contentHandler characters:&(c[0]) length:1];
  140. }
  141. else {
  142. unichar *ca;
  143. ca = calloc(len + 1, sizeof(unichar));
  144. [_s getCharacters:ca];
  145. ca[len] = 0;
  146. [self->contentHandler characters:ca length:len];
  147. if (ca) free(ca);
  148. }
  149. }
  150. - (void)_walkDictionary:(NSDictionary *)_dict {
  151. NSEnumerator *keys;
  152. id key;
  153. if (_dict == nil) return;
  154. [self->contentHandler
  155. startElement:@"dict" namespace:self->plistNamespace
  156. rawName:@"dict"
  157. attributes:nil];
  158. keys = [_dict keyEnumerator];
  159. while ((key = [keys nextObject])) {
  160. id value;
  161. value = [_dict objectForKey:key];
  162. [self->contentHandler
  163. startElement:@"key" namespace:self->plistNamespace
  164. rawName:@"key"
  165. attributes:nil];
  166. [self _writeString:key];
  167. [self->contentHandler
  168. endElement:@"key" namespace:self->plistNamespace
  169. rawName:@"key"];
  170. [value _walkWithPlistSaxDriver:self];
  171. }
  172. [self->contentHandler
  173. endElement:@"dict" namespace:self->plistNamespace
  174. rawName:@"dict"];
  175. }
  176. - (void)_walkArray:(NSArray *)_array {
  177. unsigned i, count;
  178. if (_array == nil) return;
  179. [self->contentHandler
  180. startElement:@"array" namespace:self->plistNamespace
  181. rawName:@"array"
  182. attributes:nil];
  183. for (i = 0, count = [_array count]; i < count; i++)
  184. [[_array objectAtIndex:i] _walkWithPlistSaxDriver:self];
  185. [self->contentHandler
  186. endElement:@"array" namespace:self->plistNamespace
  187. rawName:@"array"];
  188. }
  189. - (void)_walkData:(NSData *)_data {
  190. NSString *s;
  191. if (_data == nil) return;
  192. s = [[NSString alloc] initWithData:[_data dataByEncodingBase64]
  193. encoding:NSUTF8StringEncoding];
  194. AUTORELEASE(s);
  195. [self->contentHandler
  196. startElement:@"data" namespace:self->plistNamespace
  197. rawName:@"data"
  198. attributes:nil];
  199. [self _writeString:s];
  200. [self->contentHandler
  201. endElement:@"data" namespace:self->plistNamespace
  202. rawName:@"data"];
  203. }
  204. - (void)_walkString:(NSString *)_s {
  205. if (_s == nil) return;
  206. [self->contentHandler
  207. startElement:@"string" namespace:self->plistNamespace
  208. rawName:@"string"
  209. attributes:nil];
  210. [self _writeString:_s];
  211. [self->contentHandler
  212. endElement:@"string" namespace:self->plistNamespace
  213. rawName:@"string"];
  214. }
  215. - (void)_walkRoot:(id)_plist {
  216. static SaxAttributes *versionAttr = nil;
  217. if (versionAttr == nil) {
  218. versionAttr = [[SaxAttributes alloc] init];
  219. [versionAttr addAttribute:@"version" uri:self->plistNamespace
  220. rawName:@"version"
  221. type:@"CDATA"
  222. value:@"0.9"];
  223. }
  224. [self->contentHandler startDocument];
  225. [self->contentHandler
  226. startElement:@"plist" namespace:self->plistNamespace
  227. rawName:@"plist"
  228. attributes:versionAttr];
  229. [_plist _walkWithPlistSaxDriver:self];
  230. [self->contentHandler
  231. endElement:@"plist" namespace:self->plistNamespace
  232. rawName:@"plist"];
  233. [self->contentHandler endDocument];
  234. }
  235. /* parsing ... */
  236. - (void)_parseFromString:(NSString *)_str systemId:(NSString *)_sysId {
  237. id plist;
  238. if ((plist = [_str propertyList])) {
  239. [self _walkRoot:plist];
  240. }
  241. else if (self->errorHandler) {
  242. /* log parse error */
  243. SaxParseException *e;
  244. NSDictionary *ui;
  245. ui = [NSDictionary dictionaryWithObjectsAndKeys:
  246. _sysId, @"systemId",
  247. nil];
  248. e = (id)[SaxParseException exceptionWithName:@"SAXError"
  249. reason:@"couldn't parse property list"
  250. userInfo:ui];
  251. [self->errorHandler error:e];
  252. }
  253. }
  254. - (void)parseFromSource:(id)_source systemId:(NSString *)_sysId {
  255. NSAutoreleasePool *pool;
  256. pool = [[NSAutoreleasePool alloc] init];
  257. if ([_source isKindOfClass:[NSData class]]) {
  258. NSString *s;
  259. s = [[NSString alloc] initWithData:_source
  260. encoding:[NSString defaultCStringEncoding]];
  261. AUTORELEASE(s);
  262. [self _parseFromString:s systemId:_sysId];
  263. }
  264. else if ([_source isKindOfClass:[NSURL class]]) {
  265. [self parseFromSystemId:_source];
  266. }
  267. else if ([_source isKindOfClass:[NSString class]]) {
  268. if (_sysId == nil) _sysId = @"<string>";
  269. [self _parseFromString:_source systemId:_sysId];
  270. }
  271. else if ([_source isKindOfClass:[NSDictionary class]]) {
  272. if (_sysId == nil) _sysId = @"<dictionary>";
  273. [_source _walkRoot:self];
  274. }
  275. else if ([_source isKindOfClass:[NSArray class]]) {
  276. if (_sysId == nil) _sysId = @"<array>";
  277. [_source _walkRoot:self];
  278. }
  279. else {
  280. SaxParseException *e;
  281. NSDictionary *ui;
  282. ui = [NSDictionary dictionaryWithObjectsAndKeys:
  283. _source ? _source : @"<nil>", @"source",
  284. self, @"parser",
  285. nil];
  286. e = (id)[SaxParseException exceptionWithName:@"SaxIOException"
  287. reason:@"can't handle data-source"
  288. userInfo:ui];
  289. [self->errorHandler fatalError:e];
  290. }
  291. RELEASE(pool);
  292. }
  293. - (void)parseFromSource:(id)_source {
  294. [self parseFromSource:_source systemId:@"<memory>"];
  295. }
  296. - (void)parseFromSystemId:(NSString *)_sysId {
  297. NSAutoreleasePool *pool;
  298. NSString *str;
  299. NSURL *url;
  300. pool = [[NSAutoreleasePool alloc] init];
  301. url = [NSURL URLWithString:_sysId];
  302. str = [NSString stringWithContentsOfURL:url];
  303. [self _parseFromString:str systemId:_sysId];
  304. RELEASE(pool);
  305. }
  306. @end /* PlistSaxDriver */
  307. @implementation NSDictionary(Walking)
  308. - (void)_walkWithPlistSaxDriver:(PlistSaxDriver *)_driver {
  309. [_driver _walkDictionary:self];
  310. }
  311. @end
  312. @implementation NSArray(Walking)
  313. - (void)_walkWithPlistSaxDriver:(PlistSaxDriver *)_driver {
  314. [_driver _walkArray:self];
  315. }
  316. @end
  317. @implementation NSSet(Walking)
  318. - (void)_walkWithPlistSaxDriver:(PlistSaxDriver *)_driver {
  319. [_driver _walkArray:[self allObjects]];
  320. }
  321. @end
  322. @implementation NSData(Walking)
  323. - (void)_walkWithPlistSaxDriver:(PlistSaxDriver *)_driver {
  324. [_driver _walkData:self];
  325. }
  326. @end
  327. @implementation NSString(Walking)
  328. - (void)_walkWithPlistSaxDriver:(PlistSaxDriver *)_driver {
  329. [_driver _walkString:self];
  330. }
  331. @end
  332. @implementation NSObject(Walking)
  333. - (void)_walkWithPlistSaxDriver:(PlistSaxDriver *)_driver {
  334. [_driver _walkString:[self stringValue]];
  335. }
  336. @end