iPhone TBXML 循环和解析数据

Posted

技术标签:

【中文标题】iPhone TBXML 循环和解析数据【英文标题】:iPhone TBXML Looping And Parsing Data 【发布时间】:2011-03-23 14:03:41 【问题描述】:

基本上我有一个返回的 XML 响应和一个字符串,我需要遍历 xml 并将所有信息存储在一个数组中。这是xml

<?xml version="1.0" encoding="UTF-8"?>
<Response xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://schema.2sms.com/2.0/schema/0310_ResponseReportStandard.xsd" Version="1.0">
    <Error>
        <ErrorCode>00</ErrorCode>
        <ErrorReason>OK</ErrorReason>
    </Error>
    <ResponseData>
        <Identification>
            <UserID>jonathan.pink@2sms.com</UserID>
        </Identification>
        <Result>2 records were returned</Result>
        <Detail>
            <ReportTitle>Message Summary: Today</ReportTitle>
            <Record>
                <Destination>447790686158</Destination>
                <Status>WithNetwork</Status>
                <GUID><![CDATA[2011-03-22T10:54:22.097Z]]></GUID>
                <DateSubmitted>2011-03-22T10:54:22.097</DateSubmitted>
                <DateToSend></DateToSend>
                <DateSent>2011-03-22T10:54:22.533</DateSent>
                <DateReceived></DateReceived>
                <Message><![CDATA[Yet again another test]]></Message>
                <ID>2011-03-22 10:54:22.250HIHIIOJTFVETW85TS</ID>
            </Record>
            <Record>
                <Destination>447790686158</Destination>
                <Status>SUCCESS</Status>
                <GUID><![CDATA[2011-03-22T10:50:40.064Z]]></GUID>
                <DateSubmitted>2011-03-22T10:50:40.063</DateSubmitted>
                <DateToSend></DateToSend>
                <DateSent>2011-03-22T10:50:42.473</DateSent>
                <DateReceived>2011-03-22T10:50:54.570</DateReceived>
                <Message><![CDATA[This is a test]]></Message>
                <ID>2011-03-22 10:50:40.210DRUDVMCEZGETW85TS</ID>
            </Record>
            <ReportPage ReportID="775797" ItemsPerPage="25" Page="1" TotalItems="2" />
        </Detail>
    </ResponseData>
</Response>

我需要将这 2 个&lt;records&gt; 和所有数据存储在一个数组中。所以....

一个记录数组 -> 记录数组 -> 每个记录的数组,数据......

