5

I'm attempting to parse an XML file (using NSXMLParser) from the website librarything.com. This is the first file I have ever parsed, but for the most part it seems fairly straight forward. My problem occurs when trying to parse a CDATA block; the method parser:foundCDATA: isn't called, and I can't understand why. I know my parser is set up properly because the parser:foundCharacters: method works fine. The XML data I am trying to parse looks like this 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 attribute name "description".

Any help as to why the method is not being called would be greatly appreciated!

EDIT: I ran the parser:foundCharacters: method on the description CDATA block and it returned "<". I'm assuming this means that the parser is not seeing the CDATA tag correctly. Is there anything that can be done on my end to fix this?

Scott Mielcarski
  • 760
  • 6
  • 17

1 Answers1

2

It appears the CDATA contents in the <fact> tags is being returned incrementally over multiple call backs in parser:foundCharacters. In you class where you are conforming to NSXMLParserDelegate try building up the CDATA by appending it to an NSMutableString instance, like so:

(Note: here _currentElement is an 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];
    }

}
lukestringer90
  • 492
  • 7
  • 16