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

决定使用哪个解析器将取决于您的需求,但在这里描述如何使用每个解析器会占用太多空间。 本文介绍了不同类型的解析器以及如何使用每种解析器。由于这个结构看起来很简单,我倾向于使用NSXMLParserApple 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 打印出结果字典(在视图控制器的 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 回答