NSXML Parser返回空白结果

时间:2013-03-14 12:05:12

标签: objective-c xml-parsing httprequest nsxmlparser

我目前正在开发一个用于显示一些信息的iOS应用程序(目标= iPod touch),这些信息基于PostgreSQL数据库而且我是一个非常初学者。我做了很多研究,但我什么也没找到,这对解决我的问题非常有帮助。

目前我从php文件中获取数据,这是iOS App和数据库之间的“桥梁”。为此,我使用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)。条目“row”不应该在数组中。

值数组

第二个数组应该只保存值 - 也是空值。在那个例子中它将是4,61821B741AEBI8,c,2,G01E01R01,2011-12-06,2003-01-01

使用NSXML Parser

这是配置,我目前用它来解析xml并将数据保存到数组中。

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

Parser 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);

    }
}

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

我希望有人可以帮助解决这个问题。 谢谢和最好的问候 - 托比亚斯

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: 

1 个答案:

答案 0 :(得分:0)

您是正确的,您需要实施didStartElementfoundCharactersdidEndElement。您在处理给定元素的过程中将多次调用foundCharacters也是正确的,因此您需要通过字符附加到字符串来处理此问题,而不是创建一个每次都是新的独立字符串。或者,正如Apple将其置于docs

  

解析器对象可以发送几个委托   parser: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];
}