Как использовать NSXMLParser для извлечения и группировки определенных узлов из файла XML в Objective-C / iOS? - PullRequest
2 голосов
/ 17 ноября 2011

Учитывая эту структуру XML из (http://localhost:3000/route.xml):

<objects type="array">
  <object>
    <trip0>
     <departure>20:01</departure>
     <start>Place a</start>
     <end>Place b </end>
     <arrival>20:16</arrival>
     <how>Walking</how>
    </trip0>
  </object>
  <object>
    <trip1>
      <departure>20:16</departure>
      <start>Place b</start>
      <end>Place c </end>
      <arrival>20:32</arrival>
      <how>By car</how>
     </trip1>
  </object>
</objects> 

Используя следующий код Objective-C:

реализация представления

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    // URL localhost for testing purposes
    NSURL *url = [[NSURL alloc] initWithString:@"http://localhost:3000/route.xml"];

    // Init parser
    NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
    [xmlParser setDelegate:self];   

    //Start parsing the XML file.
    BOOL success = [xmlParser parse];

    if(success)
        NSLog(@"No Errors");
    else
        NSLog(@"Errors !!!!!!!!E!!!");
}


      #pragma mark XMLParser delegate
    - (void)parserDidStartDocument:(NSXMLParser *)parser 
    {
        NSLog(@"Document started", nil);
       }


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

        if([elementName isEqualToString:@"trip0"]) {
            //Initialize the array.
            NSLog(@"Found trip0 !");
        }

        NSLog(@"Processing Element: %@", elementName);
    }

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

        NSLog(@"Processing Value: %@", string);

    }

Я могу получить это как вывод:

2011-11-16 19:34:06.006 SandboxTabBar[11754:11603] Processing Element: objects
2011-11-16 19:34:06.008 SandboxTabBar[11754:11603] Processing Value: 

2011-11-16 19:34:06.009 SandboxTabBar[11754:11603] Processing Element: object
2011-11-16 19:34:06.009 SandboxTabBar[11754:11603] Processing Value: 

2011-11-16 19:34:06.010 SandboxTabBar[11754:11603] Found trip0 !!
2011-11-16 19:34:06.010 SandboxTabBar[11754:11603] Processing Element: trip0
2011-11-16 19:34:06.011 SandboxTabBar[11754:11603] Processing Value: 

2011-11-16 19:34:06.011 SandboxTabBar[11754:11603] Processing Element: departure
2011-11-16 19:34:06.012 SandboxTabBar[11754:11603] Processing Value: 20:01
2011-11-16 19:34:06.012 SandboxTabBar[11754:11603] Processing Value: 

2011-11-16 19:34:06.013 SandboxTabBar[11754:11603] Processing Element: start
2011-11-16 19:34:06.013 SandboxTabBar[11754:11603] Processing Value: Place a
2011-11-16 19:34:06.014 SandboxTabBar[11754:11603] Processing Value: 

2011-11-16 19:34:06.015 SandboxTabBar[11754:11603] Processing Element: end
2011-11-16 19:34:06.015 SandboxTabBar[11754:11603] Processing Value: Place b
2011-11-16 19:34:06.207 SandboxTabBar[11754:11603] Processing Value: 

2011-11-16 19:34:06.208 SandboxTabBar[11754:11603] Processing Element: arrival
2011-11-16 19:34:06.209 SandboxTabBar[11754:11603] Processing Value: 20:16
2011-11-16 19:34:06.210 SandboxTabBar[11754:11603] Processing Value: 

2011-11-16 19:34:06.211 SandboxTabBar[11754:11603] Processing Element: how
2011-11-16 19:34:06.212 SandboxTabBar[11754:11603] Processing Value: walking
2011-11-16 19:34:06.213 SandboxTabBar[11754:11603] Processing Value:  15 min 
2011-11-16 19:34:06.214 SandboxTabBar[11754:11603] Processing Value: 

2011-11-16 19:34:06.215 SandboxTabBar[11754:11603] Processing Value: 

2011-11-16 19:34:06.216 SandboxTabBar[11754:11603] Processing Value: 

2011-11-16 19:34:06.217 SandboxTabBar[11754:11603] Processing Element: object
2011-11-16 19:34:06.218 SandboxTabBar[11754:11603] Processing Value: 

2011-11-16 19:34:06.219 SandboxTabBar[11754:11603] Processing Element: trip1
2011-11-16 19:34:06.220 SandboxTabBar[11754:11603] Processing Value: 

