在iphone SDK上解析XML代码 [英] Parsing XML code on iphone SDK

查看:97
本文介绍了在iphone SDK上解析XML代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经编写了一些代码,其中大部分是从教程等中获取的,但不确定它是100%。代码有效,但我认为它有点长,并且有内存泄漏。

I have written some code, most of which has been taken from tutorials etc, but not sure it's 100%. The code works, but I think its a bit long winded, and has memory leaks.

所以有三个问题:


  1. 可以清理吗?更容易理解?

  2. 如何修复'if(indexPath.section == 1)theRow + = 6;'位是动态的?

  3. 内存泄漏,如果需要排序,我该如何排序? (新手......)

任何反馈/指示/帮助超过欢迎......

Any feedback/pointers/help more than welcome...

#import "InfoViewController.h"
@implementation InfoViewController

- (void)parseXMLFileAtURL:(NSString *)URL {
    sections = [[NSMutableArray alloc] init];
    secItems = [[NSMutableArray alloc] init];

    //you must then convert the path to a proper NSURL or it won't work
    NSURL *xmlURL = [NSURL URLWithString:URL];
    rssParser = [[NSXMLParser alloc] initWithContentsOfURL:xmlURL];

    // Set self as the delegate of the parser so that it will receive the parser delegate methods callbacks.
    [rssParser setDelegate:self];

    // Depending on the XML document you're parsing, you may want to enable these features of NSXMLParser.
    [rssParser setShouldProcessNamespaces:NO];
    [rssParser setShouldReportNamespacePrefixes:NO];
    [rssParser setShouldResolveExternalEntities:NO];

    [rssParser parse];
}

- (void)parserDidStartDocument:(NSXMLParser *)parser {
    [activityIndicator startAnimating];
    [activityIndicator addSubview];
}

- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
    NSString * errorString = [NSString stringWithFormat:@"Unable to download story feed from web site (Error code %i )", [parseError code]];
    NSLog(@"error parsing XML: %@", errorString);

    UIAlertView * errorAlert = [[UIAlertView alloc] initWithTitle:@"Error loading content" message:errorString delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [errorAlert show];
}

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{

    currentElement = [elementName copy];

    if ([elementName isEqualToString:@"title"]) {
        // clear out our story item caches...
        currentTitle = [[NSMutableString alloc] init];
    }

    if ([elementName isEqualToString:@"section"]) {
        //item = [[NSMutableDictionary alloc] init];
        item = [[NSMutableDictionary alloc] init];
        currentSection = [[NSMutableString alloc] init];
    }
}

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

    if ([elementName isEqualToString:@"section"]) {

        // save values to an item, then store that item into the array...
        [item setObject:currentSection forKey:@"name"];
        [item setObject:[NSNumber numberWithInt:itemsCount] forKey:@"itemsCount"];

        [sections addObject:[item copy]];

        itemsCount = 0;
    }

    if ([elementName isEqualToString:@"title"]) {

        // save values to an item, then store that item into the array...
        [item setObject:currentTitle forKey:@"title"];

        itemsCount = itemsCount + 1;
        [secItems addObject:[item copy]];
    }
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
    // save the characters for the current item...
    if ([currentElement isEqualToString:@"name"]) {
        [currentSection appendString:string];
    } else if ([currentElement isEqualToString:@"title"]) {
        [currentTitle appendString:string];
    } else if ([currentElement isEqualToString:@"description"]) {
        [currentSummary appendString:string];
    } else if ([currentElement isEqualToString:@"pubDate"]) {
        [currentDate appendString:string];
    }
}

- (void)parserDidEndDocument:(NSXMLParser *)parser {

    [activityIndicator stopAnimating];
    [activityIndicator removeFromSuperview];

    [dataTable reloadData];
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];


    if ([sections count] == 0) {
        NSString * path = @"http://www.website.com/_dev/info.xml";
        [self parseXMLFileAtURL:path];
    }

}

#pragma mark -
#pragma mark Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    // Return the number of sections.
    return [sections count];
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    return [[sections objectAtIndex: section] objectForKey: @"name"];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [[[sections objectAtIndex: section] objectForKey: @"itemsCount"] intValue];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {


    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];

    if(cell == nil){
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
    }

    int theRow = indexPath.row;

    /*
     if(indexPath.section >= 1){
     int oldSection = indexPath.section - 1;
     int prevRows = prevRows + [[[sections objectAtIndex: oldSection] objectForKey: @"itemsCount"] intValue];
     theRow += prevRows;
     }
     */

    if (indexPath.section == 1) theRow += 6;
    if (indexPath.section == 2) theRow += 8;
    if (indexPath.section == 3) theRow += 14;
    if (indexPath.section == 4) theRow += 19;
    if (indexPath.section == 5) theRow += 22;
    if (indexPath.section == 6) theRow += 23;

    cell.textLabel.text = [[secItems objectAtIndex:theRow] objectForKey: @"title"];
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    return cell;
}

