2 votes

Comment utiliser NSXMLParser pour extraire et regrouper des nœuds spécifiques à partir d'un fichier xml en Objective-C/iOS?

Étant donné cette structure XML à partir de (http://localhost:3000/route.xml):

     20:01
     Place a
     Place b 
     20:16
     Walking

      20:16
      Place b
      Place c 
      20:32
      By car

En utilisant le code Objective-C suivant :

Implémentation de la vue

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Effectuer une configuration supplémentaire après le chargement de la vue, généralement à partir d'un nib.
    // URL localhost à des fins de test
    NSURL *url = [[NSURL alloc] initWithString:@"http://localhost:3000/route.xml"];

    // Initialiser l'analyseur
    NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
    [xmlParser setDelegate:self];   

    //Commencer l'analyse du fichier XML.
    BOOL success = [xmlParser parse];

    if(success)
        NSLog(@"Aucune erreur");
    else
        NSLog(@"Erreurs !!!!!!!!E!!!");
}

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

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

        if([elementName isEqualToString:@"trip0"]) {
            //Initialiser le tableau.
            NSLog(@"Trouvé trip0 !");
        }

        NSLog(@"Traitement de l'élément : %@", elementName);
    }

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

        NSLog(@"Traitement de la valeur : %@", string);

    }

Je suis capable d'obtenir ceci comme sortie :

2011-11-16 19:34:06.006 SandboxTabBar[11754:11603] Traitement de l'élément : objects
2011-11-16 19:34:06.008 SandboxTabBar[11754:11603] Traitement de la valeur : 

2011-11-16 19:34:06.009 SandboxTabBar[11754:11603] Traitement de l'élément : object
2011-11-16 19:34:06.009 SandboxTabBar[11754:11603] Traitement de la valeur : 

2011-11-16 19:34:06.010 SandboxTabBar[11754:11603] Trouvé trip0 !!
2011-11-16 19:34:06.010 SandboxTabBar[11754:11603] Traitement de l'élément : trip0
2011-11-16 19:34:06.011 SandboxTabBar[11754:11603] Traitement de la valeur : 

2011-11-16 19:34:06.011 SandboxTabBar[11754:11603] Traitement de l'élément : departure
2011-11-16 19:34:06.012 SandboxTabBar[11754:11603] Traitement de la valeur : 20:01
2011-11-16 19:34:06.012 SandboxTabBar[11754:11603] Traitement de la valeur : 

2011-11-16 19:34:06.013 SandboxTabBar[11754:11603] Traitement de l'élément : start
2011-11-16 19:34:06.013 SandboxTabBar[11754:11603] Traitement de la valeur : Place a
2011-11-16 19:34:06.014 SandboxTabBar[11754:11603] Traitement de la valeur : 

2011-11-16 19:34:06.015 SandboxTabBar[11754:11603] Traitement de l'élément : end
2011-11-16 19:34:06.015 SandboxTabBar[11754:11603] Traitement de la valeur : Place b
2011-11-16 19:34:06.207 SandboxTabBar[11754:11603] Traitement de la valeur : 

2011-11-16 19:34:06.208 SandboxTabBar[11754:11603] Traitement de l'élément : arrival
2011-11-16 19:34:06.209 SandboxTabBar[11754:11603] Traitement de la valeur : 20:16
2011-11-16 19:34:06.210 SandboxTabBar[11754:11603] Traitement de la valeur : 

2011-11-16 19:34:06.211 SandboxTabBar[11754:11603] Traitement de l'élément : how
2011-11-16 19:34:06.212 SandboxTabBar[11754:11603] Traitement de la valeur : walking
2011-11-16 19:34:06.213 SandboxTabBar[11754:11603] Traitement de la valeur :  15 min 
2011-11-16 19:34:06.214 SandboxTabBar[11754:11603] Traitement de la valeur : 

2011-11-16 19:34:06.215 SandboxTabBar[11754:11603] Traitement de la valeur : 

2011-11-16 19:34:06.216 SandboxTabBar[11754:11603] Traitement de la valeur : 

2011-11-16 19:34:06.217 SandboxTabBar[11754:11603] Traitement de l'élément : object
2011-11-16 19:34:06.218 SandboxTabBar[11754:11603] Traitement de la valeur : 

2011-11-16 19:34:06.219 SandboxTabBar[11754:11603] Traitement de l'élément : trip1
2011-11-16 19:34:06.220 SandboxTabBar[11754:11603] Traitement de la valeur : 

