Search code examples
iosnsxmlparser

Parsing an attributed XML on iOS


I'm stuck on parsing an attributed XML on iOS.

XML

    <?xml version="1.0" encoding="UTF-8"?>
<Books>
    <Book id="1">
    <title_1>Circumference</title_1>
    <author>Nicholas Nicastro</author>
    <summary>Eratosthenes and the Ancient Quest to Measure the Globe.</summary>
</Book>
    <Book id="2">
    <title_1>Copernicus Secret</title_1>
    <author>Jack Repcheck</author>
    <summary>How the scientific revolution began</summary>
</Book>
    <Book id="3">
    <title_1>Angels and Demons</title_1>
    <author>Dan Brown</author>
    <summary>Robert Langdon is summoned to a Swiss research facility to analyze a cryptic symbol seared into the chest of a murdered physicist.</summary>
</Book>
    <Book id="4">
    <title_1>Keep the Aspidistra Flying</title_1>
    <author>George Orwell</author>
    <summary>A poignant and ultimately hopeful look at class and society, Keep the Aspidistra Flying pays tribute to the stubborn virtues of ordinary people who keep the aspidistra flying.</summary>
</Book>
</Books>

CODE

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

    if([elementName isEqualToString:@"Books"])
    {
        data_array = [[NSMutableArray alloc] init];
    }
    else if([elementName isEqualToString:@"Book"])
    {

        bookID= [[attributeDict objectForKey:@"id"]integerValue];

        NSLog(@"Reading id value :%d",bookID);


    //NSLog(@"Processing Element: %@",elementName);
    }

}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{


    if(!test_string)
    {
        test_string = [[NSMutableString alloc] initWithString:string];
}
    else
    {
        [test_string appendString:string];
    }
    //NSLog(@"Processing Value: %@",test_string);

}

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

    if([elementName isEqualToString:@"Books"])

        return;

    if ([elementName isEqualToString:@"Book"])
    {
        [data_array addObject:test_string];


    }
   else

    test_string = nil;
        }

If I follow this approach then it skips first book and shows only last three books.

If I put test_string=nil with in if block rather than else then it shows its author name as well

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

    if([elementName isEqualToString:@"Books"])

        return;

    if ([elementName isEqualToString:@"Book"])
    {
        [data_array addObject:test_string];

        test_string = nil;
        // data_array = nil;
    }

        }

Plus I am also getting a few spaces when it shows in my table view.


Solution

  • Change the didStartElement: method like:

    - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
     namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
        attributes:(NSDictionary *)attributeDict {  
    
        if([elementName isEqualToString:@"Books"])
        {
            data_array = [[NSMutableArray alloc] init];
        }
        else if([elementName isEqualToString:@"Book"])
        {
    
            bookID= [[attributeDict objectForKey:@"id"]integerValue];
            test_string = nil;
            NSLog(@"Reading id value :%d",bookID);
    
        }
        else if([elementName isEqualToString:@"title_1"])
        {
           test_string = [[NSMutableString alloc] init];
        }
    }
    

    Change the didEndElement: method like:

    - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
      namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
    
        if([elementName isEqualToString:@"Books"])
    
            return;
    
        if ([elementName isEqualToString:@"title_1"])
        {
            [data_array addObject:test_string];
    
            test_string = nil;
        }
    }