наиболее эффективный способ синтаксического анализа XML с NSXMLParser - PullRequest
1 голос
/ 11 октября 2011

Я пытаюсь выяснить лучший подход к анализу больших наборов данных xml с делегатом xmlparser .. (в основном, какого черта я помещаю данные?)

данные 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 Ответ

2 голосов
/ 11 октября 2011

Я реализовал достаточно эффективный синтаксический анализатор 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:@"&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];
}
...