Search code examples
objective-ciosipadhtml-encode

Decode XML Entitites using objective C


I'm looking a way to decode XML entities of some special characters like ( µ, Λ, μ, ν, π) for my iPad app. I went though the blogs and questions for hours to find a solution.

So I found this and I modified it by adding following code lines,

    else if ([scanner scanString:@"µ" intoString:NULL])
        [result appendString:@"µ"];
    else if ([scanner scanString:@"&Lambda" intoString:NULL])
        [result appendString:@"Λ"];
    else if ([scanner scanString:@"Π" intoString:NULL])
        [result appendString:@"Π"];

But I'm not feeling this as a good solution.

So, I'm looking someone's kind help for this.

XCode4 and iOS 4.3 are my development environment.


Solution

  • Assuming that you've already decided that you're going to do this parsing by hand, as opposed to using NSXMLParser and the appropriate entity calls in the delegate, then you probably want to use a table-driven parser for this.

    Since & in XML is always the introduction to an entity, it is safe to do something like this (assuming you're parsing XML and not HTML, which can have a significantly relaxed definition of what's allowed):

    if ([scanner scanString: @"&" intoString: nil]) {
        NSString *entityNameString;
        if ([scanner scanUpToString: @";" intoString: entityNameString]) {
            NSString *entityValue =[entityDictionary objectForKey: entityNameString];
            if (entityValue)
                 [result appendString: entityValue];
            else {
                 // TODO: figure out if you want to blow an error, ignore the entity, or insert the original string
                 [result appendString: [NSString stringWithFormat: @"&%@;", entityNameString]];
            }
        } else {
            // TODO: Determine if you want to blow an error, ignore, or insert the original string
            [result appendString: @"&"];
        }
    }
    

    entityDictionary would be a dictionary of key value pairs representing each entity and the string that it represents:

    NSDictionary *entityDictionary = [NSDictionary dictionaryWithObjectsAndKeys: @"µ",@"micro", @"π", @"Pi",nil];
    

    Or you could load from a plist using:

    NSDictionary *entityDictionary = [NSDictionary dictionaryWithContentsOfURL: @"myEntityList.plist"];