2013-03-14 94 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]; 
}