Jak używać NSXMLParser do parsowania elementów rodzic-dziecko o tej samej nazwie
Czy ktoś ma jakiś pomysł jak parsować poniższy xml używając modelu nsxmlparser class?
<Node>
<name> Main </name>
<Node>
<name> Child 1 </name>
</Node>
<Node>
<name> Child 2 </name>
</Node>
</Node>
Chcę zebrać wszystkie trzy nazwy z tego pliku xml, czy to możliwe, Czy muszę zmienić na parsowanie oparte na drzewie?
3 answers
Jest to częsty problem z parserami takimi jak ten, typu sax, gdzie musisz ręcznie śledzić bieżącą głębokość drzewa XML, w którym się znajdujesz. Problem, jak zawsze, polega na tym, że załadowanie całego drzewa w strukturze DOM w pamięci może być niemożliwe, w zależności od wielkości danych, które chcesz manipulować.
Poniższy kod pokazuje klasę, która wykonuje to zadanie:
#import <Foundation/Foundation.h>
@interface Test : NSObject <NSXMLParserDelegate>
{
@private
NSXMLParser *xmlParser;
NSInteger depth;
NSMutableString *currentName;
NSString *currentElement;
}
- (void)start;
@end
Oto implementacja:
#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
Jest to wynik uruchomienia wiersza poleceń narzędzie uruchamiające powyższą metodę "start":
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-05 11:20:57
- (NSInteger)columnNumber
Daje poziom zagnieżdżania NSXMLParser
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-15 11:00:27
Bardzo łatwiejszy sposób rozwiązania niż przyjęta odpowiedź, dla krótkich plików XML:
Przykład 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>
Zaimplementuj licznik:
@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;
}
Skąd będę wiedział, że numer czarownicy to węzeł czarownic ?
Widząc dziennik. Będzie to coś w stylu:
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:
Dziennik pokaże Ci numer czarownicy to każdy węzeł.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-05 02:47:28