0

我目前正在开发一个 iOS 应用程序(目标 = iPod touch)来显示一些信息,这些信息基于 PostgreSQL 数据库,我是一个非常初学者。我做了很多研究,但我一无所获,这确实有助于解决我的问题。

目前,我从一个 php 文件中获取数据,该文件是 iOS 应用程序和数据库之间的“桥梁”。为此,我使用 http-request 向 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];
    }
}

解析器发现字符

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

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

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: 
4

1 回答 1

0

您是正确的,您需要实施didStartElement,foundCharactersdidEndElement. 您也是正确的,foundCharacters在处理给定元素的过程中将被调用多次,因此您需要通过将字符附加到字符串来处理此问题,而不是每次都创建一个新的独立字符串。或者,正如 Apple 在文档中所说:

解析器对象可以向委托发送几个 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];
}
于 2013-05-06T09:33:25.080 回答