iPhone - Разбор XML-файла - Пожалуйста, помогите! - PullRequest
0 голосов
/ 08 декабря 2010

Мне нужна помощь с анализом XML-файла. Моя проблема в том, что я не знаю, как реализовать делегат didEndElement.
Я хочу, чтобы у меня было 2 камеры, в которых будут отображаться Ветхий Завет и Новый Завет, а затем Книги Библии и главы. Если я смогу просто получить некоторую помощь с парсингом xml, остальными я смогу управлять.

Буду очень признателен за любую помощь!

Спасибо и всего наилучшего!

Мой XML-файл выглядит следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
<bible>
 <testament name="Old Testament">
  <book name="Genesis">
   <chapter id="Genesis 1"></chapter>
   <chapter id="Genesis 2"></chapter>
  </book>
  <book name="Exodus">
   <chapter id="Exodus 1"></chapter>
   <chapter id="Exodus 2"></chapter>
  </book>
 </testament>
 <testament name="New Testament">
  <book name="Matthew">
   <chapter id="Matthew 1"></chapter>
   <chapter id="Matthew 2"></chapter>
  </book>
  <book name="Revelation">
   <chapter id="Revelation 1"></chapter>
   <chapter id="Revelation 2"></chapter>
  </book>
 </testament>
</bible>

//  Bible.h
#import <Foundation/Foundation.h>

@interface Bible : NSObject {
 NSMutableArray *bible;
 NSMutableArray *testament;
 NSMutableArray *book;
 NSString *chapterID;

}

@property (nonatomic, retain)NSMutableArray *bible;
@property (nonatomic, retain)NSMutableArray *testament;
@property (nonatomic, retain)NSMutableArray *book;
@property (nonatomic, retain)NSString *chapterID;

@end

//  Bible.m

#import "Bible.h"


@implementation Bible

@synthesize bible;
@synthesize testament;
@synthesize book;
@synthesize chapterID;

- (void) dealloc {
 [bible release];
 [testament release];
 [book release];
 [chapterID release];
 [super dealloc];
}

@end

//
//  XMLParser.h
//  BibleXML
//

#import <Foundation/Foundation.h>
#import "Bible.h"

@protocol NSXMLParserDelegate;

@class BibleXMLAppDelegate, Bible;

@interface XMLParser : NSObject <NSXMLParserDelegate> {


 NSMutableString *currentElementValue;

 BibleXMLAppDelegate *appDelegate;
 Bible *theBible;

}

- (XMLParser *) initXMLParser;

@end

//
//  XMLParser.m

#import "XMLParser.h"
#import "BibleXMLAppDelegate.h"
#import "Bible.h"


@implementation XMLParser

- (XMLParser *) initXMLParser {

 [super init];

 appDelegate = (BibleXMLAppDelegate *) [[UIApplication sharedApplication] delegate];
 return self;
}

- (void)parserDidStartDocument:(NSXMLParser *)parser{ 
 NSLog(@"found file and started parsing");
}

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
  namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
 attributes:(NSDictionary *)attributeDict {
 if([elementName isEqualToString:@"bible"]) {
  NSLog(@"Found element: %@", elementName);
  appDelegate.bible = [[NSMutableArray alloc] init];
 }

 else if([elementName isEqualToString:@"testament"]) {

  theBible = [[Bible alloc] init];
  //Extract the attribute here.
  theBible.testament = [attributeDict valueForKey:@"name"];
  NSLog(@"Testament: %@", theBible.testament);
  return;
 }

 else if ([elementName isEqualToString:@"book"])
 {
  theBible.book = [attributeDict valueForKey:@"name"];
  NSLog(@"Book: %@", theBible.book);
  return;
 }

 else if([elementName isEqualToString:@"chapter"]) 
 {
  theBible.chapterID =[attributeDict objectForKey:@"id"];
  NSLog(@"Chapter: %@", theBible.chapterID);
  return;
 } 
}


- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {

}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
  namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
 if([elementName isEqualToString:@"bible"]){
   return;
 } 

}


- (void) dealloc {
 [theBible release];
 [currentElementValue release];
 [super dealloc];
}

@end

Ниже приводится вывод из консоли отладчика:

2010-12-08 19:53:10.101 BibleXML[25641:207] found file and started parsing
2010-12-08 19:53:10.102 BibleXML[25641:207] Found element: bible
2010-12-08 19:53:10.103 BibleXML[25641:207] Testament: Old Testament
2010-12-08 19:53:10.103 BibleXML[25641:207] Book: Genesis
2010-12-08 19:53:10.104 BibleXML[25641:207] Chapter: Genesis 1
2010-12-08 19:53:10.104 BibleXML[25641:207] Chapter: Genesis 2
2010-12-08 19:53:10.105 BibleXML[25641:207] Book: Exodus
2010-12-08 19:53:10.105 BibleXML[25641:207] Chapter: Exodus 1
2010-12-08 19:53:10.106 BibleXML[25641:207] Chapter: Exodus 2
2010-12-08 19:53:10.107 BibleXML[25641:207] Testament: New Testament
2010-12-08 19:53:10.107 BibleXML[25641:207] Book: Matthew
2010-12-08 19:53:10.108 BibleXML[25641:207] Chapter: Matthew 1
2010-12-08 19:53:10.108 BibleXML[25641:207] Chapter: Matthew 2
2010-12-08 19:53:10.109 BibleXML[25641:207] Book: Revelation
2010-12-08 19:53:10.109 BibleXML[25641:207] Chapter: Revelation 1
2010-12-08 19:53:10.110 BibleXML[25641:207] Chapter: Revelation 2
2010-12-08 19:53:10.110 BibleXML[25641:207] No Errors

1 Ответ

0 голосов
/ 08 декабря 2010

Вы уже анализируете это. В вызове didEndElement: просто делайте все, что хотите, с элементом. Поскольку ваш XML-файл не содержит никаких завернутых строк (вы не используете foundCharacters:), все, что вам нужно сделать, это ответить на didStartElement: и didEndElement: соответственно. Если вам нужно захватить атрибуты или выделить новую структуру данных для хранения возможных дочерних элементов, сделайте это в didStartElement:. Если вам нужно сохранить объекты в коллекции или как-то закончить обработку определенного элемента, сделайте это в didEndElement:.

Этот вопрос на самом деле не о разборе, а о любой логике, которую вы хотите задействовать в ответ на разбор.

Изменить в ответ на комментарий ниже:

Обычно я делаю следующее, чтобы сохранить объекты во время синтаксического анализа: в своем интерфейсе я объявляю коллекцию, в которую нужно сохранить объекты, и временный объект, который я использовал для хранения любых данных, которые мне нужны, перед добавлением их в коллекцию, как это

@interface MyClass : NSObject <NSXMLParserDelegate>{
    NSMutableArray *collection_;
    SomeObject *tempObject_;
}
@end

В реализации я манипулирую этими двумя объектами, обычно в didStartDocument :, didStartElement: и didEndElement:, вот так:

- (void)parserDidStartDocument:(NSXMLParser *)parser {
    collection_ = [[NSMutableArray alloc] init];
}

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict {
    //if your object is tied to a tag that wraps text (delivered in foundCharacters:), initialize it here
    tempObject_ = [[SomeObject alloc] init];
    //maybe you need the attributes....
    tempObject_.someProperty = [attributes objectForKey:@"attribute-name"];
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
    //when the tag ends, you can save it off into the collection
    [collection_ addObject:tempObject_];
    [tempObject_ release];
    tempObject_ = nil;
}

Тогда делай что хочешь с объектом коллекции. Убедитесь, что вы обрабатываете вещи памяти, такие как освобождение объекта коллекции или что-то еще. Я обычно использую что-то вроде обратного вызова делегата (моего собственного изобретения), чтобы получить коллекцию к модели, чтобы логически отделить анализ от модели.

...