2012-10-25 3 views
0

J'essaye d'analyser un énorme document XML (décrivant un modèle 3d) avec la bibliothèque GdataxmlNode objective-c.Objective-C: Analyse XML avec gdata

Voici un échantillon de XML qui bloque moi:

<library_effects> 
    <effect name="Love_Love-fx" id="Love_Love-fx"> 
     <profile_COMMON> 
      <newparam sid="sexy-surface"> 
       <surface type="2D"> 
        <init_from>sexy</init_from> 
        <format>A8R8G8B8</format> 
       </surface> 
      </newparam> 
      .... 
     </profile_COMMON> 
    </effect> 
    .... 
</library_effects> 

Mon objectif:

  1. obtenir le nom d'effet (* Love_Love-fx *): fonctionne parfaitement

  2. obtenir le contenu de init_from (sexy): ne fonctionne pas du tout

Voici comment je l'analyse syntaxique:

xmlGetData = [xmlDoc.rootElement elementsForName:@"library_effects"]; 

//Effects infos 
int eff_c; 
NSMutableArray *eff_ids = [[NSMutableArray alloc] init]; //effect names 
NSMutableArray *eff_src = [[NSMutableArray alloc] init]; //efects sources 

for (GDataXMLElement *e in xmlGetData) 
{ 
    eff_c = [[e elementsForName:@"effect"]count];   
    NSArray *eff_node = [e elementsForName:@"effect"]; 
    for (int i = 0; i < eff_c; i++) 
    { 
     //get the effect name (id & name are the same) 
     [eff_ids addObject:[[eff_node objectAtIndex:i]attributeForName:@"id"]]; 
     //get the content of init_from 
     [eff_src addObject:[[eff_node objectAtIndex:i]elementForName:@"init_from"]]; 
    } 
} 

Mon problème: J'ai un SIGABRT sur la dernière ligne ([eff_src addObject.........) donc je ne parviens pas à obtenir le contenu de « init_from "

(car renvoie zéro. ?)

Quelqu'un pourrait-il m'aider? (? Y at-il une documentation complète & clair que je ne voyais billet de blog expliquant une partie de celui-ci)

solution Disgusting: En utilisant [[[[[[eff_node objectAtIndex:i]childAtIndex:0]childAtIndex:0]childAtIndex:0]childAtIndex:0]stri‌​ngValue];

Répondre

1

eff_node est le noeud XML effect. Ma conjecture est que la méthode elementForName: ne fonctionne pas de manière récursive et renvoie zéro car init_from n'est pas un enfant immédiat de effect.

Soit vous avez, soit effect s dans votre XML qui n'ont pas init_from nœuds qu'ils contiennent. Fondamentalement, vous ne pouvez pas ajouter de valeur nulle à un NSMutableArray. Vous devez donc tester vos deux paramètres addObject: pour zéro, par exemple, NSMutableArray et NSMutableArray.

id idAttr = [[eff_node objectAtIndex:i]attributeForName:@"id"]; 
if (idAttr != nil) 
{ 
    [eff_ids addObject:idAttr]; 
} 
GDataXMLElement* initFrom = [[eff_node objectAtIndex:i]elementForName:@"init_from"]; 
if (initFrom != nil) 
{ 
    [eff_src addObject: initFrom]; 
} 

Notez également que la ligne

NSArray *eff_node = [[NSArray alloc] init]; 

est instancié inutilement un tableau vide et dans le monde de comptage manuel de référence est une fuite de mémoire.


Je viens de regardé l'API GDataXML et il est a) non documentée (dans le sens où ils ne pouvaient pas être arsed d'écrire la documentation, et non pas le sens d'une API privée) et b) limité .

La méthode que vous utilisez n'étant pas une recherche récursive, vous disposez de deux options: implémenter votre propre recherche récursive ou utiliser l'API XPath.Le fillowing doit obtenir les nœuds que vous voulez:

NSError* myError = nil; 
NSArray* initFromNodes = [[eff_node objectAtIndex: i] nodesForXPath: @"//init_from" error: &myError]; 

La partie // du XPath signifie "un certain nombre de niveaux bas de l'arbre"

+0

en utilisant votre 'GDataXMLElement * initFrom = [[eff_node objectAtIndex: i] elementForName : @ "init_from"]; ' donne moi initFrom = nil donc même problème: x (je n'ai pas ajouté le if() car j'ai besoin de toutes ces informations dans tous les cas) – IggY

+1

@IggY Vous avez besoin de' if' parce que vous ne peut pas mettre 'nil' dans un' NSArray'. C'est ce qui provoque votre SIGABRT. Vous obtenez soit zéro parce que la méthode 'elementForName:' ​​ne recherche pas récursivement ou parce que vous avez des éléments sans sous-nœuds 'init_from'. – JeremyP

+0

Ok, j'ai eu pourquoi j'ai besoin de si, désolé c'était stupide ^^ Cependant, init_from est TOUJOURS = nil: x Alors Comment puis-je ignorer le fait que 'elementForName' n'est pas récursif? – IggY