使用NSXMLParser解析XML的最有效方法

时间:2011-10-11 03:21:09

标签: iphone ios uitableview nsxmlparser

我试图找出使用xmlparser委托解析xml的大型数据集的最佳方法..(基本上我将数据放入了什么?)

xml数据将如下所示。

<Rows>
<Row ID="76" MANF="JARD" ISMANUF="F" ISSER="F"/>
<Row ID="38" MANF ="SANBIN" ISMANUF ="F" ISSER ="T"/>
<Rows>

我正在寻找高水平的回复,所以我可以离开并做更多的研究,因为他们显然有几种不同的方式来解决这个问题。我想知道最好/最有效的存储数据来自NSXMLParser,也想要我能够缓存的东西......

到目前为止,我一直在关注NSMutabledictionarys但是听说过这可能不太可能,所以我现在开始考虑创建自己的对象..但是从我的解析委托返回的数据只与字符串兼容..所以如果我有一个bool值我不能把它放进我的对象..任何帮助都会非常感激,因为我有点不知所措。

1 个答案:

答案 0 :(得分:2)

我已经实现了一个足够有效的XML-to-NSDictionary解析器。如果您愿意,可以将其作为NSMutableDictionary返回。我目前没有github或其他任何东西,所以我会在这里发布代码内联。它使用了TBXML XML解析库(没有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:@"&amp;"
      withString:@"&"]
     stringByReplacingOccurrencesOfString:@"&#13;"
            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];
}