views:

233

answers:

4

I am needing to parse an XML file for my app and I dont have any clue how to do it. I went through one XMLParser tutorial, and it worked fine but the XML file in the tutorial was very simple and my XML file is quite a bit more complex.

here is a snippet of the xml file:

  <?xml version="1.0" encoding="UTF-8"?>
    <digital_tpp cycle="1003" from_edate="0901Z    03/11/10" to_edate="0901Z     04/08/10">
        <state_code ID="AK" state_fullname="Alaska">
            <city_name ID="ADAK ISLAND" volume="AK-1">
                <airport_name ID="ADAK" military="N" apt_ident="ADK" icao_ident="PADK" alnum="1244">
                    <record>
                        <chartseq>10100</chartseq>
                        <chart_code>MIN</chart_code>
                        <chart_name>TAKE-OFF MINIMUMS</chart_name>
                        <useraction></useraction>
                        <pdf_name>AKTO.PDF</pdf_name>
                        <cn_flg>N</cn_flg>
                        <cnsection></cnsection>
                        <cnpage></cnpage>
                        <bvsection>C</bvsection>
                        <bvpage></bvpage>
                        <procuid></procuid>
                        <two_colored>N</two_colored>
                        <civil> </civil>
                        <faanfd15></faanfd15>
                        <faanfd18></faanfd18>
                        <copter></copter>
                    </record>
                    <record>
                        <chartseq>10200</chartseq>
                        <chart_code>MIN</chart_code>
                        <chart_name>ALTERNATE MINIMUMS</chart_name>
                        <useraction></useraction>
                        <pdf_name>AKALT.PDF</pdf_name>
                        <cn_flg>N</cn_flg>
                        <cnsection></cnsection>
                        <cnpage></cnpage>
                        <bvsection>E</bvsection>
                        <bvpage></bvpage>
                        <procuid></procuid>
                        <two_colored>N</two_colored>
                        <civil> </civil>
                        <faanfd15></faanfd15>
                        <faanfd18></faanfd18>
                        <copter></copter>
                    </record>
                </airport_name>
            </city_name>
        </state_code>
    </digital_tpp>

What I'm needing to do is search the XML file for the <...icao_ident> that the user specifies, then create a dictionary containing the <pdf_name> and <chart_name> for each <record> . I will then create a UI that displays the pdf files.

Can someone direct me to a good tutorial or explanation of how XML parser works? Or if I'm going about this the wrong way I'd be open to suggestions too.

(the XML file is about 8MB)

+1  A: 

I suggest you to read the Event-Driven XML Programming Guide for Cocoa. In your specific case, what you need to do is:

  • In the parser:didStartElement: check for the element name: "airport_name", initialize a new array to store all the record elements (or you can define your own data structure to store the record element), a dictionary to store all element in the record, one string variable to store the current text
  • In the parser:foundCharacters: append the string to the current text
  • In the parser:didEndElement: save the dictionary to the array, release the array, save the results.

UPDATED

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

    if ( [elementName isEqualToString:@"airport_name"]) {

        if (!airports)
            airports = [[NSMutableArray alloc] init];
        NSString *str_icao_ident = [attributeDict objectForKey:@"icao_ident"];
        //do something
        return;
    // ... continued ...
}}
sfa
how do I have it find the correct icao_ident attribute in the airport_name element?
Brodie
I edited the answer, tell me if you need more help
sfa
Thanks hoang - i'll try that tonight
Brodie
A: 

You might find that my blog post about wrapping NSXMLParser gives you what you need - and possibly a higher level alternative (my wrapper).

For example, using my technique, you'd write methods like:

-(void) handleElement_chartname: (NSDictionary*) attributes;

Phil Nash
A: 

i know this isn't the best way...

I struggled for 2 days trying to adapt the XML parser to my situation. I couldnt grasp it, probably because I'm just so used to doing this in C# and obj-c is new to me...

So what I did was parsed the whole thing as a string.

I converted the entire XML file to a NSString, then used substringToIndex and substringFromIndex to isolate the section I needed (the airport). I then used the </record> tag to create an array of <records>, then wrote a for loop that took the values I needed out of the each array object just by getting the range of the tags.

Like I said, it was a crazy solution, but I did it all in 26 lines of code and it works great.

NSString *path = [[NSBundle mainBundle] pathForResource:@"dttps" ofType:@"xml"];
NSData *data = [[NSData alloc]initWithContentsOfFile:path];
NSString *xmlString = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];

NSRange range = [xmlString rangeOfString:searchedAirport];
xmlString = [xmlString substringFromIndex:range.location];
range = [xmlString rangeOfString:@"/airport_name"];
xmlString = [xmlString substringToIndex:range.location];

NSMutableArray *chartNames = [[NSMutableArray alloc]initWithCapacity:100] ;
NSMutableArray *pdfNames = [[NSMutableArray alloc]initWithCapacity:100] ;
NSArray *charts = [xmlString componentsSeparatedByString:@"</record>"];

NSString *tempString = [[NSString alloc]initWithFormat:@""];

int chartsCount = [charts count]-1;

int x;
for (x=0; x < chartsCount; x=x+1) {

    tempString = [charts objectAtIndex:x];
    range = [tempString rangeOfString:@"<chart_name>"];

    tempString = [tempString substringFromIndex:range.location+12];
    range = [tempString rangeOfString:@"</chart_name>"];
    tempString = [tempString substringToIndex:range.location];

    [chartNames addObject:tempString];

    tempString = [charts objectAtIndex:x];
    range = [tempString rangeOfString:@"<pdf_name>"];
    tempString = [tempString substringFromIndex:range.location+10];
    range = [tempString rangeOfString:@"</pdf_name>"];
    tempString = [tempString substringToIndex:range.location-4];
    [pdfNames addObject:tempString];


}

followed by cleanup...

Brodie
A: 

The default XML parsing on the iPhone is pretty tragic compared with contemporary scripting languages. If you are doing serious parsing with complex objects with multiple levels of child objects, then god help you with NSXMLParser.

I would recommend checking out TouchXML which offers a much more civilized solution that is closer to what you might see in a language like Python or Actionscript in terms of its implementation within your own source.

Jasconius
i will look at that. I think that was part of my problem, it is a very complex XML file. Nothing like the sample xml files I found in the tutorial I tried.
Brodie