Cocoa Touch/iPhone中的XML解析

4

我看到了TouchXML、parseXML、NSXMLDocument和NSXMLParser,但我真的很困惑该怎么做。

我有一个iPhone应用程序,连接到服务器,请求数据并获取XML响应。不同查询的示例xml响应在http://pastebin.com/f681c4b04给出。

我还有其他类作为控制器(如MVC中),用于处理获取数据的逻辑。这个类从View类获取输入并处理它,例如向Web服务器发送请求,获取xml,解析xml,填充其变量(它是单例/共享类),然后对调用者响应true或false。基于控制器类给出的响应,调用者检查控制器的变量并向用户显示适当的内容。

我有以下控制器类变量:

@interface backendController : NSObject {
NSMutableDictionary *searchResults, *plantInfoResults, *bookmarkList, *userLoginResult;
}

现在我正在通过NSLog(@"Result: :%@" [NSString stringWithContentsOfURL:url])打印来自Web服务器的纯XML返回,其中包括像getBookmarkList、getPlantInfo等功能。

我想要一个通用函数,该函数获取从服务器返回的XML,解析它,将其制成一个NSMutableDictionary,其中包含XML开放标记的文本表示为键,XML标记值作为值并返回。

唯一的问题是,如何做到这一点?


仍在期待如何使用TouchXML创建通用函数,以解析http://pastebin.com/m53d8bf41中的XML,并将其中所有内容制作成字典,以标签作为键,标记值作为值。 - Shoaibi
我通过 http://pastebin.ca/1404334 成功解决了我的问题。欢迎评论...感谢大家的帮助。 - Shoaibi
3个回答

4

你有尝试过提到的任何XML解析器吗?这是它们如何设置节点名称的键值:

[aBook setValue:currentElementValue forKey:elementName];

顺便提醒一下,虽然你的XML内容看起来没问题,但有些结果似乎缺少根节点。除非出于简化目的而省略了它。

请查看w3schools XML教程,它应该会指引你正确地使用XML语法。


查看您的获取书签结果,您的XML是<entry>...</entry><entry>...</entry>...在XML中,您需要一个节点作为所有条目的父级:<AllEntries><entry>...</entry><entry>...</entry>..</AllEntries>。请参阅w3schools教程,我将在答案中添加链接。 - Sean
好的,我修改了XML,服务器返回的新XML是:http://pastebin.com/m6723d678,其中包含执行时的错误/警告,如http://pastebin.com/m3528fa82所示。我似乎无法使用TouchXML正常解析XML。请帮忙。 - Shoaibi
我认为这是因为我在返回的XML开头得到了4个空行。 - Shoaibi
也尝试过以下代码:NSString *r2 = @"<?xml version=\"1.0\" encoding=\"UTF-8\"?><AllEntries><entry><plantID>460</plantID><scientific>Alcea rosea 'Nigra'</scientific><common>Black Hollyhock</common></entry></AllEntries>";在控制台上我得到了以下内容:2009-04-23 08:57:06.067 Landscapedia[1926:20b] Starting XML Parsing 2009-04-23 08:57:06.125 Landscapedia[1926:20b] print nodes:( )没有警告,但也没有数据,代码与最后一个 pastebin 相同。 - Shoaibi
我以前没有使用过TouchXML,今晚我可以尝试一下你的XML,看看能否得到任何结果。我使用过NSXMLParser,在我的回答中放了一个链接到相当简单易懂的教程,我建议你尝试一下。在我尝试过你的XML后,我会再报告结果的。 - Sean
教程链接已过期。这是目前可用的链接:http://www.iPhoneSDKArticles.com/2008/12/parsing-xml-files.html - Daniel

