Parsing CDATA XML Blocks

I am trying to parse an XML file (using NSXMLParser) from librarything.com. This is the first file I have ever parsed, but for the most part it seems pretty straight forward. My problem occurs when trying to parse a CDATA block; parser: foundCDATA: method is not called, and I cannot understand why. I know that my parser is configured correctly, because the parser: foundCharacters: method works fine. The XML data I'm trying to execute is as follows http://www.librarything.com/services/rest/1.1/?method=librarything.ck.getwork&isbn=030788743X&apikey=d231aa37c9b4f5d304a60a3d0ad1dad4 , and the CDATA block occurs inside the element with the name "description".

Any help regarding why the method is not called would be greatly appreciated!

EDIT: I ran the parser: foundCharacters: method in the description of the CDATA block, and it returned "<". I assume this means that the parser does not see the CDATA label correctly. Is there anything that can be done at my end to fix this?

+5
source share
1 answer

It appears that the contents of the CDATA in the tags is <fact>returned incrementally on several callbacks in parser:foundCharacters. In your class where you match NSXMLParserDelegate, try creating a CDATA by adding it to an NSMutableString instance, for example:

(Note: here _currentElement is a NSString property, and _factString is an NSMutableString property)

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict {    
    self.currentElement = elementName;
    if ([_currentElement isEqualToString:@"fact"]) {
        // Make a new mutable string to store the fact string
        self.factString = [NSMutableString string];
    }

}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
    if ([elementName isEqualToString:@"fact"]) {
        // If fact string starts with CDATA tags then just get the CDATA without the tags
        NSString *prefix = @"<![CDATA[";
        if ([_factString hasPrefix:prefix]) {
            NSString *cdataString = [_factString substringWithRange:NSMakeRange((prefix.length+1), _factString.length - 3 -(prefix.length+1))];
            // Do stuff with CDATA here...
            NSLog(@"%@", cdataString);
            // No longer need the fact string so make a new one ready for next XML CDATA
            self.factString = [NSMutableString string];

        }
    }

}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
    if ([_currentElement isEqualToString:@"fact"]) {
        // If we are at a fact element, append the string
        // CDATA is returned to this method in more than one go, so build the string up over time
        [_factString appendString:string];
    }

}
+2
source

All Articles