2010-06-02 13 views
11

Dato il seguente file XML:Parsing NSXMLNode Attributi a Cocoa

<?xml version="1.0" encoding="UTF-8"?> 
<application name="foo"> 
<movie name="tc" english="tce.swf" chinese="tcc.swf" a="1" b="10" c="20" /> 
<movie name="tl" english="tle.swf" chinese="tlc.swf" d="30" e="40" f="50" /> 
</application> 

Come posso accedere agli attributi ("inglese", "cinese", "Nome", "a", "b", etc.) e i loro valori associati dei nodi MOVIE? Al momento ho in Cocoa la possibilità di attraversare questi nodi, ma non riesco a capire come accedere ai dati nel MOVIE NSXMLNodes.

C'è un modo per scaricare tutti i valori da ogni NSXMLNode in un Hashtable e recuperare i valori in questo modo?

Sto usando NSXMLDocument e NSXMLNodes.

risposta

12

SÌ! Ho risposto alla mia stessa domanda in qualche modo.

Durante l'iterazione del documento XML, invece di assegnare ogni nodo figlio come NSXMLNode, assegnarlo come NSXMLElement. È quindi possibile utilizzare la funzione attributeForName, che restituisce un NSXMLNode, al quale è possibile utilizzare stringValue per ottenere il valore dell'attributo.

Poiché non sono bravo a spiegare le cose, ecco il mio codice commentato. Potrebbe avere più senso.

//make sure that the XML doc is valid 
if (xmlDoc != nil) { 
      //get all of the children from the root node into an array 
      NSArray *children = [[xmlDoc rootElement] children]; 
      int i, count = [children count]; 

      //loop through each child 
      for (i=0; i < count; i++) { 
       NSXMLElement *child = [children objectAtIndex:i]; 

        //check to see if the child node is of 'movie' type 
        if ([child.name isEqual:@"movie"]) { 
        { 
         NSXMLNode *movieName = [child attributeForName:@"name"]; 
         NSString *movieValue = [movieName stringValue]; 

         //verify that the value of 'name' attribute of the node equals the value we're looking for, which is 'tc' 
         if ([movieValue isEqual:@"tc"]) { 
         //do stuff here if name's value for the movie tag is tc. 
         } 
        } 
      } 
    } 
+0

È anche possibile eseguire il drill down sui nodi che si desidera utilizzando [xmldoc nodesForXPath: @ "/ application/movie [@ name = 'tc']" errore: err] È possibile utilizzare i nodi restituiti come nuovo nodo di contesto per la valutazione ulteriori espressioni XPath. –

+0

Grazie. Non ero sicuro di come funzionassero le query XPath, ma con il tuo esempio fornito con il mio file XML posso vedere come funzionano le query di base. Leggendo su XCode su internet, sono stato confuso dagli esempi perché non ero sicuro del contesto in cui usarli. –

9

Ci sono due opzioni. Se si continua a utilizzare NSXMLDocment e hai un NSXMLNode * per l'elemento di un film, si può fare questo:

if ([movieNode kind] == NSXMLElementKind) 
{ 
    NSXMLElement *movieElement = (NSXMLElement *) movieNode; 
    NSArray *attributes = [movieElement attributes]; 

    for (NSXMLNode *attribute in attributes) 
    { 
     NSLog (@"%@ = %@", [attribute name], [attribute stringValue]); 
    } 
} 

In caso contrario, è possibile passare ad usare un NSXMLParser invece. Questo è un parser event driven che informa un delegato quando ha analizzato elementi (tra le altre cose). Il metodo che stai cercando è parser:didStartElement:namespaceURI:qualifiedName:attributes:

- (void) loadXMLFile 
{ 
    NSXMLParser *parser = [NSXMLParser parserWithContentsOfURL:@"file:///Users/jkem/test.xml"]; 
    [parser setDelegate:self]; 
    [parser parse]; 
} 


// ... later ... 

-  (void)   parser:(NSXMLParser *)parser 
      didStartElement:(NSString *)elementName 
       namespaceURI:(NSString *)namespaceURI 
       qualifiedName:(NSString *)qualifiedName 
        attributes:(NSDictionary *)attributeDict 
{ 
    if ([elementName isEqualToString:@"movie"]) 
    { 
     NSLog (@"%@", [attributeDict objectForKey:@"a"]); 
     NSLog (@"%d", [[attributeDict objectForKey:@"b"] intValue]); 
    } 
} 
+0

Grazie dreamlax! Ho anche trovato la mia soluzione a questo problema, che ho postato pure. Ma sto accettando il tuo poiché hai impiegato tempo ed energie per risolverlo. Grazie, e non vedo l'ora di usare il tuo codice come riferimento. –

+0

@Jeffrey Kern: È bello risolvere le cose da solo, dopotutto ho avuto un errore nella mia risposta;) – dreamlax

+0

Heh, penso che la tua soluzione sia un po 'più elegante della mia. :) –