#pragma mark -
#pragma mark Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // Navigation logic may go here. Create and push another view controller.
}


#pragma mark -
#pragma mark Memory management

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Relinquish ownership any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {
    // Relinquish ownership of anything that can be recreated in viewDidLoad or on demand.
    // For example: self.myOutlet = nil;
}


- (void)dealloc {
    [super dealloc];
    [currentElement release];
    [rssParser release];
    [sections release];
    [item release];
    [currentTitle release];
}


@end

XML我试图分解部分和项目的Feed:

The XML feed which I am trying to break down for sections and items:

<?xml version="1.0" encoding="ISO-8859-1"?>
<data>
    <section>
        <name>Section 1</name>
        <item>
            <title>Title 1</title>
            <pubDate>1 Sept 2010</pubDate>
            <detail><![CDATA[Detail text]]></detail>
        </item>
        <item>
            <title>Title 2</title>
            <pubDate>1 Sept 2010</pubDate>
            <detail><![CDATA[<Detail text]]></detail>
        </item>
        <item>
            <title>Title 3</title>
            <pubDate>1 Sept 2010</pubDate>
            <detail><![CDATA[Detail text]]></detail>
        </item>
        <item>
            <title>Title 4</title>
            <pubDate>1 Sept 2010</pubDate>
            <detail><![CDATA[Detail text]]></detail>
        </item>
        <item>
            <title>Title 5</title>
            <pubDate>1 Sept 2010</pubDate>
            <detail><![CDATA[Detail text]]></detail>
        </item>
        <item>
            <title>Title 6</title>
            <pubDate>1 Sept 2010</pubDate>
            <detail><![CDATA[Detail text]]></detail>
        </item>
    </section>
    <section>
        <name>Section 2</name>
        <item>
            <title>Title 1</title>
            <pubDate>1 Sept 2010</pubDate>
            <detail><![CDATA[Detail text]]></detail>
        </item>
        <item>
            <title>Title 2</title>
            <pubDate>1 Sept 2010</pubDate>
            <detail><![CDATA[Detail text]]></detail>
        </item>
    </section>
</data>


推荐答案


  1. 不幸的是正如您所做的那样,Apple提供的NSXMLParser至少需要3个函数才能工作。如果要清理它,请考虑使用第三方脚本,例如 TouchXML KissXML

至于使这个动态,您可以将这些数字放入一个数组并读出它们,或改变您设置数据的方式。通常使用不同的部分,您可以为数据使用不同的数组。这会使你的theRow变量超出等式。 此处是使用多个数组但没有字典的教程。

As for making this dynamic, you can put those numbers into an array and read them out, or change the way you're setting the data. Usually with different sections you use different arrays for the data. This takes your theRow variable out of the equation. Here is a tutorial that uses multiple arrays without a dictionary.

@JeremyP有一些很好的建议。如果您还在苦苦挣扎,请进行构建和分析。这将显示潜在泄露的对象,以便您可以通过并确保所有内容都正确发布。

@JeremyP has some good suggestions. If you're still struggling, do a Build and Analyze. This will show you "potentially leaked objects" so you can go through and make sure everything's released properly.






解析XML树有两种方法 - 这就是你正在做的事情。


There are 2 ways to go about parsing XML Trees-which is what you are doing.

第一种是使用NSXML解析器你已经有。首先创建一个包含所有更高级元素名称的字典,即section和item,然后在解析器中添加两个额外的字符串,currentNodeName和parentNodeName。在迭代时,将currentNodeContent更改为elementName。如果elementName在你的字典中,请将parentNodeName设置为elementName,否则保持原样。

The first is using the NSXML parser you already have. First create a dictionary containing all of the higher level element names, i.e. section and item, then add two extra strings to your parser, currentNodeName and parentNodeName. As you iterate through, change the currentNodeContent to the elementName. If the elementName is in your dictionary, set parentNodeName to the elementName, otherwise leave it as is.

使用TouchXML需要的代码少一些。它适用于xpath,因此您可以以路径格式指定/ section / name / item / title。您可能需要添加另一个for循环,因为您向下钻取另一个级别。

Using TouchXML requires a bit less code. It works with xpaths, so you can specify /section/name/item/title in a path format. You will probably need to add another for loop that counts because you drill down another level.

这篇关于在iphone SDK上解析XML代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