2

私は現在、大きな XML ファイルを SQLite バックエンドに処理する必要がある iPad プロジェクトに取り組んでいます。私は現在、 TBXMLパーサーを使用してこれを機能させています。

したがって、すべてのロジックが適切に配置され、一般に TBXML パーサーが必要な作業を実行します。私が現在直面している唯一の問題は、XML ファイルが大きくなりすぎて、メモリが不足していることです。このため、Alan Quatermain のAQXMLParserのようなもののコア NSXMLParser のような SAX パーサーに切り替えることを考えています。ただし、これには、DOM ツリーによって提供される関数にある程度依存している現在のロジックをすべてやり直す必要があります。これは、むしろやりたくないことです。

そこで私が試みたいのは、ハイブリッド アプローチを作成することです。私のXML構造を考えると、これは可能であるはずです。基本的には、繰り返しの「レコード」要素の数です。また、各レコード内には、繰り返してネストできるさまざまな要素があります。私の現在のアプローチでは、ドキュメントを解析し、各レコード要素を関数に渡し、それを処理してデータベースに入れます。これが既に存在することを考えると、ハイブリッド解析アプローチでこれを使用したいと考えています。

これが私が達成したいことです。SAX パーサーを使用して、ドキュメントをトラバースします。ドキュメントをたどりながら、Record 要素を作成します。レコード要素を完成させるたびに、TBXML を使用してそれを処理する既存の関数に渡します。次に、SAX パーサーは次のレコード要素の構築を続けます。主な目標は次のとおりです。 - メモリ フットプリントを修正します (可能な限り小さくする必要はありませんが、TBXML を使用する場合よりも一定であるか、少なくとも小さくする必要があります) - 許容できるパフォーマンスを維持します。

現在、これを次のように実装したいと考えています。

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict{
    //Recreate record string each time record element is encountered
    if([elementName isEqualToString:@"Record"]) record = [[NSMutableString alloc] init];
    //Write XML tag with name
    [record appendFormat@"<%@>, elementName];
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
    //Write XML content
    [record appendString:string];
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
    //Write XML tag
    [record appendFormat@"</%@>, elementName];
    if([elementName isEqualToString:@"Record"]){
        //Parse record string into TBXML object
        TBXML * tbxmlRecord = [TBXML tbxmlWithXMLString:record];
        //Send it to the TBXML record processor
        [self processElement:tbxmlRecord.rootXMLElement];
    }
}

これでうまくいくと思いますが、文字列を使うのは汚いです。さらに、パーサーが新しいレコード要素に到達したときに、レコード文字列がすぐに上書きされないかどうかについて懸念があります。

だから私の質問は、これがこれにアプローチする健全な方法であるか、それとも私が探しているものを達成するためのより良い方法があるかどうかです.

編集: 私はこのアプローチを実装しましたが、うまく機能しているようです。私が遭遇した唯一の問題は、ソース ファイルが UTF-8 でエンコードされていない場合、部分的な結果しか得られないことです。しかし、私がこれを修正すると、すべてうまくいきます。ただし、メモリ使用量はそれほど良くありません。しかし、多分それはそれができることを必要とします。さらにテストを実行する必要があります...

4

1 に答える 1

1

一般的に、あなたのアプローチは私にはうまく聞こえます。あなたのソリューションがパフォーマンスの問題なしにあなたのために働いているなら、私は文字列の処理についてあまり心配しません。必要に応じて、アプリケーションのプロファイルを作成して、これによって無駄になっているCPU時間を確認できます。

もう少し最適化したい場合は、元のバッファーのバイトオフセットを提供するSAXパーサーを見つけて、これを、nullで終了していないC文字列を処理できるDOMパーサーと組み合わせることができます。これは、CまたはC++ライブラリに切り替える必要があることを意味すると思います。私はあなたが試しているものと漠然と似ているもの(巨大なファイルに埋め込まれたxmlチャンク)にrapidxmlを使用しました。

于 2012-07-31T08:04:48.057 に答える