Xml parsing in iOS tutorial [closed]
You can parse XML
with below code. But you must need to create classes which you can find below.
NSURL *URL = [[NSURL alloc] initWithString:@"http:/sites.google.com/site/iphonesdktutorials/xml/Books.xml"]; NSString *xmlString = [[NSString alloc] initWithContentsOfURL:URL encoding:NSUTF8StringEncoding error:NULL]; NSLog(@"string: %@", xmlString); NSDictionary *xmlDoc = [NSDictionary dictionaryWithXMLString:xmlString]; NSLog(@"dictionary: %@", xmlDoc);
You need to create this classes for XML
parsing with name of XMLParser
.
XMLParser.h
//// XMLParser.h////// Copyright 2016 Darshan kunjadiya. All rights reserved.#import <Foundation/Foundation.h>#pragma GCC diagnostic push#pragma GCC diagnostic ignored "-Wobjc-missing-property-synthesis"typedef NS_ENUM(NSInteger, XMLDictionaryAttributesMode){ XMLDictionaryAttributesModePrefixed = 0, //default XMLDictionaryAttributesModeDictionary, XMLDictionaryAttributesModeUnprefixed, XMLDictionaryAttributesModeDiscard};typedef NS_ENUM(NSInteger, XMLDictionaryNodeNameMode){ XMLDictionaryNodeNameModeRootOnly = 0, //default XMLDictionaryNodeNameModeAlways, XMLDictionaryNodeNameModeNever};static NSString *const XMLDictionaryAttributesKey = @"__attributes";static NSString *const XMLDictionaryCommentsKey = @"__comments";static NSString *const XMLDictionaryTextKey = @"__text";static NSString *const XMLDictionaryNodeNameKey = @"__name";static NSString *const XMLDictionaryAttributePrefix = @"_";@interface XMLURLParser : NSObject <NSCopying>+ (XMLURLParser *)sharedInstance;@property (nonatomic, assign) BOOL collapseTextNodes; // defaults to YES@property (nonatomic, assign) BOOL stripEmptyNodes; // defaults to YES@property (nonatomic, assign) BOOL trimWhiteSpace; // defaults to YES@property (nonatomic, assign) BOOL alwaysUseArrays; // defaults to NO@property (nonatomic, assign) BOOL preserveComments; // defaults to NO@property (nonatomic, assign) BOOL wrapRootNode; // defaults to NO@property (nonatomic, assign) XMLDictionaryAttributesMode attributesMode;@property (nonatomic, assign) XMLDictionaryNodeNameMode nodeNameMode;- (NSDictionary *)dictionaryWithParser:(NSXMLParser *)parser;- (NSDictionary *)dictionaryWithData:(NSData *)data;- (NSDictionary *)dictionaryWithString:(NSString *)string;- (NSDictionary *)dictionaryWithFile:(NSString *)path;@end@interface NSDictionary (XMLParser)+ (NSDictionary *)dictionaryWithXMLParser:(NSXMLParser *)parser;+ (NSDictionary *)dictionaryWithXMLData:(NSData *)data;+ (NSDictionary *)dictionaryWithXMLString:(NSString *)string;+ (NSDictionary *)dictionaryWithXMLFile:(NSString *)path;- (NSDictionary *)attributes;- (NSDictionary *)childNodes;- (NSArray *)comments;- (NSString *)nodeName;- (NSString *)innerText;- (NSString *)innerXML;- (NSString *)XMLString;- (NSArray *)arrayValueForKeyPath:(NSString *)keyPath;- (NSString *)stringValueForKeyPath:(NSString *)keyPath;- (NSDictionary *)dictionaryValueForKeyPath:(NSString *)keyPath;@end@interface NSString (XMLParser)- (NSString *)XMLEncodedString;@end#pragma GCC diagnostic pop
XMLParser.m
//// XMLParser.m////// Copyright 2016 Darshan kunjadiya. All rights reserved.#import "XMLParser.h"#pragma GCC diagnostic ignored "-Wobjc-missing-property-synthesis"#pragma GCC diagnostic ignored "-Wdirect-ivar-access"#pragma GCC diagnostic ignored "-Wformat-non-iso"#pragma GCC diagnostic ignored "-Wgnu"#import <Availability.h>#if !__has_feature(objc_arc)#error This class requires automatic reference counting#endif@interface XMLURLParser () <NSXMLParserDelegate>@property (nonatomic, strong) NSMutableDictionary *root;@property (nonatomic, strong) NSMutableArray *stack;@property (nonatomic, strong) NSMutableString *text;@end@implementation XMLURLParser+ (XMLURLParser *)sharedInstance{ static dispatch_once_t once; static XMLURLParser *sharedInstance; dispatch_once(&once, ^{ sharedInstance = [[XMLURLParser alloc] init]; }); return sharedInstance;}- (id)init{ if ((self = [super init])) { _collapseTextNodes = YES; _stripEmptyNodes = YES; _trimWhiteSpace = YES; _alwaysUseArrays = NO; _preserveComments = NO; _wrapRootNode = NO; } return self;}- (id)copyWithZone:(NSZone *)zone{ XMLURLParser *copy = [[[self class] allocWithZone:zone] init]; copy.collapseTextNodes = _collapseTextNodes; copy.stripEmptyNodes = _stripEmptyNodes; copy.trimWhiteSpace = _trimWhiteSpace; copy.alwaysUseArrays = _alwaysUseArrays; copy.preserveComments = _preserveComments; copy.attributesMode = _attributesMode; copy.nodeNameMode = _nodeNameMode; copy.wrapRootNode = _wrapRootNode; return copy;}- (NSDictionary *)dictionaryWithParser:(NSXMLParser *)parser{ [parser setDelegate:self]; [parser parse]; id result = _root; _root = nil; _stack = nil; _text = nil; return result;}- (NSDictionary *)dictionaryWithData:(NSData *)data{ NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data]; return [self dictionaryWithParser:parser];}- (NSDictionary *)dictionaryWithString:(NSString *)string{ NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding]; return [self dictionaryWithData:data];}- (NSDictionary *)dictionaryWithFile:(NSString *)path{ NSData *data = [NSData dataWithContentsOfFile:path]; return [self dictionaryWithData:data];}+ (NSString *)XMLStringForNode:(id)node withNodeName:(NSString *)nodeName{ if ([node isKindOfClass:[NSArray class]]) { NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:[node count]]; for (id individualNode in node) { [nodes addObject:[self XMLStringForNode:individualNode withNodeName:nodeName]]; } return [nodes componentsJoinedByString:@"\n"]; } else if ([node isKindOfClass:[NSDictionary class]]) { NSDictionary *attributes = [(NSDictionary *)node attributes]; NSMutableString *attributeString = [NSMutableString string]; for (NSString *key in [attributes allKeys]) { [attributeString appendFormat:@" %@=\"%@\"", [[key description] XMLEncodedString], [[attributes[key] description] XMLEncodedString]]; } NSString *innerXML = [node innerXML]; if ([innerXML length]) { return [NSString stringWithFormat:@"<%1$@%2$@>%3$@</%1$@>", nodeName, attributeString, innerXML]; } else { return [NSString stringWithFormat:@"<%@%@/>", nodeName, attributeString]; } } else { return [NSString stringWithFormat:@"<%1$@>%2$@</%1$@>", nodeName, [[node description] XMLEncodedString]]; }}- (void)endText{ if (_trimWhiteSpace) { _text = [[_text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] mutableCopy]; } if ([_text length]) { NSMutableDictionary *top = [_stack lastObject]; id existing = top[XMLDictionaryTextKey]; if ([existing isKindOfClass:[NSArray class]]) { [existing addObject:_text]; } else if (existing) { top[XMLDictionaryTextKey] = [@[existing, _text] mutableCopy]; } else { top[XMLDictionaryTextKey] = _text; } } _text = nil;}- (void)addText:(NSString *)text{ if (!_text) { _text = [NSMutableString stringWithString:text]; } else { [_text appendString:text]; }}- (void)parser:(__unused NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(__unused NSString *)namespaceURI qualifiedName:(__unused NSString *)qName attributes:(NSDictionary *)attributeDict{ [self endText]; NSMutableDictionary *node = [NSMutableDictionary dictionary]; switch (_nodeNameMode) { case XMLDictionaryNodeNameModeRootOnly: { if (!_root) { node[XMLDictionaryNodeNameKey] = elementName; } break; } case XMLDictionaryNodeNameModeAlways: { node[XMLDictionaryNodeNameKey] = elementName; break; } case XMLDictionaryNodeNameModeNever: { break; } } if ([attributeDict count]) { switch (_attributesMode) { case XMLDictionaryAttributesModePrefixed: { for (NSString *key in [attributeDict allKeys]) { node[[XMLDictionaryAttributePrefix stringByAppendingString:key]] = attributeDict[key]; } break; } case XMLDictionaryAttributesModeDictionary: { node[XMLDictionaryAttributesKey] = attributeDict; break; } case XMLDictionaryAttributesModeUnprefixed: { [node addEntriesFromDictionary:attributeDict]; break; } case XMLDictionaryAttributesModeDiscard: { break; } } } if (!_root) { _root = node; _stack = [NSMutableArray arrayWithObject:node]; if (_wrapRootNode) { _root = [NSMutableDictionary dictionaryWithObject:_root forKey:elementName]; [_stack insertObject:_root atIndex:0]; } } else { NSMutableDictionary *top = [_stack lastObject]; id existing = top[elementName]; if ([existing isKindOfClass:[NSArray class]]) { [existing addObject:node]; } else if (existing) { top[elementName] = [@[existing, node] mutableCopy]; } else if (_alwaysUseArrays) { top[elementName] = [NSMutableArray arrayWithObject:node]; } else { top[elementName] = node; } [_stack addObject:node]; }}- (NSString *)nameForNode:(NSDictionary *)node inDictionary:(NSDictionary *)dict{ if (node.nodeName) { return node.nodeName; } else { for (NSString *name in dict) { id object = dict[name]; if (object == node) { return name; } else if ([object isKindOfClass:[NSArray class]] && [object containsObject:node]) { return name; } } } return nil;}- (void)parser:(__unused NSXMLParser *)parser didEndElement:(__unused NSString *)elementName namespaceURI:(__unused NSString *)namespaceURI qualifiedName:(__unused NSString *)qName{ [self endText]; NSMutableDictionary *top = [_stack lastObject]; [_stack removeLastObject]; if (!top.attributes && !top.childNodes && !top.comments) { NSMutableDictionary *newTop = [_stack lastObject]; NSString *nodeName = [self nameForNode:top inDictionary:newTop]; if (nodeName) { id parentNode = newTop[nodeName]; if (top.innerText && _collapseTextNodes) { if ([parentNode isKindOfClass:[NSArray class]]) { parentNode[[parentNode count] - 1] = top.innerText; } else { newTop[nodeName] = top.innerText; } } else if (!top.innerText && _stripEmptyNodes) { if ([parentNode isKindOfClass:[NSArray class]]) { [parentNode removeLastObject]; } else { [newTop removeObjectForKey:nodeName]; } } else if (!top.innerText && !_collapseTextNodes && !_stripEmptyNodes) { top[XMLDictionaryTextKey] = @""; } } }}- (void)parser:(__unused NSXMLParser *)parser foundCharacters:(NSString *)string{ [self addText:string];}- (void)parser:(__unused NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock{ [self addText:[[NSString alloc] initWithData:CDATABlock encoding:NSUTF8StringEncoding]];}- (void)parser:(__unused NSXMLParser *)parser foundComment:(NSString *)comment{ if (_preserveComments) { NSMutableDictionary *top = [_stack lastObject]; NSMutableArray *comments = top[XMLDictionaryCommentsKey]; if (!comments) { comments = [@[comment] mutableCopy]; top[XMLDictionaryCommentsKey] = comments; } else { [comments addObject:comment]; } }}@end@implementation NSDictionary(XMLDictionary)+ (NSDictionary *)dictionaryWithXMLParser:(NSXMLParser *)parser{ return [[[XMLURLParser sharedInstance] copy] dictionaryWithParser:parser];}+ (NSDictionary *)dictionaryWithXMLData:(NSData *)data{ return [[[XMLURLParser sharedInstance] copy] dictionaryWithData:data];}+ (NSDictionary *)dictionaryWithXMLString:(NSString *)string{ return [[[XMLURLParser sharedInstance] copy] dictionaryWithString:string];}+ (NSDictionary *)dictionaryWithXMLFile:(NSString *)path{ return [[[XMLURLParser sharedInstance] copy] dictionaryWithFile:path];}- (NSDictionary *)attributes{ NSDictionary *attributes = self[XMLDictionaryAttributesKey]; if (attributes) { return [attributes count]? attributes: nil; } else { NSMutableDictionary *filteredDict = [NSMutableDictionary dictionaryWithDictionary:self]; [filteredDict removeObjectsForKeys:@[XMLDictionaryCommentsKey, XMLDictionaryTextKey, XMLDictionaryNodeNameKey]]; for (NSString *key in [filteredDict allKeys]) { [filteredDict removeObjectForKey:key]; if ([key hasPrefix:XMLDictionaryAttributePrefix]) { filteredDict[[key substringFromIndex:[XMLDictionaryAttributePrefix length]]] = self[key]; } } return [filteredDict count]? filteredDict: nil; } return nil;}- (NSDictionary *)childNodes{ NSMutableDictionary *filteredDict = [self mutableCopy]; [filteredDict removeObjectsForKeys:@[XMLDictionaryAttributesKey, XMLDictionaryCommentsKey, XMLDictionaryTextKey, XMLDictionaryNodeNameKey]]; for (NSString *key in [filteredDict allKeys]) { if ([key hasPrefix:XMLDictionaryAttributePrefix]) { [filteredDict removeObjectForKey:key]; } } return [filteredDict count]? filteredDict: nil;}- (NSArray *)comments{ return self[XMLDictionaryCommentsKey];}- (NSString *)nodeName{ return self[XMLDictionaryNodeNameKey];}- (id)innerText{ id text = self[XMLDictionaryTextKey]; if ([text isKindOfClass:[NSArray class]]) { return [text componentsJoinedByString:@"\n"]; } else { return text; }}- (NSString *)innerXML{ NSMutableArray *nodes = [NSMutableArray array]; for (NSString *comment in [self comments]) { [nodes addObject:[NSString stringWithFormat:@"<!--%@-->", [comment XMLEncodedString]]]; } NSDictionary *childNodes = [self childNodes]; for (NSString *key in childNodes) { [nodes addObject:[XMLURLParser XMLStringForNode:childNodes[key] withNodeName:key]]; } NSString *text = [self innerText]; if (text) { [nodes addObject:[text XMLEncodedString]]; } return [nodes componentsJoinedByString:@"\n"];}- (NSString *)XMLString{ if ([self count] == 1 && ![self nodeName]) { //ignore outermost dictionary return [self innerXML]; } else { return [XMLURLParser XMLStringForNode:self withNodeName:[self nodeName] ?: @"root"]; }}- (NSArray *)arrayValueForKeyPath:(NSString *)keyPath{ id value = [self valueForKeyPath:keyPath]; if (value && ![value isKindOfClass:[NSArray class]]) { return @[value]; } return value;}- (NSString *)stringValueForKeyPath:(NSString *)keyPath{ id value = [self valueForKeyPath:keyPath]; if ([value isKindOfClass:[NSArray class]]) { value = [value count]? value[0]: nil; } if ([value isKindOfClass:[NSDictionary class]]) { return [(NSDictionary *)value innerText]; } return value;}- (NSDictionary *)dictionaryValueForKeyPath:(NSString *)keyPath{ id value = [self valueForKeyPath:keyPath]; if ([value isKindOfClass:[NSArray class]]) { value = [value count]? value[0]: nil; } if ([value isKindOfClass:[NSString class]]) { return @{XMLDictionaryTextKey: value}; } return value;}@end@implementation NSString (XMLDictionary)- (NSString *)XMLEncodedString{ return [[[[[self stringByReplacingOccurrencesOfString:@"&" withString:@"&"] stringByReplacingOccurrencesOfString:@"<" withString:@"<"] stringByReplacingOccurrencesOfString:@">" withString:@">"] stringByReplacingOccurrencesOfString:@"\"" withString:@"""] stringByReplacingOccurrencesOfString:@"\'" withString:@"'"];}@end
i hope this answer is useful for you.
Use TBXml parser..That is the easiest way and also less time taken to parse a value..U can download TBXMLDemo project on github and to print that instead of label u can use table view cell and make it selection as null.So that it looks simillarly like label.If u need more details comment me,..i'll be helping it..