Разбор Xml в учебнике iOS

Привет, я создаю приложение, которое должно печатать значение в ярлыке из XML файла на сервере. Я пробовал читать некоторую документацию под поиском google.. но я не могу ее найти... Кто-нибудь знает простой учебник или любой пример кода, который используется для интеграции анализа XML в моем приложении.

2 ответа

Использовать синтаксический анализатор TBXml. Это самый простой способ, а также меньше времени для анализа значения. Можно загрузить проект TBXMLDemo на github и напечатать, что вместо метки u вы можете использовать ячейку просмотра таблицы и сделать ее выборкой как null.Таким образом, она выглядит похожей на метку. Если вам нужна дополнительная информация, комментируйте меня, я буду помогать ей.


Вы можете проанализировать 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);

Вам нужно создать эти классы для разбора XML с именем 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
</nscopying></foundation>

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
</nsxmlparserdelegate></availability.h>

Я надеюсь, что этот ответ будет полезен для вас.

licensed under cc by-sa 3.0 with attribution.