2010-01-05 10 views

risposta

31

Questo è un problema comune con parser come questo, di "tipo SAX", in cui è necessario tenere traccia manualmente della profondità attuale dell'albero XML in cui ci si trova. Il problema, come sempre, è che il caricamento l'intero albero in una struttura DOM in memoria può essere impossibile, a seconda delle dimensioni dei dati che si desidera manipolare.

Il codice seguente mostra una classe che fa questo lavoro:

#import <Foundation/Foundation.h> 

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

- (void)start; 

@end 

Questa è l'implementazione:

#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 

Questo è il risultato di esecuzione di uno strumento a riga di comando che fa scattare il "start" metodo di cui sopra:

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

grazie per la soluzione, funziona bene per me. Il file xml è lungo, l'ho ridotto per adattarlo alla domanda. –

5
- (NSInteger)columnNumber 

ti dà il livello di nidificazione di NSXMLParser

-1

Un modo molto più facile da risolvere esso che la risposta accettata, per i file XML brevi: esempio

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> 

implementare un contatore:

@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; 

} 

Come faccio a sapere che il numero di streghe è il nodo strega? Vedendo il registro. Sarà qualcosa del tipo:

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: 

Il registro mostrerà che il numero di streghe è ogni nodo.

Problemi correlati