Я реализовал достаточно эффективный синтаксический анализатор XML-to- NSDictionary
.Вы можете вернуть его как NSMutableDictionary
, если хотите.В настоящее время у меня нет github или чего-либо еще, поэтому я выложу код здесь.Он использует библиотеку синтаксического анализа XML TBXML
(без поддержки XPath и синтаксического анализа только для чтения, но достаточно эффективный и высокоуровневый).
РЕДАКТИРОВАТЬ: Я только что понял, что мой парсер был создан для синтаксического анализа имен элементов и текста внутри элементов, но не для элементов атрибутов , как выстроен ваш набор данных XML.К сожалению, приведенный ниже код не будет анализировать атрибуты.Хотя у вас есть отправная точка, вы можете изменить код, который использует ->firstChild
и ->nextSibling
для чтения атрибутов.
XML.h
@interface XML : NSObject
/**
* Constructs an NSDictionary from the provided XML tree.
*
* Uses the default prefix of 'config'.
*/
+ (NSDictionary *)dictionaryForXMLTree:(TBXMLElement *)tree;
/**
* Constructs an NSDictionary from the provided XML tree.
*
* The format of the dictionary keys is:
* section/[subsection/.../]optionName
*/
+ (NSDictionary *)dictionaryForXMLTree:(TBXMLElement *)tree
withPrefix:(NSString *)keyPrefix;
/**
* Iteratively parses configuration areas from the provided XML document.
*
* If an 'list' area is encountered, its immediate children are added to
* the dictionary as a numbered list (i.e list/1/..., list/2/...).
*/
+ (NSDictionary *)dictionaryFromXML:(TBXML *)xmlDoc;
@end
XML.m
NSString *stripHTML(const char* xmlString);
NSString* stripHTML(const char* xmlString)
{
return [[[NSString stringWithUTF8String:xmlString]
stringByReplacingOccurrencesOfString:@"&"
withString:@"&"]
stringByReplacingOccurrencesOfString:@" "
withString:@""];
}
@implementation XML
@synthesize configDict;
#pragma mark - XML parsing
+ (NSDictionary *)itemisedDictionaryForXMLTree:(TBXMLElement *)tree
withPrefix:(NSString *)keyPrefix
{
NSMutableDictionary *returnValues =
[[NSMutableDictionary alloc] init];
NSUInteger itemNumber = 1;
for (TBXMLElement *option = tree->firstChild;
option != nil;
option = option->nextSibling)
{
if(option->text == NULL)
option->text = "";
NSString *childPrefix = [NSString stringWithFormat:@"%@/%u",
keyPrefix, itemNumber++];
[returnValues setObject:stripHTML(option->text)
forKey:childPrefix];
[returnValues addEntriesFromDictionary:
[self dictionaryForXMLTree:option withPrefix:childPrefix]];
}
return [returnValues autorelease];
}
+ (NSDictionary *)dictionaryForXMLTree:(TBXMLElement *)tree
withPrefix:(NSString *)keyPrefix
{
NSMutableDictionary *returnValues =
[[NSMutableDictionary alloc] init];
for (TBXMLElement *option = tree->firstChild;
option != nil;
option = option->nextSibling)
{
if(option->text == NULL)
option->text = "";
NSString *childPrefix = [NSString stringWithFormat:@"%@/%s",
keyPrefix,
option->name];
[returnValues setObject:stripHTML(option->text)
forKey:childPrefix];
[returnValues addEntriesFromDictionary:
[self dictionaryForXMLTree:option withPrefix:childPrefix]];
}
return [returnValues autorelease];
}
+ (NSDictionary *)dictionaryForXMLTree:(TBXMLElement *)tree
{
return [self dictionaryForXMLTree:tree withPrefix:@"config"];
}
+ (NSDictionary *)dictionaryFromXML:(TBXML *)xmlDoc
{
NSMutableDictionary *config = [[NSMutableDictionary alloc] init];
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
TBXMLElement *rootElement = [xmlDoc rootXMLElement];
if(rootElement != nil)
{
for(TBXMLElement *configArea = rootElement->firstChild;
configArea != nil;
configArea = configArea->nextSibling)
{
NSString *areaName = [NSString stringWithFormat:@"%s",
configArea->name];
if([areaName
isEqualToString:@"list"]) // multiple children with the same name
{
[config addEntriesFromDictionary:
[self itemisedDictionaryForXMLTree:configArea
withPrefix:areaName]];
} else {
[config addEntriesFromDictionary:
[self dictionaryForXMLTree:configArea
withPrefix:areaName]];
}
}
}
[pool release];
return [config autorelease];
}
+ (NSDictionary *)fetchConfig:(NSURL *)atURL
{
TBXML *xmlDoc = [TBXML tbxmlWithURL:atURL];
return [XML dictionaryFromXML:xmlDoc];
}
+ (NSDictionary *)parseConfigFromXMLString:(NSString *)xmlString
{
TBXML *xmlDoc = [TBXML tbxmlWithXMLString:xmlString];
return [XML dictionaryFromXML:xmlDoc];
}