2013-03-14 121 views
0

我目前正在開發一個用於顯示一些信息的iOS應用程序(target = iPod touch),這些信息基於PostgreSQL數據庫,我是一個非常初學者。我做了大量的研究,但是我什麼也沒找到,這確實有助於解決我的問題。NSXML解析器返回空白結果

目前我從一個php文件獲取數據,這是iOS應用程序和數據庫之間的「橋樑」。爲此,我使用一個http請求來詢問php文件中xml格式的數據。在我使用的php文件裏面

SELECT query_to_xml('".$queryString."', false, true, '') as xml 

得到一個xml文件作爲回報。

到目前爲止,一切正常,所以我有一個字符串變量與我的iOS應用程序中可用查詢的xml結果。

這就是我得到:

<row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 

    <id>4</id> 
    <invnr>61821B741AEBI8</invnr> 
    <art>c</art> 
    <type_id>2</type_id> 
    <rechnung></rechnung> 
    <standort>G01E01R01</standort> 
    <erstellt>2011-12-06</erstellt> 
    <gekauft>2003-01-01</gekauft> 
</row> 

在Objective-C我想有兩個數組:

字幕陣列

第一陣列應該保持字幕從xml文件(id,invnr,art,type_id,rechnung,standort,erstellt,gekauft)。條目「行」不應該在數組內。

值陣列

第二個數組應該只保存值 - 也與空粒。在該示例中這將是4,61821B741AEBI8,C,2,...,G01E01R01,2011-12-06,2003-01-01

使用NSXML解析器

這是配置,我使用目前用於解析xml並將數據保存到數組中。

分析器didStartElement

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

    element = [[NSMutableString alloc] init]; 

    if(!dataCaptions){ 
     dataCaptions = [[NSMutableArray alloc]init]; 
    } 

    if([elementName isEqualToString:@"id"] || 
    [elementName isEqualToString:@"invnr"] || 
    [elementName isEqualToString:@"art"] || 
    [elementName isEqualToString:@"type_id"] || 
    [elementName isEqualToString:@"rechnung"] || 
    [elementName isEqualToString:@"standort"] || 
    [elementName isEqualToString:@"erstellt"] || 
    [elementName isEqualToString:@"gekauft"]){ 

    [element setString:elementName]; 
    [dataCaptions addObject:elementName]; 
    } 
} 

分析器foundCharacters

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

    if(!dataValues){ 
     dataValues = [[NSMutableArray alloc]init]; 
    } 

    BOOL copy; 

    if([element isEqualToString:@"id"] || 
     [element isEqualToString:@"invnr"] || 
     [element isEqualToString:@"art"] || 
     [element isEqualToString:@"type_id"] || 
     [element isEqualToString:@"rechnung"]|| 
     [element isEqualToString:@"standort"] || 
     [element isEqualToString:@"erstellt"] || 
     [element isEqualToString:@"gekauft"]){ 

     copy = YES; 

    }else{ 
     copy = NO; 
    } 

    if(copy){ 
     [dataValues addObject:string]; 
     NSLog(@"Found: %@ with value: %@", element, string); 

    } 
} 

分析器didEndElement

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

} 

輸出和問題

問題是解析器似乎通過一個元素多次。這導致我的值數組看起來像這樣:

2013-03-14 12:54:54.591 BarcodeScanner[582:907] Array Values(
    4, 
    "\n ", 
    61821B741AEBI8, 
    "\n ", 
    c, 
    "\n ", 
    2, 
    "\n ", 
    "\n ", 
    G01E01R01, 
    "\n ", 
    "2011-12-06", 
    "\n ", 
    "2003-01-01", 
    "\n" 
) 

輸出也有點複雜。是我的錯,解析器首先採用起始xml標籤,例如。 (Parser didStartElement),比讀取值4(Parser foundCharacters)和至少讀取(Parser didEndElement)?

我希望有人能夠幫助解決這個問題。 感謝和最誠摯greetings-托比亞斯

