具有多个连接/提要/视图的 XML 解析的设计/实施建议

Posted

技术标签:

【中文标题】具有多个连接/提要/视图的 XML 解析的设计/实施建议【英文标题】:Design/Implementation advice on XML Parsing with multiple connections/feeds/views 【发布时间】:2011-12-16 03:52:45 【问题描述】:

开始我的第一个 ios 项目并想就如何构建应用程序提供建议。 该应用程序提取 XML 提要,对其进行解析并显示一个表示 XML 提要中的项目的列表。单击列表中的项目时,应用程序将使用先前提取的 XML 提要中的属性之一拉取新的 XML 提要。这发生在几层拉,解析,显示和用户选择上,再次做同样的事情。现在大部分的 XML 元素结构是这样的:

(这些是简单的例子,只是为了演示发生了什么)

http://site.com/get/items/

返回(在新视图上显示信息):

<items>
    <item id="123" name="item 1" />
    <item id="124" name="item 2" />
    <item id="125" name="item 3" />
</itmes>
http://site.com/get/description/123(示例用户已选择第 1 项,拨打电话获取描述)

返回:

<itemDescription>
    <description itemId="123" name="desc 1" description="blah 1" />
</itemDescription>

想知道:

我应该在每个视图中都有一个连接类/对象还是一个新连接? 我应该有一个解析器类/对象还是解析每个视图中的 XML 提要? 我还希望存储一些返回的数据,因此如果用户导航回主项目列表,我不需要再次调用 XML 提要,但我需要每次都解析 itemsDescription XML 提要.

我查看了一些关于解析 XML 的教程,并且了解了如何做到这一点的要点,我希望更多地关注设计和可重用性,而不是在每个新视图中重复代码。或者我对它是如何工作的还有很长的路要走

【问题讨论】:

【参考方案1】:

您可以按照 Apple 指南执行此操作的最佳方法是查看其中一个示例,几个月前,我按照此示例制作了一个与您类似的应用程序。您还可以了解如何使您的应用处于离线模式。

Basic structure(无离线模式):

SeismicXML 示例应用程序演示了如何使用 NSXMLParser 解析 XML 数据。当您启动应用程序时,它会下载并 解析来自美国地质调查局 (USGS) 的 RSS 提要 提供世界各地近期地震的数据。它显示 每次地震的位置、日期和震级,以及 指示地震严重程度的彩色编码图形。这 XML 解析发生在后台线程上,使用 NSOperation 和 使用批量解析的对象更新地震表视图。

Advanced structure(带离线模式):

演示如何在多线程环境中使用 Core Data, 遵循核心数据中提到的第一个推荐模式 编程指南。

基于 SeismicXML 示例,它下载并解析 RSS 提要 美国地质调查局 (USGS) 提供的数据 世界各地最近发生的地震。是什么让这个样本与众不同 是它使用核心数据持续存储地震。每一次 您启动应用程序,它会下载新的地震数据,并以 NSOperation 检查重复和新创建的存储 地震作为管理对象。

对于那些刚接触 Core Data 的人来说,比较 SeismicXML 会很有帮助 用这个样品取样并注意必要的成分 在您的应用程序中引入 Core Data。

关于 cwieland 的答案,我不会使用 ASIHTTPRequest,因为它是 outdated,所以如果您想遵循他的方法,我建议您使用 AFNetworking,您可以轻松快速地处理 XML 请求:

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://api.flickr.com/services/rest/?method=flickr.groups.browse&api_key=b6300e17ad3c506e706cb0072175d047&cat_id=34427469792%40N01&format=rest"]];
AFXMLRequestOperation *operation = [AFXMLRequestOperation XMLParserRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, NSXMLParser *XMLParser) 
  XMLParser.delegate = self;
  [XMLParser parse];
 failure:nil];

NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease];
[queue addOperation:operation];

【讨论】:

+1 表示“我不会使用 ASIHTTPRequest,因为它已经过时了,所以如果你想遵循他的方法,我建议你使用 AFNetworking”【参考方案2】:

这是我将如何实现它。我会为所有连接项使用 ASIHTTPRequest 而不必担心它的那一部分。它可以通过简单的委托方法非常轻松地处理所有异步数据下载。

我会有一个解析器类,它接收 url,异步下载它,然后解析返回的数据。然后,它会通过委托方法将解析后的子元素数组返回到 tableview,该 tableview 将在 xml 数据中显示子元素。

我会创建一个 UITableViewController 的子类,它可以处理任何 url/数据类型,在这种情况下,您只需编写一个 tableview 类,而不必担心用户如何导航。这将使您只需要编写一个类,它就可以处理任意数量的向下钻取或组合。此实现很大程度上取决于不同级别的 xml 数据的复杂程度。如果它们完全不同,那么在 tableview 中使用更简洁的代码而不让if's 检查单元格创建中的数据类型会更有意义。

使用导航风格的应用程序将无需在每次从堆栈中弹出视图时重新解析数据。尽管它会重新解析,但任何时候都可以重新解析,但是如果需要/需要,一个简单的 urls->array 缓存可以解决这个问题。不过,每次应用启动时都需要重新加载数据。当然,如果您收到 3 级深度的内存警告,则需要在备份过程中重新解析或缓存检索。

如果你想要一个缓存系统,我会编写一个介于视图控制器和检查存储的 url 解析器之间的类,如果它在那里,则返回数据数组,否则返回 nil 并获取它。

我个人会使用 NSXMLParser,因为这是我所熟悉的。您可能希望将元素存放在类包装器中,在这种情况下,您只需检查didStartElement 上的元素类型并设置一个枚举以通过创建打开。使用 nsxmlparser 很容易。我没有使用任何其他解析器进行比较,但确实发现调试 NSXMLParser 非常简单,编码也很简单,因此启动和运行它并不难。这是一个关于所有不同 xml 解析器的好网站:

http://www.raywenderlich.com/553/how-to-chose-the-best-xml-parser-for-your-iphone-project

所以总而言之,我将有一个 NSObject 的子类,它接受 url,通过 ASIHTTPRequest 下载它,解析它。 UITableviewController 的 Sublcas,在单元格点击时它分配具有新 url 的相同视图控制器类并将其推送到导航堆栈上。该视图将显示加载屏幕,直到返回数组,然后重新加载数据。希望这是一个非常干燥的吻。

我会尽可能多地将代码存放在全局类中。如果每次拉取数据只有一个主要类别,如

<items>
    <stuff></stuff>
    ....
    <stuff></stuff>
</items>
EOF

我会使用一个数组来存放所有值,如果有多个主要部分,我会将所有内容存储在字典中,其中 parent 属性作为键,值在数组中。然后在 tableview 上根据字典的键有不同的部分。

我希望这能回答您的一些问题。我不确定你要找的级别有多低。我从开发不少应用程序和编写 RSS 阅读器说起。如果您有任何需要我澄清的地方,请告诉我。

【讨论】:

哇!很好很详细+1

以上是关于具有多个连接/提要/视图的 XML 解析的设计/实施建议的主要内容,如果未能解决你的问题,请参考以下文章

情节提要中具有约束的多个TextField [重复]

将多个xml合并为一个

iPhone Core Data 一次保存多个项目的随机行为?

使用 XML 包 R 解析 RSS 提要

LINQ TO XML 解析 RSS 提要

解析 XML(RSS 提要)的 PHP 错误