解析具有相同标记的XML文件

时间:2012-10-18 09:25:00

标签: iphone objective-c ios xml xcode

我有一个需要解析的XML文件。 我以前解析过一个XML,但它更简单。因为这个文件有类似的标签,所以我无法弄清楚如何解析它。

xml文件如下所示:

<resource classname="Quote">
<field name="name">USD/KRW</field>
<field name="price">1104.319946</field>
<field name="symbol">KRW=X</field>
<field name="ts">1350544190</field>
<field name="type">currency</field>
<field name="utctime">2012-10-18T07:09:50+0000</field>
<field name="volume">-56144</field>
</resource>

我想获取价格字段并将其添加到数组中。我在一些在线示例中尝试了以下代码,但它显示了所有字段的值,而我只想要price字段。

- (void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementname namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{

    if ([[attributeDict objectForKey:@"name"] isEqualToString:@"price"])
    {

        currencyValuesString = [[NSMutableString alloc]init];
    }

}


- (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementname namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
    if ([elementname isEqualToString:@"field"]) 
    {
        [currencyValuesArray addObject:currencyValuesString];
    }
}

- (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    currencyValuesString = (NSMutableString *) [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}

2 个答案:

答案 0 :(得分:2)

您的代码存在多个问题:

  • 当您输入currencyValuesString标签时,您会分配/初始化<field name="price">,但是您永远不会释放它(如果您不使用ARC,它会泄漏),更重要的是您不使用此分配例如,因为在-parser:foundCharacters:中,使用不同的字符串替换此变量的值。
  • 因此先前分配的NSMutableString完全没用。而且,如果您的字段包含多个文本而不是一个文本(例如<field name="price">1.234<b>€</b></field>),-parser:foundCharacters:将被多次调用,但您的代码将始终丢弃先前的值并仅保留最后一个块而不是将它们添加到NSMutableString
  • 事实上,使用您的代码没有任何意义NSMutableString,因为您不将它用作可变字符串,而只是每次都用新的值替换每个值而不是附加它。

但是,每当您遇到结束</field>标记时,无论此标记是什么,您都会执行[currencyValuesArray addObject:currencyValuesString];但不会释放currencyValuesString(只有在您使用时才会有效) ARC,但如果你使用手动参考计数会泄漏),更重要的是你会将这个字符串添加到数组每次你遇到结束</field>标记,无论name是什么开头标签是。因此,您需要在价格之后将</field>结束标记的次数添加到数组中。

所以正确的方法是:

  • 将foundCharacters附加到NSMutableString而不是替换它
  • 当您遇到结束标记时,请将价格添加到数组中,然后释放并立即将价格字符串设置回nil。这样currencyValuesString只会在<field name="price">开始标记与其对应的</field>结束标记之间,而不是在解析其他<field>标记时
  • 如果currencyValuesString不是nil
  • ,则只在结束标记中为您的数组添加价格

- (void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementname namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
    if ([[attributeDict objectForKey:@"name"] isEqualToString:@"price"])
    {
        currencyValuesString = [[NSMutableString alloc]init];
    }
}

- (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    [currencyValuesString appendString:[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];
}

- (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementname namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
    if ([elementname isEqualToString:@"field"] && (currencyValuesString != nil)) 
    {
        [currencyValuesArray addObject:currencyValuesString];
        [currencyValuesString release]; // Only needed if not using ARC. Remove this line if you use ARC
        currencyValuesString = nil; // so that the next closing tag won't readd the price
    }
}

答案 1 :(得分:-1)

试试这个:

in .h

NSXMLParser * rssParser;

NSDictionary * myAttrDict;

NSString * currentElement;

NSMutableArray * prizeArr;

in .m:

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
    if([elementName isEqualToString:@"field"])
    {        
        if([[attributeDict objectForKey:@"name"] isEqualToString:@"price"])
        {
            currentElement = @"price";
        }
        else{
            currentElement = nil;
        }
    }
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    if([currentElement isEqualToString:@"price"])
    {
        [prizeArr addObject:string];
    }
    NSLog(@"prizeArr :%@",prizeArr);
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
    {
    }

- (void)parserDidEndDocument:(NSXMLParser *)parser
{
}