Search code examples
iosobjective-cxcodexml-parsingnsxmlparser

How to parse multilevel xml in xcode


can you help me with this program i'm trying to parse an xml file with two levels (i don't know the term so i call that way) here's the sample of my xml file

<?xml version="1.0" encoding="UTF-8"?>
<countries>
<country>
    <countryname>Philippines</countryname>
<subsidiaries>
    <subsidiary>
           <name>Sart Philippines Inc.</name>
           <address>Unit 10-A The World Empire Building, 330 Senator Gil Puyat Avenue  Philippines, Philippines</address>
           <phone>+63.2.929</phone>
           <fax>+63.932</fax>
           <email>[email protected]</email>
           <website>http://www.sartorius-mechatronics.com.ph</website>
    </subsidiary>
</subsidiaries>
</country>
<country>
    <countryname>Denmark</countryname>
    <subsidiaries>
        <subsidiary>
           <name>Stedim Nordic A|S</name>
           <address>Hoerskaetten 6d 2630 Taastrup, Denmark</address>
           <phone>+45.7023.4400</phone>
           <fax>+45.4630.4030</fax>
           <email>[email protected]</email>
           <website></website>
        </subsidiary>
        <subsidiary>
           <name>Nordic A|S</name>
           <address>Hoerskaetten 6D 2630 Taastrup, Denmark</address>
           <phone>+45.7523.8700</phone>
           <fax>+45.4130.4020</fax>
           <email>[email protected]</email>
           <website></website>
       </subsidiary>
     </subsidiaries>
   </country>
</countries>

What i was planning to do was you choose a country, then you choose a subsidiary to view it's info. I was able to parse it but i was not able to show the Stedim Nordic A|S subsidiary.

here is my parser class

@implementation Parser

-(id)initParser
{
    if (self == [super init])
    {
        app = (AppDelegate *) [[UIApplication sharedApplication]delegate];
    }
    return self;
}

-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:    (NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
    if ([elementName isEqualToString:@"countries"])
    {
        app.listArray = [[NSMutableArray alloc]init];

    }
  if ([elementName isEqualToString:@"country"])
    {
        theList = [[List alloc]init];

    }

}

-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    if (!currentElementValue)
    {
        currentElementValue = [[NSMutableString alloc]initWithString:string];
    }
    else
    {
        [currentElementValue appendString:string];
    }
}

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

   if ([elementName isEqualToString:@"country"])
    {
        [app.listArray addObject:theList];
    }

    else {

         if ([elementName isEqualToString:@"countryname"]) {
            theList.countryname = currentElementValue;
        }
        if ([elementName isEqualToString:@"name"])
        {
            theList.name = currentElementValue;
        }
        if ([elementName isEqualToString:@"address"])
        {
            theList.address = currentElementValue;
        }
        if ([elementName isEqualToString:@"phone"])
        {
            theList.phone = currentElementValue;
        }
        if ([elementName isEqualToString:@"fax"])
        {
            theList.fax = currentElementValue;
        }
        if ([elementName isEqualToString:@"email"])
        {
            theList.email = currentElementValue;
        }
        if ([elementName isEqualToString:@"website"])
        {
            theList.website = currentElementValue;

      }

       currentElementValue = nil;

    }


}
@end

I can't explain it well but i hope you can help me , if you can send me a link for a tutorial for this kind of issues i would really appreciate it


Solution

  • The issue is because on your second country element there is two subsidiary. So you need to modify your code like:

    You need another NSString for holding the Country Name. Because there is a single Country name element for your two subsidiary.

    NSString *temp = nil;
    
    -(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:    (NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
    {
        if ([elementName isEqualToString:@"countries"])
        {
            app.listArray = [[NSMutableArray alloc]init];
    
        }
        if ([elementName isEqualToString:@"subsidiary"])
        {
            theList = [[List alloc]init];
        }
    }
    
    
    -(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:    (NSString *)namespaceURI qualifiedName:(NSString *)qName
    {
    
       if ([elementName isEqualToString:@"subsidiary"])
        {
            theList.countryname = temp;
            [app.listArray addObject:theList];
        }
        else
        {
    
             if ([elementName isEqualToString:@"countryname"])
             {
                temp = currentElementValue;
             }
            if ([elementName isEqualToString:@"name"])
            {
                theList.name = currentElementValue;
            }
            if ([elementName isEqualToString:@"address"])
            {
                theList.address = currentElementValue;
            }
            if ([elementName isEqualToString:@"phone"])
            {
                theList.phone = currentElementValue;
            }
            if ([elementName isEqualToString:@"fax"])
            {
                theList.fax = currentElementValue;
            }
            if ([elementName isEqualToString:@"email"])
            {
                theList.email = currentElementValue;
            }
            if ([elementName isEqualToString:@"website"])
            {
                theList.website = currentElementValue;
            }
            currentElementValue = nil;
        }
    }