2011-11-16 19:34:06.221 SandboxTabBar[11754:11603] Traitement de l'élément : departure
2011-11-16 19:34:06.222 SandboxTabBar[11754:11603] Traitement de la valeur : 20:32
2011-11-16 19:34:06.223 SandboxTabBar[11754:11603] Traitement de la valeur:

2011-11-16 19:34:06.221 SandboxTabBar[11754:11603] Traitement de l'élément : start
2011-11-16 19:34:06.222 SandboxTabBar[11754:11603] Traitement de la valeur : Place b
2011-11-16 19:34:06.223 SandboxTabBar[11754:11603] Traitement de la valeur:

Et ainsi de suite ...

Je veux remplir des UITableViews avec du contenu comme ceci :

"Le départ du trajet 0 est à 20:01 de Place A à Place b et est arrivé à 20:16 en marchant."

et

"Le départ du trajet 1 est à 20:16 de Place b à Place c et est arrivé à 20:32 en voiture"

Il doit y avoir un moyen plus simple de sélectionner et de combiner les nœuds dont j'ai besoin dans le fichier XML.

Comment parvenir à un tel résultat avec le fichier XML donné ?

2voto

Il semble que vous pourriez utiliser un analyseur DOM avec XPath. Un analyseur DOM vous permet de parcourir la structure arborescente XML au lieu de parser l'ensemble du document et XPath vous permet de interroger et de filtrer les nœuds.

Jetez un œil à GDataXMLNode de Google. Cet analyseur est l'une des possibilités les plus simples pour cela, des tutoriels peuvent être trouvés, exemple http://www.raywenderlich.com/725/how-to-read-and-write-xml-documents-with-gdataxml

2voto

Tim Dean Points 5161

Un parseur DOM facilite beaucoup les choses dans des cas comme celui-ci, mais cela signifie (a) choisir une bibliothèque qui prend en charge le DOM sur iOS, comprendre comment cela fonctionne, ses particularités, etc et (b) avoir l'intégralité du document XML en mémoire avant de le parser et de remplir votre modèle de tableau. Aucun de ces deux points n'est fondamental pour de nombreux cas, mais parfois des problèmes de mémoire peuvent vous faire renoncer au DOM.

Si vous voulez éviter ces problèmes potentiels pour votre application, ce n'est pas si difficile d'implémenter ce que vous voulez en utilisant NSXMLParser. Pour commencer, définissez une classe qui représente un "Voyage" et donnez à cette classe les propriétés que vous souhaitez pour chaque voyage (début, fin, arrivée, etc). Ensuite, dans votre classe déléguée du parser, définissez quelques ivars pour contenir un tableau mutable d'objets Voyage, un objet "currentTrip" que vous pouvez remplir au fur et à mesure, et un tampon de caractères mutable que vous pouvez utiliser pour capturer les caractères analysés par le parser.

Avec tout cela en place, vous pouvez implémenter quelque chose comme ce qui suit dans la logique de votre délégué du parser :

- (void)parserDidStartDocument:(NSXMLParser *)parser 
{
    NSLog(@"Le document a commencé", 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(@"Voyage trouvé : %@ !", elementName);
        currentTrip = [[Trip alloc] initWithName:elementName];
    }
    else {
        characterBuffer = [[NSMutableString alloc] init];
    }

    NSLog(@"Élément en cours de traitement : %@", elementName);
}

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

    NSLog(@"Valeur en cours de traitement : %@", 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"){
        // Définissez la valeur de début
        NSString *value = [characterBuffer stringByTrimmingCharactersInSet:[NSCharacterSet  whitespaceAndNewlineCharacterSet]];
        [currentTrip setStart:value];
    }
    // Traiter chaque autre propriété de voyage qui vous intéresse avec des else if séparés

}

C'est simplement la structure de base du code que vous voulez, pas nécessairement optimisé. En particulier, je n'ai pas inclus de libérations pour éviter les fuites de mémoire, ce que vous auriez besoin de faire si vous n'utilisez pas ARC. De plus, j'ai créé un nouvel objet characterBuffer au début de chaque élément pouvant contenir du texte qui vous intéresse : Cela pourrait être fait de manière plus intelligente avec un peu plus de soin et de réflexion. Vous avez compris l'idée cependant.

Dans l'ensemble, cette approche peut être un peu fastidieuse mais ce n'est pas difficile et elle peut fonctionner beaucoup mieux que l'analyse DOM dans certains cas, si c'est quelque chose d'important pour votre application.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X