我一直坐在这里尝试使用 TBXML 来解决这个问题,这很容易抓住单个节点....但我不能这样做:(

【问题讨论】:

请看您是否可以接受更多答案。对于一些未被接受的问题,您似乎有合理的答案。 【参考方案1】:

好的,第一步是创建一个解析数据的类。例如,称之为RecordParser。我们现在需要在标题中添加几个方法,以及一个NSMutableArray

@interface RecordParser : NSObject 
    NSMutableArray *records;    

@property(nonatomic,retain)NSMutableArray *records;

-(void)loadRecords:(NSString *)records;
-(void)traverseElement:(TBXMLElement *)element;

@end

现在,继续进行实施。我们现在需要实现这两种方法来做我们希望它们做的事情。

- (void)loadRecords:(NSString *)records 
    NSString *someXML = @"http://www.something.com/somexml.xml";
    TBXML *tbxml = [[TBXML tbxmlWithURL:[NSURL URLWithString:someXML]] retain];

    records = [NSMutableArray array];
    [records retain];

    if (tbxml.rootXMLElement)
        [self traverseElement:tbxml.rootXMLElement];
    [tbxml release];

基本上,该方法将获取相关的 XML 文件并开始解析过程。此外,您正在初始化数组并保留它。现在我们来看看奶酪。

- (void) traverseElement:(TBXMLElement *)element 
    do 
        if (element->firstChild) 
            [self traverseElement:element->firstChild];

        if ([[TBXML elementName:element] isEqualToString:@"Record"]) 
            TBXMLElement *destination = [TBXML childElementNamed:@"Destination" parentElement:element];
            TBXMLElement *status = [TBXML childElementNamed:@"Status" parentElement:element];
            TBXMLElement *guid = [TBXML childElementNamed:@"GUID" parentElement:element];
            TBXMLElement *dateSub = [TBXML childElementNamed:@"DateSubmitted" parentElement:element];
            TBXMLElement *dateToSend = [TBXML childElementNamed:@"DateToSend" parentElement:element];
            TBXMLElement *dateSent = [TBXML childElementNamed:@"DateSent" parentElement:element];
            TBXMLElement *dateReceived = [TBXML childElementNamed:@"DateReceived" parentElement:element];
            TBXMLElement *message = [TBXML childElementNamed:@"Message" parentElement:element];
            TBXMLElement *id = [TBXML childElementNamed:@"ID" parentElement:element];

            [records addObject:[NSArray arrayWithObjects:
                                  [TBXML textForElement:destination],
                                  [TBXML textForElement:status],
                                  [TBXML textForElement:guid],
                                  [TBXML textForElement:dateSub],
                                  [TBXML textForElement:dateToSend],
                                  [TBXML textForElement:dateSent],
                                  [TBXML textForElement:dateReceived],
                                  [TBXML textForElement:message],
                                  [TBXML textForElement:id],nil]];  
        
     while ((element = element->nextSibling));  

该方法的作用基本上是遍历 XML 文件以查找具有您要查找的名称的元素,然后从子节点中获取数据。此外,数据被添加到records 数组中。所以基本上,当它完成后,它应该在你的records 数组中包含你想要的数据,你可以随意操作它。

这是完全未经测试的。如果它炸毁了您的计算机并杀死了您的猫,请不要怪我。我通常不会花费所有的工作来编写这样一个完整的方法,但我碰巧喜欢TBXML。请让我知道它是否有效。我真的希望知道。

【讨论】:

是的!谢谢它也完全符合我的要求!但是我遇到了另一个问题,即从数组中选择要在 tableview 单元格中使用的特定条目....但是非常感谢它治愈了我 2 天的头痛! @MrPink:您只需将要在表格中显示的数组中的objectAtIndex 放入cellForRowAtIndexPath cell.textLabel.text = [NSString stringWithFormat:@"%@",[records objectAtIndex:indexPath.row]];这就是我正在使用的,但是它正在打印出数组每条记录中的所有内容 @MrPink:需要展示哪些数据? ID? GUID? @MrPink:您能否在问题中提出一个包含相关数据(上面的records 数组)的新问题?那我就可以回答的更清楚了。【参考方案2】:

我编写了递归函数来解析任何使用 TBXML 库正确创建的 xml。

在我的项目中,我有一个类来解析 XML。它有一个名为的类方法:+ (id) infoOfElement: (TBXMLElement*) element

使用方法:

TBXML *tbxml = [TBXML tbxmlWithXMLData:yourData];
TBXMLElement *rootXMLElement = tbxml.rootXMLElement;

id parsedData = [self infoOfElement: rootXMLElement];

    //return NSString or NSDictionary ot NSArray of parsed data
    + (id) infoOfElement: (TBXMLElement*) element
    
        if (element->text)
            return [TBXML textForElement:element];
        NSMutableDictionary *info = [NSMutableDictionary new];
        TBXMLAttribute *attribute = element->firstAttribute;
        if (attribute) 
            do 
                [info setValue:[TBXML attributeValue:attribute] forKey:[TBXML attributeName:attribute]];
                attribute = attribute -> next;
             while (attribute);
        
        TBXMLElement *child = element->firstChild;
        if (child)
            TBXMLElement *siblingOfChild = child->nextSibling;
            //If we have array of children with equal name -> create array of this elements
            if ([[TBXML elementName:siblingOfChild] isEqualToString:[TBXML elementName:child]])
                NSMutableArray *children = [NSMutableArray new];
                do 
                    [children addObject:[self infoOfElement:child]];
                    child = child -> nextSibling;
                 while (child);
                return [NSDictionary dictionaryWithObject:children forKey:[TBXML elementName:element]];
            
            else
                do 
                    [info setValue:[self infoOfElement:child] forKey:[TBXML elementName:child]];
                    child = child -> nextSibling;
                 while (child);
            
                    
        return info;
    

【讨论】:

【参考方案3】:

使用苹果的NSXMLParser;它变得老派了,但它真的很有效。

相应地设置您的 XMLParser(使用NSXMLParserDelegate 协议)。

一旦您的解析器命中调用parser:didStartElement:namespaceURI:qualifiedName:attributes: 委托回调并且elementName 等于Record(来自您似乎想要的)。

Alloc'init'一个NSMutableDictionary。然后像上面那样如果elementName 等于Destination 然后[myDictionary setObject: elementName forKey: @"Destination"] 等等。

希望对您有所帮助:)。

附注:更喜欢使用Apple's“技术”而不是第 3 方:它更高效,而且可能性无穷无尽

【讨论】:

然而,TBXML 已被证明在解析方面比NSXMLParser 快得多。我使用 TBXML,我喜欢它。 :) 这是真的,这就是我想做的事情。 sudo 你将如何使用 tbxml 来解析我上面的 xml?【参考方案4】:

最好使用 NSXMLParser,因为它是 Apple 的官方版本。

NSXMLParser 的所有文档都是here。

另外,这里有一个 NSXMLParser Tutorial。

【讨论】:

NSXMLParser 比 TBXML 慢 3 倍。 “Apple”制造的事实并没有让它变得更好。

以上是关于iPhone TBXML 循环和解析数据的主要内容,如果未能解决你的问题,请参考以下文章

TBXML 将复杂的 xml 解析为数组

内存泄漏与自动释放的字符串 iphone

在 Objective-C 中使用 TBXML 时的内存泄漏

iOS:结合 SAX 和 DOM 解析

iOS之深入解析如何检测“循环引用”

iPhone 的实时音频循环切换