2012-07-04 6 views
15

こんにちは私はserver.IのXMLファイルからラベルの値を印刷しなければならないアプリケーションを作成しています。 。私のアプリでxml解析を統合するために使用される簡単なチュートリアルやサンプルコードを知っている人はいませんか?iOSチュートリアルでXmlを解析する

+0

http://developer.apple.com/library/ios/#samplecode/XMLPerformance/Introduction/Intro.html#//apple_ref/doc/uid/DTS40008094このサンプルコードが役に立ちますようお願いいたします。 – Neo

答えて

5

TBXmlパーサーを使用する。これは最も簡単な方法で、値を解析する時間も短縮されます。githubでTBXMLDemoプロジェクトをダウンロードして、ラベルの代わりにそれを印刷して、テーブルビューのセルを使用してそれで、ラベルのように見えます。もっと詳しく知りたいのなら、私はそれを助けるでしょう。

19

以下のコードでXMLを解析できます。しかし、以下で見つけることができるクラスを作成する必要があります。

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); 

あなたはXMLXMLParserの名前で解析するために、このクラスを作成する必要があります。

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:@"<%[email protected]%[email protected]>%[email protected]</%[email protected]>", nodeName, attributeString, innerXML]; 
     } 
     else 
     { 
      return [NSString stringWithFormat:@"<%@%@/>", nodeName, attributeString]; 
     } 
    } 
    else 
    { 
     return [NSString stringWithFormat:@"<%[email protected]>%[email protected]</%[email protected]>", 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:@"&amp;"] 
       stringByReplacingOccurrencesOfString:@"<" withString:@"&lt;"] 
       stringByReplacingOccurrencesOfString:@">" withString:@"&gt;"] 
      stringByReplacingOccurrencesOfString:@"\"" withString:@"&quot;"] 
      stringByReplacingOccurrencesOfString:@"\'" withString:@"&apos;"]; 
} 

@end 

私はこの答えはあなたのために有用であると思います。

+0

これは、辞書の配列があるときに問題を引き起こします。 – DivineDesert

+2

これは、ARCベースのコーディングで多くの問題を引き起こします!修理する! –

+0

@JayprakashDubey大丈夫です。この回答を確認して更新します。 –