Using NSXMLParser truncates words with accents


#1

Hello friends!

I’ve been using this method for parsing XML but I realize if my info has characters with accents this parser truncates it, for instance:

MÉRIDA (the result is ÉRIDA)
MÉXICO (the result is ÉXICO)
ORTOGRÁFICO (result is ÁFICO)

and so on…
I also tried removing accents from all these words and then this parser works like a charm, but I need this working with accents as well because of my language… this is how I do this:

-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    currentNodeContent = (NSMutableString *)[string stringByTrimmingCharactersInSet:
                                            [NSCharacterSet whitespaceAndNewlineCharacterSet]];

        NSLog(@"string added: %@", string);
 }

this is my XML Result (response obtained by using soapUI):

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <ns:CiudadesResponse xmlns:ns="http://xxx.xxx.com">
         <ns:return xsi:type="ax21:DetallPais" xmlns:ax21="http://xxx.xxx.com/xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <ax21:lista>01  -YUC -MX -MÉRIDA</ax21:lista>
            <ax21:lista>02  -YUC -MX -TIZIMÍN</ax21:lista>
            <ax21:lista>03  -YUC -MX -TICUL</ax21:lista>
            <ax21:lista>04  -YUC -MX -MOTUL DE CARRILLO PUERTO</ax21:lista>
            <ax21:lista>05  -YUC -MX -VALLADOLID</ax21:lista>
            <ax21:trasaCod>000</ax21:trasaCod>
            <ax21:trasaMsj>[INF] Transaccion exitosa</ax21:trasaMsj>
         </ns:return>
      </ns:CiudadesResponse>
   </soapenv:Body>
</soapenv:Envelope>

Console of X-Code throws this:

2012-12-20 13:41:49.520 xxx[18203:18203] string added: 01  -YUC -MX -M
2012-12-20 13:41:49.520 xxx[18203:18203] string added: ÉRIDA
2012-12-20 13:41:49.520 xxx[18203:18203] string added: 02  -YUC -MX -TIZIM
2012-12-20 13:41:49.520 xxx[18203:18203] string added: ÍN
2012-12-20 13:41:49.520 xxx[18203:18203] string added: 03  -YUC -MX -TICUL
2012-12-20 13:41:49.520 xxx[18203:18203] string added: 04  -YUC -MX -MOTUL DE CARRILLO PUERTO
2012-12-20 13:41:49.521 xxx[18203:18203] string added: 05  -YUC -MX -VALLADOLID
2012-12-20 13:41:49.521 xxx[18203:18203] string added: 000
2012-12-20 13:41:49.521 xxx[18203:18203] string added: [INF] Transaccion exitosa

and this is the full code of my parser

@interface obtenerCiudadesWS(){
    NSMutableData           *webData;
    NSURLConnection         *conn;

    NSMutableString         *currentNodeContent;
    NSXMLParser             *parser;
    BOOL                    isStatus, incompleteXML;

    obtenerCiudadObject     *ciudadActual; //objectcontainer
}
@end


@implementation obtenerCiudadesWS

@synthesize     arrayCiudades           = _arrayCiudades;        //arraycontainer
@synthesize     webServiceVacioFlag     = _webServiceVacioFlag;


//1. Crear la petición para el webservice, establecer conexión, enviar petición y obtener el XML Resultado
-(id)obtenerCiudades:(NSString *)clavePais claveEdo:(NSString *)claveEdo{

    NSString *webService = webServiceURL;
    NSString *soapMsg =  [NSString stringWithFormat:@"<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ser=\"http://xxx.xxx.com\"><soapenv:Header/><soapenv:Body><ser:Ciudades><ser:tipAplic>M</ser:tipAplic><ser:clvePais>%@</ser:clvePais><ser:clveEsta>%@</ser:clveEsta></ser:Ciudades></soapenv:Body></soapenv:Envelope>",clavePais, claveEdo];

    NSLog(@"XML ObtenerCiudades: %@", soapMsg);

    NSURL *url               = [NSURL URLWithString:[NSString stringWithFormat:@"%@WSEventos/services/WSServer",webService]];


    NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];

    NSString *msgLength      = [NSString stringWithFormat:@"%d", [soapMsg length]];
    [req addValue:@"text/xml; charset=iso-8859-1" forHTTPHeaderField:@"Content-Type"];
    [req addValue:[NSString stringWithFormat:@"%@WSEventos/services/WSServer",webService] forHTTPHeaderField:@"SOAPAction"];
    [req addValue:msgLength forHTTPHeaderField:@"Content-Length"];
    [req setHTTPMethod:@"POST"];
    [req setHTTPBody: [soapMsg dataUsingEncoding:NSUTF8StringEncoding]];


    conn = [[NSURLConnection alloc] initWithRequest:req delegate:self];
    if (conn)
        webData = [NSMutableData data];
    else
        NSLog(@"NSURLConnection initWithRequest: Failed to return a connection.");
    return self;
}

