NSXML解析器返回空白结果
我目前正在开发一个用于显示一些信息的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:
你是正确的,你需要实现didStartElement
,foundCharacters
和didEndElement
。你也正确地认为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];
}