2011-11-16 19:34:06.221 SandboxTabBar[11754:11603] Processing Element: departure
2011-11-16 19:34:06.222 SandboxTabBar[11754:11603] Processing Value: 20:32
2011-11-16 19:34:06.223 SandboxTabBar[11754:11603] Processing Value:

2011-11-16 19:34:06.221 SandboxTabBar[11754:11603] Processing Element: start
2011-11-16 19:34:06.222 SandboxTabBar[11754:11603] Processing Value: Place b
2011-11-16 19:34:06.223 SandboxTabBar[11754:11603] Processing Value:

И так далее ...

Я хочу заполнить UITableviews таким содержимым:

«Депутат поездки 0 находится в 20:01 от места А до места b и прибыл в 20:16 пешком»

и

«Отправление первой поездки в 20:16 с места b на место c и прибытие в 20:32 на машине»

Должен быть более простой способ выбора и объединения нужных мне узлов из файла XML.

Как добиться такого результата с данным XML-файлом?

Ответы [ 2 ]

2 голосов
/ 17 ноября 2011

Синтаксический анализатор DOM делает вещи намного проще для таких вещей, но это означает (а) выбор библиотеки, которая поддерживает DOM на iOS, выяснение того, как она работает, ее особенности и т. Д. И (б) наличие всего документа XMLв памяти, прежде чем разобрать его и заполнить модель таблицы.Во многих случаях это не имеет большого значения, но иногда проблемы с памятью могут вынудить вас отказаться от DOM.

Если вы хотите избежать этих потенциальных проблем для своего приложения, не так сложно реализовать то, что выхочу использовать NSXMLParser.Для начала определите класс, который представляет «Поездку», и присвойте этому классу нужные свойства для каждой поездки (начало, конец, прибытие и т. Д.).Затем в своем классе делегата синтаксического анализатора определите несколько иваров для хранения изменяемого массива объектов Trip, объекта «currentTrip», который можно заполнять по ходу работы, и буфера изменяемых символов, который можно использовать для захвата символов, отсканированных синтаксическим анализатором.

Имея их, вы можете реализовать что-то вроде следующего в вашей логике делегата синтаксического анализатора:

- (void)parserDidStartDocument:(NSXMLParser *)parser 
{
    NSLog(@"Document started", nil);
    allTrips = [[NSMutableArray alloc] init];
   }


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

    if([elementName hasPrefix:@"trip"]) {
        NSLog(@"Found trip: %@ !", elementName);
        currentTrip = [[Trip alloc] initWithName:elementName];
    }
    else {
        characterBuffer = [[NSMutableString alloc] init];
    }

    NSLog(@"Processing Element: %@", elementName);
}

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

    NSLog(@"Processing Value: %@", string);
    [characterBuffer appendString:string];
}

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

    if([elementName hasPrefix:@"trip"]) {
        [allTrips addObject:currentTrip];
    }
    else if ([elementName isEqualToString:@"start"){
        // Set start value
        NSString *value = [characterBuffer stringByTrimmingCharactersInSet:[NSCharacterSet  whitespaceAndNewlineCharacterSet]];
        [currentTrip setStart:value];
    }
    // Handle each other trip property you care about with separate else if's

}

Это просто базовая структура кода, которую вы хотите, не обязательно оптимизировать.В частности, я не включил никаких выпусков, чтобы избежать утечек памяти, которые вам понадобятся, если вы не используете ARC.Кроме того, я создал новый объект characterBuffer в начале каждого элемента, который может включать в себя текст, который вам небезразличен: это может быть сделано более разумно, с небольшим вниманием и вниманием.Вы понимаете, хотя.

В целом, этот подход может быть немного утомительным, но он также не сложен, и в некоторых случаях он может работать немного лучше, чем анализ DOM, если это то, чтофактор для вашего приложения.

2 голосов
/ 17 ноября 2011

Похоже, вы могли бы использовать DOM-парсер с XPath. Синтаксический анализатор DOM позволяет вам перебирать древовидную структуру XML вместо синтаксического анализа всего, а XPath позволяет запрашивать и фильтровать узлы.

Посмотрите на GDataXMLNode от Google. Этот синтаксический анализатор является одной из простых возможностей сделать это, учебники можно найти, например http://www.raywenderlich.com/725/how-to-read-and-write-xml-documents-with-gdataxml

...