2010-01-05 15 views

Respuesta

31

Este es un problema común con analizadores como este, de "tipo SAX", donde tiene que realizar un seguimiento manual de la profundidad actual del árbol XML en el que se encuentra. El problema, como siempre, es que se está cargando el árbol completo en una estructura DOM en la memoria puede ser imposible, dependiendo del tamaño de los datos que desea manipular.

El siguiente código muestra una clase que hace este trabajo:

#import <Foundation/Foundation.h> 

@interface Test : NSObject <NSXMLParserDelegate> 
{ 
@private 
    NSXMLParser *xmlParser; 
    NSInteger depth; 
    NSMutableString *currentName; 
    NSString *currentElement; 
} 

- (void)start; 

@end 

Ésta es la aplicación:

#import "Test.h" 

@interface Test() 
- (void)showCurrentDepth; 
@end 


@implementation Test 

- (void)dealloc 
{ 
    [currentElement release]; 
    [currentName release]; 
    [xmlParser release]; 
    [super dealloc]; 
} 

- (void)start 
{ 
    NSString *xml = @"<?xml version=\"1.0\" encoding=\"UTF-8\" ?><Node><name>Main</name><Node><name>Child 1</name></Node><Node><name>Child 2</name></Node></Node>"; 
    xmlParser = [[NSXMLParser alloc] initWithData:[xml dataUsingEncoding:NSUTF8StringEncoding]]; 
    [xmlParser setDelegate:self]; 
    [xmlParser setShouldProcessNamespaces:NO]; 
    [xmlParser setShouldReportNamespacePrefixes:NO]; 
    [xmlParser setShouldResolveExternalEntities:NO]; 
    [xmlParser parse]; 

} 

#pragma mark - 
#pragma mark NSXMLParserDelegate methods 

- (void)parserDidStartDocument:(NSXMLParser *)parser 
{ 
    NSLog(@"Document started", nil); 
    depth = 0; 
    currentElement = nil; 
} 

- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError 
{ 
    NSLog(@"Error: %@", [parseError localizedDescription]); 
} 

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName 
    namespaceURI:(NSString *)namespaceURI 
qualifiedName:(NSString *)qName 
    attributes:(NSDictionary *)attributeDict 
{ 
    [currentElement release]; 
    currentElement = [elementName copy]; 

    if ([currentElement isEqualToString:@"Node"]) 
    { 
     ++depth; 
     [self showCurrentDepth]; 
    } 
    else if ([currentElement isEqualToString:@"name"]) 
    { 
     [currentName release]; 
     currentName = [[NSMutableString alloc] init]; 
    } 
} 

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName 
    namespaceURI:(NSString *)namespaceURI 
qualifiedName:(NSString *)qName 
{ 

    if ([elementName isEqualToString:@"Node"]) 
    { 
     --depth; 
     [self showCurrentDepth]; 
    } 
    else if ([elementName isEqualToString:@"name"]) 
    { 
     if (depth == 1) 
     { 
      NSLog(@"Outer name tag: %@", currentName); 
     } 
     else 
     { 
      NSLog(@"Inner name tag: %@", currentName); 
     } 
    } 
}   

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string 
{ 
    if ([currentElement isEqualToString:@"name"]) 
    { 
     [currentName appendString:string]; 
    } 
} 

- (void)parserDidEndDocument:(NSXMLParser *)parser 
{ 
    NSLog(@"Document finished", nil); 
} 

#pragma mark - 
#pragma mark Private methods 

- (void)showCurrentDepth 
{ 
    NSLog(@"Current depth: %d", depth); 
} 

@end 

Este es el resultado de ejecutar una herramienta de línea de comando que activa el "inicio" método anterior:

Document started 
Current depth: 1 
Outer name tag: Main 
Current depth: 2 
Inner name tag: Child 1 
Current depth: 1 
Current depth: 2 
Inner name tag: Child 2 
Current depth: 1 
Current depth: 0 
Document finished 
+0

gracias por su solución, funciona bien para mí. El archivo xml es largo, lo he reducido para que se ajuste a la pregunta. –

5
- (NSInteger)columnNumber 

le da el nivel de anidamiento de NSXMLParser

-1

Una forma muy fácil de resolver lo que la respuesta aceptada, para los archivos XML cortos: ejemplo

XML:

<cotacoes> 
    <bovespa> 
      <cotacao>50058</cotacao> 
      <variacao>-0.16</variacao> 
    </bovespa> 
    <dolar> 
      <cotacao>3.4610</cotacao> 
      <variacao>+0.29</variacao> 
    </dolar> 
    <euro> 
      <cotacao>3.7673</cotacao> 
      <variacao>-0.25</variacao> 
    </euro> 
    <atualizacao>04/08/15 - 18:14</atualizacao> 
</cotacoes> 

Implementar un contador:

@implementation className{ 
    int parserCounter; 
} 

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

    NSLog(@"%d: %@",contadorParser,string); 

    if (parserCounter == 3) doAnythingFor3; 
    if (parserCounter == 5) doAnythingFor5; 
    if (parserCounter == 9) doAnythingFor9; 
    if (parserCounter == 11) doAnythingFor11; 
    if (parserCounter == 15) doAnythingFor15; 
    if (parserCounter == 17) doAnythingFor17; 
    if (parserCounter == 20) doAnythingFor20; 

} 

¿Cómo sé que el número de bruja es el nodo brujo? Al ver el registro. Será algo así como:

2015-08-04 23:36:08.070 Tesouro Direto[7252:1554402] 1:  
2015-08-04 23:36:08.070 Tesouro Direto[7252:1554402] 2:  
2015-08-04 23:36:08.071 Tesouro Direto[7252:1554402] 3:  50058 
2015-08-04 23:36:08.105 Tesouro Direto[7252:1554402] 4:  
2015-08-04 23:36:08.105 Tesouro Direto[7252:1554402] 5:  -0.16 
2015-08-04 23:36:08.131 Tesouro Direto[7252:1554402] 6:  
2015-08-04 23:36:08.132 Tesouro Direto[7252:1554402] 7:  
2015-08-04 23:36:08.132 Tesouro Direto[7252:1554402] 8:  
2015-08-04 23:36:08.132 Tesouro Direto[7252:1554402] 9:  3.4610 
2015-08-04 23:36:08.156 Tesouro Direto[7252:1554402] 10:  
2015-08-04 23:36:08.156 Tesouro Direto[7252:1554402] 11: +0.29 
2015-08-04 23:36:08.180 Tesouro Direto[7252:1554402] 12:  
2015-08-04 23:36:08.180 Tesouro Direto[7252:1554402] 13:  
2015-08-04 23:36:08.180 Tesouro Direto[7252:1554402] 14:  
2015-08-04 23:36:08.180 Tesouro Direto[7252:1554402] 15: 3.7673 
2015-08-04 23:36:08.203 Tesouro Direto[7252:1554402] 16:  
2015-08-04 23:36:08.203 Tesouro Direto[7252:1554402] 17: -0.25 
2015-08-04 23:36:08.226 Tesouro Direto[7252:1554402] 18:  
2015-08-04 23:36:08.227 Tesouro Direto[7252:1554402] 19:  
2015-08-04 23:36:08.227 Tesouro Direto[7252:1554402] 20: 04/08/15 - 18:14 
2015-08-04 23:36:08.227 Tesouro Direto[7252:1554402] 21: 

El registro le mostrará el número de bruja en cada nodo.

Cuestiones relacionadas