I am having an XML file which needs to be parsed. I have parse an XML before but it was simpler. Because this file has similar tags, I am not able to figure out how to parse it.
The xml file looks like this:
<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>
I want to get the price field and add it to an array. I tried the code below from some online examples but it's showing all field's values and I want only the price
field.
- (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]];
}
There is multiple problems with your code:
currencyValuesString
when you enter your <field name="price">
tag, but you never release it (which will leak if you are not using ARC), and more importantly you don't use this allocated instance, because in your -parser:foundCharacters:
you replace the value of this variable with a different string. NSMutableString
is totally useless. And moreover, in case your fields would contain multiple chucks of text instead of one ( <field name="price">1.234<b>€</b></field>
for example), -parser:foundCharacters:
would be called multiple times, but your code will always throw away the previous value and keep only the last chunk instead of adding them to the NSMutableString
. NSMutableString
as you don't use it as a mutable string but simply replace each value with a new one each time instead of appending it. But also, each time you encounter a closing </field>
tag, whatever this tag is, you perform [currencyValuesArray addObject:currencyValuesString];
but don't release the currencyValuesString
(which is fine only if you use ARC, but will leak if you use Manual Reference Counting) and more importantly you will add this string to the array each time you encounter the closing </field>
tag, whatever the name
of the opening tag was. So you will add the price to your array as many times as you have </field>
closing tags after your price.
So the right approach would be to:
NSMutableString
instead of replacing it nil
immediately. This way the currencyValuesString
will only be around between the <field name="price">
opening tag and its corresponding </field>
closing tag, and not when parsing the other <field>
tags currencyValuesString
is not 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
}
}
try this :
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
{
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.