-(void) connection:(NSURLConnection *) connection didReceiveResponse:(NSURLResponse *) response {
    [webData setLength: 0];
}

-(void) connection:(NSURLConnection *) connection didReceiveData:(NSData *) data {
    [webData appendData:data];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
    NSLog(@"connection didFailWithError: %@ %@", error.localizedDescription,
          [error.userInfo objectForKey:NSURLErrorFailingURLStringErrorKey]);
}

-(void) connectionDidFinishLoading:(NSURLConnection *) connection {
    NSLog(@"DONE. Received Bytes: %d", [webData length]);
    parser = [[NSXMLParser alloc] initWithData:webData];
    [parser setDelegate:self];
    [parser setShouldResolveExternalEntities:YES];
    [parser parse];
}


//2. Descomponer el resultado

-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    currentNodeContent = (NSMutableString *)[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

        NSLog(@"string added: %@", string);
 }

-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
    if ([elementName isEqualToString:@"ns:return"]) {
        _arrayCiudades    = [[NSMutableArray alloc]init];
        isStatus        = YES;
    }
    if ([elementName isEqualToString:@"ax21:trasaMsj"]) {
        isStatus        = NO;
    }
}


-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
    NSArray *tempArray;

    if (isStatus) {
        ciudadActual = [obtenerCiudadObject alloc];
        if ([elementName isEqualToString:@"ax21:lista"] && ![currentNodeContent isEqualToString:@""]) {

            ciudadActual.claveCiudad    = currentNodeContent;
            ciudadActual.nombreCiudad   = currentNodeContent;

            tempArray = nil;
        }

        if(ciudadActual.claveCiudad != nil || ciudadActual.nombreCiudad != nil) [_arrayCiudades addObject:ciudadActual];
    }

    //Confirma que el webservice tenga correcto todos los elementos
    if ([elementName isEqualToString:@"ax21:trasaCod"] &&![currentNodeContent isEqualToString:@"000"])
    {
        incompleteXML = 1;
        self.webServiceVacioFlag = @"TRUE";
    }

    else
    {
        incompleteXML = 0;
        self.webServiceVacioFlag = @"FALSE";
    }

    if([elementName isEqualToString:@"ax21:trasaMsj"]){
        NSLog(@"Mensaje XML: %@", currentNodeContent);
    }
}
@end

result of the webservice without accents

result with accents

thanks in advance for the help friends =D

Juan


#2

I have the answer for my last issue

just modified my foundCharacters as follows

-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
     if(!currentNodeContent) currentNodeContent = [[NSMutableString alloc] initWithString:string];
     else [currentNodeContent appendString:string];
 }

this is my final result

this is the full code of my parser

#import "obtenerCiudadesWS.h"
@interface obtenerCiudadesWS(){
    NSMutableData           *webData;
    NSURLConnection         *conn;
    
    NSMutableString         *currentNodeContent;
    NSXMLParser             *parser;
    BOOL                    isStatus, incompleteXML;
    
    obtenerCiudadObject     *ciudadActual; //objectcontainer
}
@end


@implementation obtenerCiudadesWS

@synthesize     arrayCiudades           = _arrayCiudades;        //arraycontainer
@synthesize     webServiceVacioFlag     = _webServiceVacioFlag;


