2010-06-02 10 views
11

Angesichts der folgenden XML-Datei:Parsing NSXMLNode Attribute in 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> 

Wie kann ich die Attribute zugreifen ("Englisch", "chinese", "name", "a", "b" usw.) und ihre zugehörigen Werte der MOVIE-Knoten? Ich habe derzeit in Cocoa die Fähigkeit, diese Knoten zu durchlaufen, aber ich bin ratlos, wie ich auf die Daten in den MOVIE NSXMLNodes zugreifen kann.

Gibt es eine Möglichkeit, ich kann alle Werte von jedem NSXMLNode in eine Hashtable ablegen und Werte auf diese Weise abrufen?

Bin mit NSXMLDocument und NSXMLNodes.

Antwort

12

JA! Ich habe irgendwie meine eigene Frage beantwortet.

Beim Iterieren durch das XML-Dokument, anstatt jeden untergeordneten Knoten als NSXMLNode zuzuweisen, weisen Sie ihn als NSXMLElement zu. Sie können dann die Funktion attributeForName verwenden, die einen NSXMLNode zurückgibt, auf den Sie mit stringValue den Wert des Attributs abrufen können.

Da ich schlecht bin Dinge zu erklären, hier ist mein kommentierter Code. Es könnte mehr Sinn machen.

//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

Sie können auch einen Drilldown auf die gewünschten Knoten ausführen, indem Sie [xmldoc nodesForXPath: @ "/ application/movie [@ name = 'tc']" verwenden. Error] Sie können die zurückgegebenen Knoten als neuen Kontextknoten zum Auswerten verwenden weitere XPath-Ausdrücke. –

+0

Danke. Ich war nicht sicher, wie XPath-Abfragen funktionierten, aber mit Ihrem Beispiel, das mit meiner XML-Datei gegeben wurde, kann ich sehen, wie grundlegende Abfragen funktionieren. Als ich auf XCode im Internet las, war ich von den Beispielen verwirrt, weil ich nicht sicher war, in welchem ​​Kontext sie verwendet wurden. –

9

Es gibt zwei Möglichkeiten. Wenn Sie weiterhin NSXMLDocment verwenden und Sie haben eine NSXMLNode * für den ein Filmelement, können Sie dies tun:

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

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

Andernfalls können Sie schalten einen NSXMLParser stattdessen zu verwenden. Dies ist ein ereignisgesteuerter Parser, der einen Delegaten informiert, wenn er (unter anderem) Elemente analysiert hat. Die Methode, nach der Sie suchen, ist 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

Danke dreamlax! Ich habe auch meine eigene Lösung für dieses Problem gefunden, die ich auch gepostet habe. Aber ich akzeptiere deine, weil du dir Zeit und Energie genommen hast, um sie zu lösen. Danke, und ich freue mich darauf, Ihren Code auch als Referenz zu verwenden. –

+0

@ Jeffrey Kern: Es ist gut, die Dinge selbst zu lösen, schließlich hatte ich einen Fehler in meiner Antwort;) – dreamlax

+0

Heh, ich denke, deine Lösung ist ein bisschen eleganter als meins. :) –