2013-03-14 12:54:54.423 BarcodeScanner[582:907] Found: id with value: 4 
2013-03-14 12:54:54.425 BarcodeScanner[582:907] Found: id with value: 

2013-03-14 12:54:54.426 BarcodeScanner[582:907] Found: invnr with value: 61821B741AEBI8 
2013-03-14 12:54:54.428 BarcodeScanner[582:907] Found: invnr with value: 

2013-03-14 12:54:54.430 BarcodeScanner[582:907] Found: art with value: c 
2013-03-14 12:54:54.432 BarcodeScanner[582:907] Found: art with value: 

2013-03-14 12:54:54.444 BarcodeScanner[582:907] Found: type_id with value: 2 
2013-03-14 12:54:54.446 BarcodeScanner[582:907] Found: type_id with value: 

2013-03-14 12:54:54.448 BarcodeScanner[582:907] Found: rechnung with value: 

2013-03-14 12:54:54.450 BarcodeScanner[582:907] Found: standort with value: G01E01R01 
2013-03-14 12:54:54.451 BarcodeScanner[582:907] Found: standort with value: 

2013-03-14 12:54:54.454 BarcodeScanner[582:907] Found: erstellt with value: 2011-12-06 
2013-03-14 12:54:54.456 BarcodeScanner[582:907] Found: erstellt with value: 

2013-03-14 12:54:54.461 BarcodeScanner[582:907] Found: gekauft with value: 2003-01-01 
2013-03-14 12:54:54.464 BarcodeScanner[582:907] Found: gekauft with value: 

回答

0

你是正確的,你需要實現didStartElementfoundCharactersdidEndElement。你也正確地認爲foundCharacters將在處理給定元素的過程中被多次調用,所以你需要通過字符附加到一個字符串來處理,而不是每次都創建一個新的獨立字符串。或者,正如蘋果所說的那樣在docs

解析器對象可以發送委託幾個 解析器:foundCharacters:消息,報告的 元素的字符。因爲字符串可能只是當前元素的總字符內容的一部分,所以您應該將其附加到字符當前的 堆積中,直到元素更改。

作爲一個例子,下面是我從當前項目中完成的一個簡單工作解析器的完整實現。注意多麼簡單foundCharacters是 - 你需要的所有基層要做的就是繼續追加字符的字符串,直到didEndElement被稱爲(那麼你可以在didEndElement清除它,然後再次啓動附加處理):

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

    if([elementName isEqualToString:@"device"]){ 
     self.currentDeviceID = [[SRDeviceID alloc]init]; 
    } 
} 

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

    if([elementName isEqualToString:@"deviceList"]){ 
     [self.pairingTableView reloadData]; 
    } 

    if([elementName isEqualToString:@"device"]){ 
     [self.deviceIDListFromServer addObject:self.currentDeviceID]; 
    } 

    //The accumulation of characters for the current element is complete, 
    //so we can tidy up the string and use the result: 
    NSString* finalParsedString = [self.currentParseString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; 

    if([elementName isEqualToString:@"deviceName"]){ 
     self.currentDeviceID.deviceName = finalParsedString; 
    } 

    if([elementName isEqualToString:@"UUID"]){ 
     self.currentDeviceID.uuid = finalParsedString; 
    } 

    if([elementName isEqualToString:@"deviceLocation"]){ 
     self.currentDeviceID.location = finalParsedString; 
    } 

    if([elementName isEqualToString:@"deviceLastSeenTime"]){ 
     self.currentDeviceID.lastSeenTime = finalParsedString; 
    } 

    //Now we've used the accumulated string from the current element, 
    //we can clear it ready to start the accumulation process for 
    //the next element's contents: 
    self.currentParseString = [NSMutableString stringWithString:@""]; 

} 

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{ 
    //All we need to do here is add the next lot of characters 
    //to the accumulating string for the current element, 
    //which continues to happen until didEndElement is called: 
    [self.currentParseString appendString:string]; 
}