//1. Crear la petición para el webservice, establecer conexión, enviar petición y obtener el XML Resultado
-(id)obtenerCiudades:(NSString *)clavePais claveEdo:(NSString *)claveEdo{
    
    NSString *webService = webServiceURL;
    NSString *soapMsg =  [NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
                          "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ser=\"http://xxx.xxx.com\"><soapenv:Header/><soapenv:Body><ser:Ciudades><ser:tipAplic>M</ser:tipAplic><ser:clvePais>%@</ser:clvePais><ser:clveEsta>%@</ser:clveEsta></ser:Ciudades></soapenv:Body></soapenv:Envelope>",clavePais, claveEdo];
    
    NSLog(@"XML ObtenerCiudades: %@", soapMsg);
    
    NSURL *url               = [NSURL URLWithString:[NSString stringWithFormat:@"%@WSEventos/services/WSServer",webService]];
    
    
    NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
    
    NSString *msgLength      = [NSString stringWithFormat:@"%d", [soapMsg length]];
    [req addValue:@"text/xml; charset=iso-8859-1" forHTTPHeaderField:@"Content-Type"];
    [req addValue:[NSString stringWithFormat:@"%@WSEventos/services/WSServer",webService] forHTTPHeaderField:@"SOAPAction"];
    [req addValue:msgLength forHTTPHeaderField:@"Content-Length"];
    [req setHTTPMethod:@"POST"];
    [req setHTTPBody: [soapMsg dataUsingEncoding:NSUTF8StringEncoding]];
    
    
    conn = [[NSURLConnection alloc] initWithRequest:req delegate:self];
    if (conn)
        webData = [NSMutableData data];
    else
        NSLog(@"NSURLConnection initWithRequest: Failed to return a connection.");
    return self;
}

-(void) connection:(NSURLConnection *) connection didReceiveResponse:(NSURLResponse *) response {
    [webData setLength: 0];
}

-(void) connection:(NSURLConnection *) connection didReceiveData:(NSData *) data {
    
    [webData appendData:data];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
    NSLog(@"connection didFailWithError: %@ %@", error.localizedDescription,
          [error.userInfo objectForKey:NSURLErrorFailingURLStringErrorKey]);
}

-(void) connectionDidFinishLoading:(NSURLConnection *) connection {
    NSLog(@"DONE. Received Bytes: %d", [webData length]);

    parser = [[NSXMLParser alloc] initWithData:webData];
	[parser setDelegate:self];
	[parser setShouldResolveExternalEntities:YES];
	[parser parse];
}



//2. Descomponer el resultado para manipularlo y mostrarlo en la app
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
     if(!currentNodeContent) currentNodeContent = [[NSMutableString alloc] initWithString:string];
     else [currentNodeContent appendString:string];
 }

-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
    if ([elementName isEqualToString:@"ns:return"]) {
        _arrayCiudades    = [[NSMutableArray alloc]init];
        isStatus        = YES;
    }
    if ([elementName isEqualToString:@"ax21:trasaMsj"]) {
        isStatus        = NO;
    }
}


-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
    NSArray *tempArray;
    
    if (isStatus) {
        ciudadActual = [obtenerCiudadObject alloc];
        if ([elementName isEqualToString:@"ax21:lista"] && ![currentNodeContent isEqualToString:@""]) {

            tempArray = [currentNodeContent componentsSeparatedByString:@"-"];
            
            ciudadActual.claveCiudad    = [tempArray objectAtIndex:0];
            ciudadActual.nombreCiudad   = [tempArray objectAtIndex:3];
            
            tempArray = nil;
        }
 
        if(ciudadActual.claveCiudad != nil || ciudadActual.nombreCiudad != nil)
            [_arrayCiudades addObject:ciudadActual];
        
        currentNodeContent = nil;
    }
    
    //Confirma que el webservice tenga correcto todos los elementos
    if ([elementName isEqualToString:@"ax21:trasaCod"] &&![currentNodeContent isEqualToString:@"000"])
    {
        incompleteXML = 1;
        self.webServiceVacioFlag = @"TRUE";
    }
    
    else
    {
        incompleteXML = 0;
        self.webServiceVacioFlag = @"FALSE";
    }
    
    if([elementName isEqualToString:@"ax21:trasaMsj"]){
        NSLog(@"Mensaje XML: %@", currentNodeContent);
    }
}
@end