Permalink
Browse files

Initial commit, contains SMModelObject as we've been using it for a w…

…hile plus a new sample project with demo code.
  • Loading branch information...
nfarina committed Jan 19, 2011
0 parents commit 3b33548903b083524a1e4fe918ef39644e4d5c5d
@@ -0,0 +1,12 @@
+
+# Mac
+.DS_Store
+
+# Xcode
+build/
+*.mode*
+*.pbxuser
+*~.nib
+
+# Xcode 4
+xcuserdata/
@@ -0,0 +1,50 @@
+
+// Thanks Apple, for not just exposing NSXMLDocument!
+
+#ifdef __IPHONE_4_0
+@interface SMXMLElement : NSObject<NSXMLParserDelegate> {
+#else
+@interface SMXMLElement : NSObject {
+#endif
+
+@private
+ SMXMLElement *parent; // nonretained
+ NSString *name;
+ NSMutableString *value;
+ NSMutableArray *children;
+ NSDictionary *attributes;
+}
+
+@property (nonatomic, assign) SMXMLElement *parent;
+@property (nonatomic, copy) NSString *name;
+@property (nonatomic, retain) NSString *value;
+@property (nonatomic, retain) NSArray *children;
+@property (nonatomic, readonly) SMXMLElement *firstChild, *lastChild;
+@property (nonatomic, retain) NSDictionary *attributes;
+
+- (SMXMLElement *)childNamed:(NSString *)name;
+- (NSArray *)childrenNamed:(NSString *)name;
+- (SMXMLElement *)childWithAttribute:(NSString *)attributeName value:(NSString *)attributeValue;
+- (NSString *)attributeNamed:(NSString *)name;
+- (SMXMLElement *)descendantWithPath:(NSString *)path;
+- (NSString *)valueWithPath:(NSString *)path;
+
+@end
+
+#ifdef __IPHONE_4_0
+@interface SMXMLDocument : NSObject<NSXMLParserDelegate> {
+#else
+@interface SMXMLDocument : NSObject {
+#endif
+
+@private
+ SMXMLElement *root;
+}
+
+@property (nonatomic, retain) SMXMLElement *root;
+
+- (id)initWithData:(NSData *)data;
+
++ (SMXMLDocument *)documentWithData:(NSData *)data;
+
+@end
@@ -0,0 +1,170 @@
+#import "SMXMLDocument.h"
+
+@implementation SMXMLElement
+@synthesize parent, name, value, children, attributes;
+
+- (void)dealloc {
+ self.parent = nil;
+ self.name = nil;
+ self.value = nil;
+ self.children = nil;
+ self.attributes = nil;
+ [super dealloc];
+}
+
+- (NSString *)descriptionWithIndent:(NSString *)indent {
+
+ NSMutableString *s = [NSMutableString string];
+ [s appendFormat:@"%@<%@", indent, name];
+
+ for (NSString *attribute in attributes)
+ [s appendFormat:@" %@=\"%@\"", attribute, [attributes objectForKey:attribute]];
+
+ NSString *trimVal = [value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
+
+ if (trimVal.length > 25)
+ trimVal = [NSString stringWithFormat:@"%@", [trimVal substringToIndex:25]];
+
+ if (children.count) {
+ [s appendString:@">\n"];
+
+ NSString *childIndent = [indent stringByAppendingString:@" "];
+
+ if (trimVal.length)
+ [s appendFormat:@"%@%@\n", childIndent, trimVal];
+
+ for (SMXMLElement *child in children)
+ [s appendFormat:@"%@\n", [child descriptionWithIndent:childIndent]];
+
+ [s appendFormat:@"%@</%@>", indent, name];
+ }
+ else if (trimVal.length) {
+ [s appendFormat:@">%@</%@>", trimVal, name];
+ }
+ else [s appendString:@"/>"];
+
+ return s;
+}
+
+- (NSString *)description {
+ return [self descriptionWithIndent:@""];
+}
+
+- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
+
+ if (!string) return;
+
+ if (value)
+ [(NSMutableString *)value appendString:string];
+ else
+ self.value = [NSMutableString stringWithString:string];
+}
+
+- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
+ SMXMLElement *child = [[[SMXMLElement alloc] init] autorelease];
+ child.parent = self;
+ child.name = elementName;
+ child.attributes = attributeDict;
+
+ if (children)
+ [(NSMutableArray *)children addObject:child];
+ else
+ self.children = [NSMutableArray arrayWithObject:child];
+
+ [parser setDelegate:child];
+}
+
+- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
+ [parser setDelegate:parent];
+}
+
+- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
+ NSLog(@"ERROR at line %i col %i while parsing <%@>: %@. Value so far: %@", parser.lineNumber, parser.columnNumber, name, parseError, value);
+}
+
+- (SMXMLElement *)childNamed:(NSString *)nodeName {
+ for (SMXMLElement *child in children)
+ if ([child.name isEqual:nodeName])
+ return child;
+ return nil;
+}
+
+- (NSArray *)childrenNamed:(NSString *)nodeName {
+ NSMutableArray *array = [NSMutableArray array];
+ for (SMXMLElement *child in children)
+ if ([child.name isEqual:nodeName])
+ [array addObject:child];
+ return [[array copy] autorelease];
+}
+
+- (SMXMLElement *)childWithAttribute:(NSString *)attributeName value:(NSString *)attributeValue {
+ for (SMXMLElement *child in children)
+ if ([[child attributeNamed:attributeName] isEqual:attributeValue])
+ return child;
+ return nil;
+}
+
+- (NSString *)attributeNamed:(NSString *)attributeName {
+ return [attributes objectForKey:attributeName];
+}
+
+- (SMXMLElement *)descendantWithPath:(NSString *)path {
+ SMXMLElement *descendant = self;
+ for (NSString *childName in [path componentsSeparatedByString:@"."])
+ descendant = [descendant childNamed:childName];
+ return descendant;
+}
+
+- (NSString *)valueWithPath:(NSString *)path {
+ NSArray *components = [path componentsSeparatedByString:@"@"];
+ SMXMLElement *descendant = [self descendantWithPath:[components objectAtIndex:0]];
+ return [components count] > 1 ? [descendant attributeNamed:[components objectAtIndex:1]] : descendant.value;
+}
+
+
+- (SMXMLElement *)firstChild { return [children count] > 0 ? [children objectAtIndex:0] : nil; }
+- (SMXMLElement *)lastChild { return [children lastObject]; }
+
+@end
+
+@implementation SMXMLDocument
+@synthesize root;
+
+- (id)initWithData:(NSData *)data {
+ if ([super init]) {
+ NSXMLParser *parser = [[[NSXMLParser alloc] initWithData:data] autorelease];
+ [parser setDelegate:self];
+ [parser setShouldProcessNamespaces:YES];
+ [parser setShouldReportNamespacePrefixes:YES];
+ [parser setShouldResolveExternalEntities:NO];
+ [parser parse];
+ }
+ return self;
+}
+
+- (void)dealloc {
+ self.root = nil;
+ [super dealloc];
+}
+
++ (SMXMLDocument *)documentWithData:(NSData *)data {
+ return [[[SMXMLDocument alloc] initWithData:data] autorelease];
+}
+
+- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
+
+ self.root = [[[SMXMLElement alloc] init] autorelease];
+ root.name = elementName;
+ root.attributes = attributeDict;
+ [parser setDelegate:root];
+}
+
+- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
+ NSLog(@"ERROR at line %i col %i while parsing root: %@", parser.lineNumber, parser.columnNumber, parseError);
+}
+
+- (NSString *)description {
+ return root.description;
+}
+
+@end
@@ -0,0 +1,3 @@
+
+@interface AppDelegate : NSObject <UIApplicationDelegate>
+@end
@@ -0,0 +1,36 @@
+#import "AppDelegate.h"
+#import "SMXMLDocument.h"
+
+@implementation AppDelegate
+
+- (void) applicationDidFinishLaunching:(UIApplication *)application {
+
+ // find "sample.xml" in our bundle resources
+ NSString *sampleXML = [[NSBundle mainBundle] pathForResource:@"sample" ofType:@"xml"];
+ NSData *data = [NSData dataWithContentsOfFile:sampleXML];
+
+ // create a new SMXMLDocument with the contents of sample.xml
+ SMXMLDocument *document = [SMXMLDocument documentWithData:data];
+
+ // demonstrate -description of document/element classes
+ NSLog(@"Document:\n %@", document);
+
+ // Pull out the <books> node
+ SMXMLElement *books = [document.root childNamed:@"books"];
+
+ // Look through <books> children of type <book>
+ for (SMXMLElement *book in [books childrenNamed:@"book"]) {
+
+ // demonstrate common cases of extracting XML data
+ NSString *isbn = [book attributeNamed:@"isbn"]; // XML attribute
+ NSString *title = [book valueWithPath:@"title"]; // child node value
+ float price = [[book valueWithPath:@"price"] floatValue]; // child node value (converted)
+
+ // show off some KVC magic
+ NSArray *authors = [[book childNamed:@"authors"].children valueForKey:@"value"];
+
+ NSLog(@"Found a book!\n ISBN: %@ \n Title: %@ \n Price: %f \n Authors: %@", isbn, title, price, authors);
+ }
+}
+
+@end
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleDisplayName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIconFile</key>
+ <string></string>
+ <key>CFBundleIdentifier</key>
+ <string>com.yourcompany.${PRODUCT_NAME:rfc1034identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>LSRequiresIPhoneOS</key>
+ <true/>
+ <key>UISupportedInterfaceOrientations</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ </array>
+ <key>UISupportedInterfaceOrientations~ipad</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationPortraitUpsideDown</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+</dict>
+</plist>
Oops, something went wrong.

0 comments on commit 3b33548

Please sign in to comment.