0

私は現在、PostgreSQL データベースに基づいたいくつかの情報を表示するための iOS アプリ (ターゲット = iPod touch) を開発しており、私は非常に初心者です。私は多くの調査を行いましたが、問題を解決するのに本当に役立つものは何も見つかりませんでした.

現時点では、iOS アプリとデータベースの間の「ブリッジ」である php ファイルからデータを取得しています。そのために、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 では、2 つの配列が必要です。

キャプション配列

最初の配列は、xml ファイルのキャプション (id、invnr、art、type_id、rechnung、standort、erstellt、gekauft) を保持する必要があります。エントリ「行」は配列内にあってはなりません。

値配列

2 番目の配列は値のみを保存する必要があり、空の値も保存します。この例では、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{

}

出力と問題

問題は、パーサーが 1 つの要素を何度も処理しているように見えることです。そのため、値の配列は次のようになります。

 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-tag を取得するのは間違っています。(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

didStartElementfoundCharactersおよびを実装する必要があることは正しいですdidEndElement。特定の要素を処理する過程で何度か呼び出されることも正しいので、毎回新しいスタンドアロン文字列を作成するのではなく、文字列に文字を追加foundCharactersしてこれを処理する必要があります。または、Appleがドキュメントに記載しているように:

パーサー オブジェクトは、いくつかの parser:foundCharacters: メッセージをデリゲートに送信して、要素の文字を報告する場合があります。string は現在の要素の文字コンテンツ全体の一部にすぎない可能性があるため、要素が変更されるまで、現在の文字の蓄積に追加する必要があります。

例として、現在のプロジェクトからの単純な作業パーサーの完全な実装を次に示します。がいかに単純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 に答える