Search code examples
iosxmlnsxmlparserfile-format

NSXMLParser strange behavior with \n


I'm developing an iOS 4 application that parses a XML file. A piece of XML is:

<?xml version="1.0" encoding="utf-8" ?>
<cards>
  <card id ="0">
    <name lang="es">The Mad</name>
    <description lang="es">...</description>
  </card>
...
</cards>

I use the following method to parse <name lang="es">The Mad</name>.

#pragma mark -
#pragma mark NSXMLParserDelegate methods

- (void)parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName 
  namespaceURI:(NSString *)namespaceURI
 qualifiedName:(NSString *)qName 
    attributes:(NSDictionary *)attributeDict
{
    NSLog(@"DidStartElement: %@", elementName);
    if ([elementName isEqualToString:@"card"])
    {
        currentCard = [[Card alloc] init];
        NSString* arcaneNumber = [attributeDict objectForKey:@"id"];
        currentCard.Number = arcaneNumber;

        return;
    }
    if ([elementName isEqualToString:@"name"])
    {
        if ([[attributeDict objectForKey:@"lang"] isEqualToString:userLanguage])
        {
            currentProperty = kNameProperty;
            return;
        }
    }
    if ([elementName isEqualToString:@"description"])
    {
        if ([[attributeDict objectForKey:@"lang"] isEqualToString:userLanguage])
        {
            currentProperty = kDescriptionProperty;
            return;
        }
    }
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    if (!currentStringValue)
    {
        // currentStringValue is an NSMutableString instance variable
        currentStringValue = [[NSMutableString alloc] initWithCapacity:50];
    }
    [currentStringValue appendString:string];
}

- (void) parser:(NSXMLParser *)parser
  didEndElement:(NSString *)elementName
   namespaceURI:(NSString *)namespaceURI
  qualifiedName:(NSString *)qName
{
    NSLog(@"DidEndElement: %@", elementName);
    if ([elementName isEqualToString:@"card"])
    {
        [cards setObject:currentCard forKey:currentCard.Number];
        [currentCard release];
        currentCard = nil;

        return;
    }

    if (currentProperty == kNameProperty)
    {
        currentProperty = kNoneProperty;
        currentCard.Name = [currentStringValue stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
        [currentStringValue release];
        currentStringValue = nil;

        return;
    }

    if (currentProperty == kDescriptionProperty)
    {
        currentProperty = kNoneProperty;
        currentCard.Description = currentStringValue;
        [currentStringValue release];
        currentStringValue = nil;

        return;
    }
}

After, parsing , I get on currentStringValue the following:

\n\nThe Mad

How can avoid these two '\n'? Why am I getting these two '\n'?

This xml file came from a Windows system, and I've used TextWrangler to covert it to Classic Mac format.


Solution

  • The foundCharacters delegate method also gets called for whitespace in between elements. It will get called if there is say a newline between <cards> and <card id=....

    I suggest clearing currentStringValue at the top of didStartElement to discard any characters found before the start of the current element and to make sure only the characters inside the current element (not between) are captured by foundCharacters.

    At the top of didStartElement, add:

    [currentStringValue release];
    currentStringValue = nil;
    


    It is possible for an element's value to contain whitespace (so removing them in didEndElement could result in saving values that don't match the xml content).