XML解析,加入iOS中的元素

时间:2013-09-07 12:04:11

标签: ios objective-c xml xml-parsing nsxmlparser

我一直试图弄清楚这一点,但无法解决这个问题。希望这里有人会有一个想法。

我有一些我正在解析的XML数据,它看起来像:

    <Name>MAC 101</Name>
    <Modes>
        <Mode>
            <Name>Basic RGB</Name>
            <ChannelCount>8</ChannelCount>
        </Mode>
        <Mode>
            <Name>Raw RGB</Name>
            <ChannelCount>12</ChannelCount>
        </Mode>
    </Modes>

我正在做的是将信息保存到SQLite数据库,但是我需要先将一些信息组合成1个字符串。我需要字符串看起来像:(使用换行符)

8基本RGB
12原始RGB

然而,有时会有多个“模式”,这个例子只有2个,有时它可能是十几个或更多。

我正在使用的当前代码是NSXMLParser:

-(void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if (isStatus) {
    if ([elementName isEqualToString:@"Name"]) {
        CurrentFixture.Title = currentNodeContent;
        NSLog(@"Name: %@",currentNodeContent);
    }
    if ([elementName isEqualToString:@"Name"]) {
        CurrentFixture.ModeName = currentNodeContent;
        NSLog(@"Mode Name: %@",currentNodeContent);
    }
    if ([elementName isEqualToString:@"ChannelCount"]) {
        CurrentFixture.ChannelCount = currentNodeContent;
        NSLog(@"Channel Count: %@",currentNodeContent);
    }
}
 if ([elementName isEqualToString:@"Fixture"]) {
    NSLog(@"Do something with data.");
    [self.data addObject:CurrentFixture];
    NSLog(@"Data: %@",);
    CurrentFixture = nil;
    currentNodeContent = nil;
    }
}

模式名称将改变标签,因此它不会与实际名称混淆,但目前我只需要一些工作。 任何建议或指导将不胜感激。 谢谢 安德鲁

2 个答案:

答案 0 :(得分:0)

完成所有解析后,您会想要一个函数。它看起来不像你给了我们整个XML文件,但我假设你的外部标签是<Fixtures>而你的内部标签是<Fixture>。不考虑这个假设,您可以在parser:didEndElement:

中添加一个支票
-(void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
    //...

    if ([elementName isEqualToString:@"Fixtures"]) {
        [self saveModesToDatabase];
    }
}

-(void) saveModesToDatabase {
    NSString* allModes = @"";
    for (Fixture* aFixture in self.data) {
        NSString* modeString = [aFixture.ChannelCount stringByAppendingFormat:@" %@", aFixture.Title];

        // Don't add a line break if it's the last object
        if (aFixture == [self.data lastObject])
            allModes = [allModes stringByAppendingFormat:@"%@", modeString];
        else
            allModes = [allModes stringByAppendingFormat:@"%@\n", modeString];
    }

    // Save allModes to database
}

答案 1 :(得分:0)

你需要

  • 用于跟踪所有模式的数组,例如modesArray;

  • 用于跟踪您的模式“ChannelCountName的对象词典,例如modeDictionary;以及

  • 和一些BOOL变量让您知道您是否正在解析模式数组(最重要的是,您可以区分Name中的Mode和较高级Name,例如parsingModes

然后,您可以

  • 启动模式时,初始化阵列;

  • 当您开始Mode时,请初始化词典;

  • 完成NameChannelCount后,请更新模式字典;

  • 完成Mode后,您可以将这两个值连接成一个字符串,并将该字符串添加到数组中;

  • 完成Modes后,您可以使用换行符加入Mode数组中的所有字符串。

因此产生类似的东西:

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
    if ([elementName isEqualToString:@"Fixture"])
    {
        currentFixture = [[Fixture alloc] init];
    }
    else if ([elementName isEqualToString:@"Modes"])
    {
        modesArray = [NSMutableArray array];
        parsingModes = YES;
    }
    else if ([elementName isEqualToString:@"Mode"])
    {
        modeDictionary = [NSMutableDictionary dictionary];
    }
    else
    {
        currentNodeContent = [NSMutableString string];
    }
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    [currentNodeContent appendString:string];
}

-(void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
    if (parsingModes)
    {
        if ([elementName isEqualToString:@"Name"]) {
            modeDictionary[@"Name"] = currentNodeContent;
        }
        else if ([elementName isEqualToString:@"ChannelCount"]) {
            modeDictionary[@"ChannelCount"] = currentNodeContent;
        }
        else if ([elementName isEqualToString:@"Mode"]) {
            [modesArray addObject:[NSString stringWithFormat:@"%@ %@", modeDictionary[@"ChannelCount"], modeDictionary[@"Name"]]];
            modeDictionary = nil;
        }
        else if ([elementName isEqualToString:@"Modes"]) {
            currentFixture.longStringWithModes = [modesArray componentsJoinedByString:@"\n"];
            modesArray = nil;
            parsingModes = NO;
        }
    }
    else
    {
        if ([elementName isEqualToString:@"Name"]) {
            currentFixture.title = currentNodeContent;
        }
    }

    // carry on with your other elements

    currentNodeContent = nil;
}

(注意我转移到了camelCase。)

告诉你如何做到这一点,我建议不要这样做。数据库最好将数据保存在单独的字段中。将所有内容连接成单个字符串可能是您在UI中执行的操作,但数据库可能应该反映基础数据结构。话虽如此,由于每个灯具有多个Mode条目,这意味着您可能有一个单独的表格。