2010-04-19 87 views
0

我需要解析我的應用程序的XML文件,我沒有任何線索如何做到這一點。我經歷了一個XMLParser教程,它運行良好,但教程中的XML文件非常簡單,我的XML文件比較複雜。iPhone XMLParser幫助

這裏是xml文件的一個片段:

<?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> 

什麼,我需要做的是搜索與用戶指定的<...icao_ident> XML文件,然後創建一個包含了<pdf_name><chart_name>字典每個<record>。然後,我將創建一個顯示PDF文件的UI。

有人可以指導我一個很好的教程或XML解析器如何工作的解釋嗎?或者,如果我以這種錯誤的方式開展工作,我也會接受建議。

(XML文件約8MB)

回答

1

我知道這是不是最好的辦法...

我奮鬥2天努力使XML解析器適應我的情況。我不能理解它,可能是因爲我只是習慣於在C#中做這件事,obj-c對我來說是新的...

所以我所做的就是將整個事情解析爲一個字符串。

我將整個XML文件轉換爲NSString,然後使用substringToIndex和substringFromIndex來隔離我需要的部分(機場)。然後,我使用</record>標籤創建了一個<records>的數組,然後編寫了一個for循環,通過獲取標籤的範圍,從每個數組對象中提取所需的值。

就像我說的那樣,這是一個瘋狂的解決方案,但是我在26行代碼中完成了所有工作,並且效果很好。

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]; 


} 

隨後清理...

1

我建議你閱讀Event-Driven XML Programming Guide for Cocoa。在特定情況下,你需要做的是:

  • 在解析器:didStartElement:檢查元素名稱:「AIRPORT_NAME」,初始化一個新的陣列來存儲所有的記錄元素(或者你也可以定義自己的數據結構來存儲該記錄元件),詞典存儲在所述記錄中的所有元件,一個字符串變量來存儲當前的文本
  • 在解析器:foundCharacters:字符串附加到當前文本
  • 在解析器:didEndElement:將字典保存到數組,釋放數組,保存結果。

修訂

- (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 ... 
}} 
+0

我該如何在airport_name元素中找到正確的icao_ident屬性? – Brodie 2010-04-20 01:44:16

+0

我編輯了答案,告訴我你是否需要更多幫助 – 2010-04-20 08:56:58

+0

謝謝hoang - 我今晚會試試 – Brodie 2010-04-20 15:57:31

2

你可能會發現,my blog post about wrapping NSXMLParser爲您提供您所需要的 - 和可能更高水平的替代(我的包裝)。

例如,使用我的技術,你會寫這樣的方法:

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

+0

該死的對那些if語句來說是一個很好的解決方案(除了下劃線,但這是一個偏好的事情)。剛好足夠的元編程以避免惱人的if-else塊。太好了!它仍然是一個連續的解析器,但由於某種原因,我們忍受了在其他平臺上我們在DECADES中無法忍受的iOS上的事情,但我認爲創建一個類似DOM的解析器是很容易的(並且全部弄錯了)。 – 2011-01-11 20:33:00

0

與當代腳本語言相比,iPhone上默認的XML解析非常悲慘。如果您正在使用具有多級子對象的複雜對象進行嚴重解析,那麼上帝可以幫助您使用NSXMLParser。

我會推薦檢查一下TouchXML,它提供了一個更加文明的解決方案,它更接近您可能在Python或Actionscript語言中看到的在您的源代碼中實現的方面。

+0

我會看看那個。我認爲這是我的問題的一部分,它是一個非常複雜的XML文件。沒有什麼比我在我嘗試的教程中找到的示例xml文件。 – Brodie 2010-04-21 04:31:25