0
考虑以下代码片段,它使用 libxml2Matt Gallagher 的 libxml2 包装器Ben Copsey 的 ASIHTTPRequest 来解析 HTTP 文档。
要解析 XML,请使用 PerformXMLXPathQuery 而不是我在示例中使用的 PerformHTTPXPathQuery
类型为 NSArray *nodes 实例将包含 NSDictionary * 对象,您可以递归解析以获取所需的数据。
或者,如果您知道 XML 文档的结构,可以编写 XPath 查询,直接获取 nodeContentnodeAttribute 值。
ASIHTTPRequest *request = [ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:@"http://stackoverflow.com/"];
[request start];
NSError *error = [request error];
if (!error) {
    NSData *response = [request responseData];
    NSLog(@"Root node: %@", [[self query:@"//" withResponse:response] description]);
}
else 
    @throw [NSException exceptionWithName:@"kHTTPRequestFailed" reason:@"Request failed!" userInfo:nil];
[request release];

...

- (id) query:(NSString *)xpathQuery withResponse:(NSData *)respData {
    NSArray *nodes = PerformHTMLXPathQuery(respData, xpathQuery);
    if (nodes != nil)
        return nodes;
    return nil;
}

0

为您提供一个在表格中解析XML的简单示例,希望能对您有所帮助。

//XMLViewController.h

#import <UIKit/UIKit.h>
@interface TestXMLViewController : UIViewController<NSXMLParserDelegate,UITableViewDelegate,UITableViewDataSource>{
@private
NSXMLParser *xmlParser;
NSInteger depth;
NSMutableString *currentName;
NSString *currentElement;
NSMutableArray *data;
}
@property (nonatomic, strong) IBOutlet UITableView *tableView;
-(void)start;
@end

//TestXMLViewController.m

#import "TestXmlDetail.h"
#import "TestXMLViewController.h"
@interface TestXMLViewController ()
- (void)showCurrentDepth;

@end

@implementation TestXMLViewController

@synthesize tableView;
- (void)start
{
NSString *xml = @"<?xml version=\"1.0\" encoding=\"UTF-8\" ?><Node><name>Main</name><Node><name>first row</name></Node><Node><name>second row</name></Node><Node><name>third row</name></Node></Node>";
xmlParser = [[NSXMLParser alloc] initWithData:[xml dataUsingEncoding:NSUTF8StringEncoding]];
[xmlParser setDelegate:self];
[xmlParser setShouldProcessNamespaces:NO];
[xmlParser setShouldReportNamespacePrefixes:NO];
[xmlParser setShouldResolveExternalEntities:NO];
[xmlParser parse];

}


- (void)parserDidStartDocument:(NSXMLParser *)parser 
{
NSLog(@"Document started");
depth = 0;
currentElement = nil;
}

- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError 
{
NSLog(@"Error: %@", [parseError localizedDescription]);
}

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

currentElement = [elementName copy];

if ([currentElement isEqualToString:@"Node"])
{
    ++depth;
    [self showCurrentDepth];
}
else if ([currentElement isEqualToString:@"name"])
{

    currentName = [[NSMutableString alloc] init];
}
}

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

if ([elementName isEqualToString:@"Node"]) 
{
    --depth;
    [self showCurrentDepth];
}
else if ([elementName isEqualToString:@"name"])
{
    if (depth == 1)
    {
        NSLog(@"Outer name tag: %@", currentName);
    }
    else 
    {
        NSLog(@"Inner name tag: %@", currentName);
      [data addObject:currentName];
    }
    }
   }        

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if ([currentElement isEqualToString:@"name"]) 
{
    [currentName appendString:string];
} 
}

- (void)parserDidEndDocument:(NSXMLParser *)parser 
{
    NSLog(@"Document finished", nil);
}



- (void)showCurrentDepth
{
  NSLog(@"Current depth: %d", depth);
}


- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
 data = [[NSMutableArray alloc]init ];
[self start];
self.title=@"XML parsing";
NSLog(@"string is %@",data);
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
`enter code here`return [data count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = @"Cell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];

if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = [data objectAtIndex:indexPath.row];
return cell;
}
@end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接