0

XML の REST 応答を解析しようとしています。応答の興味深い点は、複数のノードが同じ名前を持っていることです。iOS でこのデータを解析する簡単な方法を探しています。サンプルは次のとおりです。

<Report name="BalanceSheet">
<ColDesc><ColTitle>AccountType</ColTitle><ColType>ids_String</ColType></ColDesc>
<ColDesc><ColTitle>Amount</ColTitle><ColType>ids_Amount</ColType></ColDesc>
<Data>
<DataRow>
<ColData>Checking/Savings</ColData>
<ColData>12345345</ColData>
</DataRow>
<DataRow>
<ColData>Accounts Receivable</ColData>
<ColData>674532</ColData>
</DataRow>
<DataRow>
<ColData>Other Current Assets</ColData>
<ColData>423546</ColData>
</DataRow>
<DataRow>
<ColData>Fixed Assets</ColData>
<ColData>63545534</ColData>
</DataRow>
<DataRow>
<ColData>Other Assets</ColData>
<ColData>325465</ColData>
</DataRow>
<DataRow>
<ColData>Accounts Payable</ColData>
<ColData>653653</ColData>
</DataRow>
<DataRow>
<ColData>Other Current Liabilities</ColData>
<ColData>910596.75</ColData>
</DataRow>
<DataRow>
<ColData>Long Term Liabilities</ColData>
<ColData>553797.26</ColData>
</DataRow>
<DataRow>
<ColData>Equity</ColData>
<ColData>45363</ColData>
</DataRow>
</Data>
</Report>

SMXMLDocument パーサーを使用して、XMLReader を使用して NSDictionary に変換しようとしました。XML が構造化されている方法は、紛らわしいだけです。

助言がありますか?

4

2 に答える 2

1

これは、データベース テーブル (または Excel スプレッド シート) へのマッピングのように見えます。2 つの列名を取得しているようです。<Data>それぞれの行に該当するデータが含まれるデータが続きます。

<Report name="BalanceSheet">
        <ColDesc>
            <ColTitle>
                AccountType
            </ColTitle>
            <ColType>
                ids_String
            </ColType>
        </ColDesc>
        <ColDesc>
            <ColTitle>
                Amount
            </ColTitle>
            <ColType>
                ids_Amount
            </ColType>
        </ColDesc>
    <Data>
        <DataRow>
            <ColData>
                Checking/Savings
            </ColData>
            <ColData>
                12345345
            </ColData>
        </DataRow>
        <DataRow>
            <ColData>
                Accounts Receivable
            </ColData>
            <ColData>
                674532
            </ColData>
        </DataRow>
        <DataRow>
            <ColData>
                Other Current Assets
            </ColData>
            <ColData>
                423546
            </ColData>
        </DataRow>
        <DataRow>
            <ColData>
                Fixed Assets
            </ColData>
            <ColData>
                63545534
            </ColData>
        </DataRow>
    </Data>
    </Report>


AccountType         | Amount
--------------------------------
Checking/Savings    | 12345345
Accounts Receivable | 674532

どのパーサーを使用するかはニーズに応じて決定しますが、各パーサーの使用方法をここで説明するとスペースがかかりすぎます。 この記事では、さまざまな種類のパーサーと、それぞれの使用方法について説明します。NSXMLParserこの構造は非常に単純に見えるので、 ( Apple Docs )を使用する傾向があります。

于 2012-11-06T22:47:47.660 に答える
0

今日はすでに簡単な NSXMLParser の例を書いていたので、それを取り上げて、あなたが説明した XML を解析させました。

作業サンプル プロジェクトはこちら: https://github.com/erikt/ETParseIntuitSOExample

NSXMLParser デリゲートは、あなたが求めているものです。ヘッダーは次のとおりです。

#import <Foundation/Foundation.h>

@interface ETIntuitParser : NSObject<NSXMLParserDelegate>
+ (NSDictionary *)parseIntuitXML:(NSString *)xml;
@end

そして実装:

#import "ETIntuitParser.h"

@interface ETIntuitParser ()
@property NSUInteger dataColNumber;
@property (copy,nonatomic) NSString *dataKey;
@property (strong,nonatomic) NSMutableString *currentElementValue;
@property (strong,nonatomic) NSMutableDictionary *resultDict;
@end

@implementation ETIntuitParser

+ (NSDictionary *)parseIntuitXML:(NSString *)xml {
    ETIntuitParser *intuitParser = [[ETIntuitParser alloc] init];
    NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithData:[xml dataUsingEncoding:NSUTF8StringEncoding]];
    [xmlParser setDelegate:intuitParser];
    BOOL success = [xmlParser parse];

    if (success) {
        return [NSDictionary dictionaryWithDictionary:intuitParser.resultDict];
    } else {
        NSLog(@"Error parsing login information");
        return nil;
    }
}

#pragma mark - NSXMLParserDelegate
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
    if ([elementName isEqualToString:@"Report"]) {
        if (!self.resultDict) {
            self.resultDict = [NSMutableDictionary dictionary];
        }
        return;
    }
}

- (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
    if (!self.currentElementValue) {
        self.currentElementValue = [[NSMutableString alloc] initWithString:string];
    } else {
        [self.currentElementValue appendString:string];
    }
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{

    if ([elementName isEqualToString:@"DataRow"]) {
        self.dataColNumber = 0;
    }

    if ([elementName isEqualToString:@"ColData"]) {
        NSString *trimmedValue = [self.currentElementValue stringByTrimmingCharactersInSet:
                                  [NSCharacterSet whitespaceAndNewlineCharacterSet]];

        if (self.dataColNumber == 0) {
            self.dataKey = trimmedValue;
            self.dataColNumber++;
        } else {
            [self.resultDict setObject:trimmedValue forKey:self.dataKey];
        }

    }

    self.currentElementValue = nil;
}
@end

結果の辞書を NSLog で出力しただけです(View ControllerのviewDidLoadでも...)。結果は次のとおりです。

2012-11-07 00:21:22.409 ETParseIntuitSOExample[66941:c07] {
    "Accounts Payable" = 653653;
    "Accounts Receivable" = 674532;
    "Checking/Savings" = 12345345;
    Equity = 45363;
    "Fixed Assets" = 63545534;
    "Long Term Liabilities" = "553797.26";
    "Other Assets" = 325465;
    "Other Current Assets" = 423546;
    "Other Current Liabilities" = "910596.75";
}

XML 構造からの列ヘッダー情報が必要かどうかはわかりませんが、簡単に追加できるはずです。

于 2012-11-06T23:30:37.103 に答える