Разбор атрибутов NSXMLNode в Cocoa

Учитывая следующий XML файл:

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

Как я могу получить доступ к атрибутам ( "английский", "китайский", "имя", "а", "b" и т.д.) и связанным с ними значениям узлов MOVIE? В настоящее время у меня есть Cocoa возможность перемещения этих узлов, но я не понимаю, как я могу получить доступ к данным в MOVIE NSXMLNodes.

Есть ли способ сбросить все значения из каждого NSXMLNode в Hashtable и получить значения таким образом?

Используем NSXMLDocument и NSXMLNodes.

Ответ 1

ДА! Я как-то ответил на свой вопрос.

При повторении через XML-документ вместо назначения каждого дочернего node в качестве NSXMLNode назначьте его как NSXMLElement. Затем вы можете использовать функцию attributeForName, которая возвращает NSXMLNode, к которой вы можете использовать stringValue для получения значения атрибута.

Поскольку я плохо разбираюсь в этом, вот мой прокомментированный код. Это может иметь смысл.

//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 value for the movie tag is tc.
                        }
                    }
            }   
   }

Ответ 2

Есть два варианта. Если вы продолжаете использовать NSXMLDocment и у вас есть NSXMLNode * для элемента фильма, вы можете сделать это:

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

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

В противном случае вы можете переключиться на использование NSXMLParser. Это управляемый событиями парсер, который информирует делегата, когда он разбирает элементы (между прочим). Метод, который вы используете, 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]);
    }
}