Reputation: 387
Being said that I understand the basic parsing of XML files with NSXMLParser, I have the following situation, where I have several elements <table_data>...</table_data>
which differ from each other for the value of a certain attribute, so, for example:
<table_data attr="one">...</table_data>
<table_data attr="two">...</table_data>
<table_data attr="three">...</table_data>
While in didStartElement, I'd like that the parser takes into account the <table_data>
element as the start element only if it has the attr="one"
.
This would imply that in foundCharacters I could get only the content of children elements of <table_data attr="one">
but not of <table_data attr="two">
, <table_data attr="three">
, etc.
By now, I try this:
- (void)parser:(NSXMLParser*)parser didStartElement:(NSString *)elementName namespaceURI:(NSString*)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary*)attributeDict {
elementoCorrente = [elementName copy];
if ([elementName isEqualToString:@"table_data"]) {
if ([[attributeDict objectForKey:@"attr"] isEqualToString:@"one"]) {
stringDesc = [[NSMutableString alloc] init];
}
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if ([elementoCorrente isEqualToString:@"field"]) {
[stringDesc appendString:string];
NSLog(@"%@",string);
}
}
But what I get is the log of the content of the <field>
element, child of all the <table_data>
.
Is there a way to print only the content of the <field>
element, if child of <table_data attr="one">
?
Thanks
Fabio
Upvotes: 1
Views: 956
Reputation: 437422
The problem is that you do nothing to stop foundCharacters
from appending data for the other occurrences of table_data
. You could have your didStartElement
save the attributeDict[@"attr"]
value, too, and then foundCharacters
could check both elementoCorrente
as well as this new ivar in which you're holding the attributeDict[@"attr"]
value. For example:
- (void)parser:(NSXMLParser*)parser didStartElement:(NSString *)elementName namespaceURI:(NSString*)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary*)attributeDict {
elementoCorrente = nil;
atributoCorrente = nil;
if ([elementName isEqualToString:@"table_data"]) {
if ([attributeDict[@"attr"] isEqualToString:@"one"]) {
elementoCorrente = [elementName copy];
atributoCorrente = [attributeDict[@"attr"] copy];
stringDesc = [[NSMutableString alloc] init];
}
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if ([elementoCorrente isEqualToString:@"table_data"] && [atributoCorrente isEqualToString:@"one"]) {
[stringDesc appendString:string];
}
}
Frankly, you probably want a didEndElement
implementation, too, that saves stringDesc
wherever you wanted to save it, and then sets elementoCorrente
to nil
.
Upvotes: 3
Reputation: 23637
Perhaps the code fragment is missing something, but from what you are showing here, to print the content of all the field
tags is the expected behavior, since the only test you make in the parser:foundCharacters:
method is if the current element is field
.
You could add a flag indicating that you are inside the table_data
with attr_one
. Something like:
if ([[attributeDict objectForKey:@"attr"] isEqualToString:@"one"]) {
stringDesc = [[NSMutableString alloc] init];
insideTableOne = YES;
}
And then, in the parser:foundCharacters:
also test if insideTableOne
is true before appending the string.
This test is also necessary so your program won't crash if it finds a table_data
without the expected attribute. If that happens, stringDesc
won't have been instantiated yet.
Upvotes: 1