-1

My iOS app parses xml that is fetched from a remote server (and that I can't influence in any way). When it encounters an xml tag like the following:

<tag a="x" b="y" c="z">
  this is a
  <aabb/>
  content
  <ccdd/>
  string
</tag>

It only parses the first part of the content ("this is a") while leaving out everything that follows after these single tags. It doesn't matter how many of those single tags follow, it also skips the rest if it's only one single tag. I don't really get this behavior, is there an explanation or a way to overcome this?

vikingosegundo
  • 52,040
  • 14
  • 137
  • 178
LaK
  • 99
  • 1
  • 7

1 Answers1

5

As you didnt add any code, I created my own test code and couldn't find any issue

import <Foundation/Foundation.h>

@interface ParseDelegate : NSObject  <NSXMLParserDelegate>
@property (nonatomic, copy) NSString *parsedText;
@end

@implementation ParseDelegate {
    NSMutableString *_string;
}

- (id)init {
    if (self = [super init]){
     _string = [@"" mutableCopy];
    }
    return self;
}


- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
    [_string appendString:[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];
    [_string appendString:@" "];
}

- (void)parserDidEndDocument:(NSXMLParser *)parser {
    self.parsedText = _string;
}
@end

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        ParseDelegate *parseDelegate = [ParseDelegate new];
        NSString *str = @"<tag a=\"x\" b=\"y\" c=\"z\">\n"
                "  this is a\n"
                "  <aabb/>\n"
                "  content\n"
                "  <ccdd/>\n"
                "  string\n"
                "</tag>";
        NSXMLParser *parser = [[NSXMLParser alloc] initWithData:[str dataUsingEncoding:NSUTF8StringEncoding]];
        parser.delegate = parseDelegate;
        [parser parse];
        NSLog(@"%@", parseDelegate.parsedText);
    }
    return 0;
}

results as expected in this is a content string


If you implement the …:didStart… …:didEnd… delegate methods you will see, that the single tags are correctly handled

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
        NSLog(@"start %@", elementName);
    }

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
    NSLog(@"end %@", elementName);
}

results in

start tag
start aabb
end aabb
start ccdd
end ccdd
end tag

to check for errors you can do

if([parser parse]){
    NSLog(@"%@", parseDelegate.parsedText);
} else {
    NSLog(@"%@", parser.parserError);
}

Another error checking is provided via the delegate. If an error occurs, it will be send to the delegate method parser:parseErrorOccurred:

The error contains a code. There are 94 different codes. Thanks to the fantastic IDE AppCode 2, it is easy to create a switch statement that covers all of them, while how you handle each of them is up to you.:

- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
    NSXMLParserError code = parseError.code;
    switch (code)
    {
        case NSXMLParserTagNameMismatchError:
            NSLog(@"NSXMLParserTagNameMismatchError");
            break;
        case NSXMLParserInternalError:break;
        case NSXMLParserOutOfMemoryError:break;
        case NSXMLParserDocumentStartError:break;
        case NSXMLParserEmptyDocumentError:break;
        case NSXMLParserPrematureDocumentEndError:break;
        case NSXMLParserInvalidHexCharacterRefError:break;
        case NSXMLParserInvalidDecimalCharacterRefError:break;
        case NSXMLParserInvalidCharacterRefError:break;
        case NSXMLParserInvalidCharacterError:break;
        case NSXMLParserCharacterRefAtEOFError:break;
        case NSXMLParserCharacterRefInPrologError:break;
        case NSXMLParserCharacterRefInEpilogError:break;
        case NSXMLParserCharacterRefInDTDError:break;
        case NSXMLParserEntityRefAtEOFError:break;
        case NSXMLParserEntityRefInPrologError:break;
        case NSXMLParserEntityRefInEpilogError:break;
        case NSXMLParserEntityRefInDTDError:break;
        case NSXMLParserParsedEntityRefAtEOFError:break;
        case NSXMLParserParsedEntityRefInPrologError:break;
        case NSXMLParserParsedEntityRefInEpilogError:break;
        case NSXMLParserParsedEntityRefInInternalSubsetError:break;
        case NSXMLParserEntityReferenceWithoutNameError:break;
        case NSXMLParserEntityReferenceMissingSemiError:break;
        case NSXMLParserParsedEntityRefNoNameError:break;
        case NSXMLParserParsedEntityRefMissingSemiError:break;
        case NSXMLParserUndeclaredEntityError:break;
        case NSXMLParserUnparsedEntityError:break;
        case NSXMLParserEntityIsExternalError:break;
        case NSXMLParserEntityIsParameterError:break;
        case NSXMLParserUnknownEncodingError:break;
        case NSXMLParserEncodingNotSupportedError:break;
        case NSXMLParserStringNotStartedError:break;
        case NSXMLParserStringNotClosedError:break;
        case NSXMLParserNamespaceDeclarationError:break;
        case NSXMLParserEntityNotStartedError:break;
        case NSXMLParserEntityNotFinishedError:break;
        case NSXMLParserLessThanSymbolInAttributeError:break;
        case NSXMLParserAttributeNotStartedError:break;
        case NSXMLParserAttributeNotFinishedError:break;
        case NSXMLParserAttributeHasNoValueError:break;
        case NSXMLParserAttributeRedefinedError:break;
        case NSXMLParserLiteralNotStartedError:break;
        case NSXMLParserLiteralNotFinishedError:break;
        case NSXMLParserCommentNotFinishedError:break;
        case NSXMLParserProcessingInstructionNotStartedError:break;
        case NSXMLParserProcessingInstructionNotFinishedError:break;
        case NSXMLParserNotationNotStartedError:break;
        case NSXMLParserNotationNotFinishedError:break;
        case NSXMLParserAttributeListNotStartedError:break;
        case NSXMLParserAttributeListNotFinishedError:break;
        case NSXMLParserMixedContentDeclNotStartedError:break;
        case NSXMLParserMixedContentDeclNotFinishedError:break;
        case NSXMLParserElementContentDeclNotStartedError:break;
        case NSXMLParserElementContentDeclNotFinishedError:break;
        case NSXMLParserXMLDeclNotStartedError:break;
        case NSXMLParserXMLDeclNotFinishedError:break;
        case NSXMLParserConditionalSectionNotStartedError:break;
        case NSXMLParserConditionalSectionNotFinishedError:break;
        case NSXMLParserExternalSubsetNotFinishedError:break;
        case NSXMLParserDOCTYPEDeclNotFinishedError:break;
        case NSXMLParserMisplacedCDATAEndStringError:break;
        case NSXMLParserCDATANotFinishedError:break;
        case NSXMLParserMisplacedXMLDeclarationError:break;
        case NSXMLParserSpaceRequiredError:break;
        case NSXMLParserSeparatorRequiredError:break;
        case NSXMLParserNMTOKENRequiredError:break;
        case NSXMLParserNAMERequiredError:break;
        case NSXMLParserPCDATARequiredError:break;
        case NSXMLParserURIRequiredError:break;
        case NSXMLParserPublicIdentifierRequiredError:break;
        case NSXMLParserLTRequiredError:break;
        case NSXMLParserGTRequiredError:break;
        case NSXMLParserLTSlashRequiredError:break;
        case NSXMLParserEqualExpectedError:break;
        case NSXMLParserUnfinishedTagError:break;
        case NSXMLParserStandaloneValueError:break;
        case NSXMLParserInvalidEncodingNameError:break;
        case NSXMLParserCommentContainsDoubleHyphenError:break;
        case NSXMLParserInvalidEncodingError:break;
        case NSXMLParserExternalStandaloneEntityError:break;
        case NSXMLParserInvalidConditionalSectionError:break;
        case NSXMLParserEntityValueRequiredError:break;
        case NSXMLParserNotWellBalancedError:break;
        case NSXMLParserExtraContentError:break;
        case NSXMLParserInvalidCharacterInEntityError:break;
        case NSXMLParserParsedEntityRefInInternalError:break;
        case NSXMLParserEntityRefLoopError:break;
        case NSXMLParserEntityBoundaryError:break;
        case NSXMLParserInvalidURIError:break;
        case NSXMLParserURIFragmentError:break;
        case NSXMLParserNoDTDError:break;
        case NSXMLParserDelegateAbortedParseError:break;
        default:
            break;
    }


}
vikingosegundo
  • 52,040
  • 14
  • 137
  • 178
  • +2 for an excellent, thorough answer and -1 for lack of capitalization and punctuation. – Caleb Apr 10 '13 at 20:16
  • @Caleb: feel free to correct a non-native english speaker. – vikingosegundo Apr 10 '13 at 20:17
  • Thanks for the great answer. I have checked on that stuff before, but strangely there was nothing wrong with it. I think I'll go over the xml provided to me manually again, probably they have consistency problems in their xml, but wouldn't that result in parser errors? Great answer nevertheless, thanks for the hints. – LaK Apr 10 '13 at 20:27
  • 1
    @LaK: see my edit for how to check for errors – vikingosegundo Apr 10 '13 at 20:31
  • Okay it worked, thanks for that! There was a little deviation in the parsed xml that got in trouble with case sensitive code. Thanks!!! – LaK Apr 10 '13 at 20:46