NSXMLParser with UTF8 Data - objective-c

I'm having a really hard time trying to figure this out and would really appreciate any help.
I'm trying to parse a utf 8 string with NSXMLParser but it won't work.
here is my string
<?xml version="1.0" encoding="UTF-8"?><host><type>mac</type><port>62181</port><address>192.168.1.159</address><hostname>Samuel’s%20Mac%20Book</hostname><username>samuelw</username></host>
and here the parsing code
- (void) parse:(NSString*)XMLEncodedString withLength:(int)l_length {
#ifndef NDEBUG
NSLog(#"Received lookup %#",XMLEncodedString);
#endif
NSData* data=[XMLEncodedString dataUsingEncoding:NSUTF8StringEncoding];
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
[parser setDelegate:self]; // The parser calls methods in this class
[parser setShouldProcessNamespaces:NO]; // We don't care about namespaces
[parser setShouldReportNamespacePrefixes:NO]; //
[parser setShouldResolveExternalEntities:NO]; // We just want data, no other stuff
[parser parse]; // Parse that data..
[parser release];
}
the XMLEncodedString is constructed like this
- (void) checkForReceive {
//NSLog(#"listener: waiting to recvfrom...\n");
addr_len = sizeof their_addr;
if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN-1 , 0,
(struct sockaddr *)&their_addr, &addr_len)) == -1) {
perror("recvfrom");
return;
}
buf[numbytes] = '\0';
NSString * string = [[NSString alloc] initWithUTF8String:buf];
[self parse:string withLength:numbytes];
[string release];
}
my problem is coming from the Unicode Character 'RIGHT SINGLE QUOTATION MARK' (U+2019) that I have in my string and I am getting this error:
2010-07-19 17:13:35.734 SwypeSendForMac2[34354:4233] Error Domain=NSXMLParserErrorDomain Code=73 "The operation couldn’t be completed. (NSXMLParserErrorDomain error 73.)"
2010-07-19 17:13:35.736 SwypeSendForMac2[34354:4233] Error Domain=NSXMLParserErrorDomain Code=76 "The operation couldn’t be completed. (NSXMLParserErrorDomain error 76.)"

In your connection method that calls the xml, try replacing any problem characters with something like this:
NSString *final = [connRespStr
stringByReplacingOccurrencesOfString:#"&" withString:#" and "];
The above line replaces all ampersands with and, maybe use this to replace the singe quotes?
Also, I believe 'error 76' has something to do with not closing an xml tag.
EDIT: Just realized how old this is, maybe the above info will be worthwhile to future searchers.

Related

How to use blocks to handle errors returned by NS methods

I created a file using the following code:
NSMutableString *tabString = [NSMutableString stringWithCapacity:0]; // it will automatically expand
// write column headings <----- TODO
// now write out the data to be exported
for(int i = 0; i < booksArray.count; i++) {
[tabString appendString:[NSString stringWithFormat:#"%#\t,%#\t,%#\t\n",
[[booksArray objectAtIndex:i] author],
[[booksArray objectAtIndex:i] binding],
[[booksArray objectAtIndex:i] bookDescription]]];
}
if (![self checkForDataFile: #"BnN.tab"]) // does the file exist?
[[NSFileManager defaultManager] createFileAtPath:documentsPath contents: nil attributes:nil]; // create it if not
NSFileHandle *handle;
handle = [NSFileHandle fileHandleForWritingAtPath: [NSString stringWithFormat:#"%#/%#",documentsPath, #"BnN.tab"]]; // <---------- userID?
[handle truncateFileAtOffset:[handle seekToEndOfFile]]; // tell handle where's the file fo write
[handle writeData:[tabString dataUsingEncoding:NSUTF8StringEncoding]]; //position handle cursor to the end of file (why??)
This is the code I am using to read back the file (for debugging purposes):
// now read it back
NSString* content = [NSString stringWithContentsOfFile:[NSString stringWithFormat:#"%#/%#",documentsPath, #"BnN.tab"]
encoding:NSUTF8StringEncoding
error: ^{ NSLog(#"error: %#", (NSError **)error);
}];
I am getting 2 build errors on this last statement that says:
Sending 'void (^)(void)' to parameter of incompatible type 'NSError *__autoreleasing *'
and
Use of undeclared identifier 'error'
This is the first time I am using a block to handle method returned errors; I was unable to find any docs in SO or Google showing how to do this. What am I doing wrong?
That function is expecting an NSError** parameter, not a block. The way you should be calling it is something like:
NSError *error = nil;
NSString* content = [NSString stringWithContentsOfFile: [NSString stringWithFormat:#"%#/%#", documentsPath, #"BnN.tab"]
encoding: NSUTF8StringEncoding
error: &error];
if (content == nil) {
NSLog("error: %#", error);
}

Parsing a .csv file from a server with Objective-C

I have looked for an answer of a long time and still not found one so I thought I'd ask the question myself.
In my iPad app, I need to have the capability of parsing a .csv file in order to populate a table. I am using http://michael.stapelberg.de/cCSVParse to parse the csv files. However, I have only been successful in parsing local files. I have been trying to access a file from a server but am getting nowhere.
Here is my code to parse a local .csv file:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 1)
{
//UITextField *reply = [alertView textFieldAtIndex:buttonIndex];
NSString *fileName = input.text;
NSLog(#"fileName %#", fileName);
CSVParser *parser = [CSVParser new];
if ([fileName length] != 0)
{
NSString *pathAsString = [[NSBundle mainBundle]pathForResource:fileName ofType:#"csv"];
NSLog(#"%#", pathAsString);
if (pathAsString != nil)
{
[parser openFile:pathAsString];
NSMutableArray *csvContent = [parser parseFile];
NSLog(#"%#", csvContent);
[parser closeFile];
NSMutableArray *heading = [csvContent objectAtIndex:0];
[csvContent removeObjectAtIndex:0];
NSLog(#"%#", heading);
AppDelegate *ap = [AppDelegate sharedAppDelegate];
NSManagedObjectContext *context = [ap managedObjectContext];
NSString *currentHeader = [heading objectAtIndex:0];
NSString *currentValueInfo = [heading objectAtIndex:1];
NSManagedObject *newObject = [NSEntityDescription insertNewObjectForEntityForName:#"Field" inManagedObjectContext:context];
[newObject setValue:#"MIS" forKey:#"header"];
[newObject setValue:currentHeader forKey:#"fieldName"];
for (NSArray *current in csvContent)
{
NSManagedObject *newField = [NSEntityDescription insertNewObjectForEntityForName:#"Field" inManagedObjectContext:context];
[newField setValue:currentHeader forKey:#"header"];
[newField setValue:currentValueInfo forKey:#"valueInfo"];
NSLog(#"%#", [current objectAtIndex:0]);
[newField setValue:[current objectAtIndex:0] forKey:#"fieldName"];
[newField setValue:[NSNumber numberWithDouble:[[current objectAtIndex:1] doubleValue]] forKey:#"value"];
}
NSError *error;
if (![context save:&error])
{
NSLog(#"Couldn't save: %#", [error localizedDescription]);
}
[self storeArray];
[self.tableView reloadData];
}
}
}
input.text = nil;
}
Forgive the weird beginning and ending brace indentation. :/
Anyway, so that is my code to take input from a user and access a file locally which I'm sure you guys have realized already. Now I want to know how to get the path of a file in my server.
Also if you guys see anything else wrong such as writing style and other bad habits please tell me as I'm new to iOS.
Thank you so much in advance! If you didn't understand my question please clarify as I'm bad at explaining myself at times! :)
As I am guessing you are trying to get data from a server's .csv file and want to show that data in table view list.
so I suggest you try to get that .csv file data in NSData and then work on that.
NSData *responseData = [NSData dataWithContentsOfURL:[NSURL URLWithString:#"serverUrl"]];
NSString *csvResponseString = [[[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding] autorelease];
NSLog(#"responseString--->%#",csvResponseString);
Now try to use nsstring's method (componentsSeparatedByString) with coma (')
arrSepratedData = [[responseString componentsSeparatedByString:#","];
Now use this arr for UITableView data populate.

NSRegularExpression:enumerateMatchesInString hangs when called more than once

In the context of an iPhone app I am developing, I am parsing some html to extract data to map, using NSRegularExpression. This information is updated whenever the user "pans" the map to a new location.
This works fine the first time or two through, but on the second or third time the function is called, the application hangs. I have used XCode's profiler to confirm I am not leaking memory, and no error is generated (the application does not terminate, it just sits in execution at the point shown below).
When I examine the HTML being parsed, I do not see that it is incomplete or otherwise garbled when the application hangs.
Furthermore, if I replace the regex code with a collection of explicitly address strings, everything works as expected.
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
// receivedData contains the returned HTML
NSString *result = [[NSString alloc] initWithData:receivedData encoding:NSASCIIStringEncoding];
NSError *error = nil;
NSString *pattern = #"description.*?h4>(.*?)<\\/h4>.*?\"address>[ \\s]*(.*?)<.*?zip>.*?(\\d{5,5}), US<";
NSRegularExpression *regex = [NSRegularExpression
regularExpressionWithPattern:pattern
options:NSRegularExpressionDotMatchesLineSeparators
error:&error];
__block NSUInteger counter = 0;
// the application hangs on the next line after 1-2 times through
[regex enumerateMatchesInString:result options:0 range:NSMakeRange(0, [result length]) usingBlock:^(NSTextCheckingResult *match, NSMatchingFlags flags, BOOL *stop){
NSRange range = [match rangeAtIndex:2];
NSString *streetAddress =[result substringWithRange:range];
range = [match rangeAtIndex:3];
NSString *cityStateZip = [result substringWithRange:range];
NSString *address = [NSString stringWithFormat:#"%# %#", streetAddress, cityStateZip];
EKItemInfo *party = [self addItem:address]; // geocode address and then map it
if (++counter > 4) *stop = true;
}];
[receivedData release];
[result release];
[connection release]; //alloc'd previously, so release here.
}
I realize this is going to be difficult/impossible to duplicate, but I was wondering if anyone has run into a similar issue with NSRegularExpression or if there is something obviously wrong here.
I also have encountered the regular expression exception, too. In my case, the problem was Character Encoding. So that I wrote a code to go well with several character encoding. Maybe this code help you.
+ (NSString *)encodedStringWithContentsOfURL:(NSURL *)url
{
// Get the web page HTML
NSData *data = [NSData dataWithContentsOfURL:url];
// response
int enc_arr[] = {
NSUTF8StringEncoding, // UTF-8
NSShiftJISStringEncoding, // Shift_JIS
NSJapaneseEUCStringEncoding, // EUC-JP
NSISO2022JPStringEncoding, // JIS
NSUnicodeStringEncoding, // Unicode
NSASCIIStringEncoding // ASCII
};
NSString *data_str = nil;
int max = sizeof(enc_arr) / sizeof(enc_arr[0]);
for (int i=0; i<max; i++) {
data_str = [
[NSString alloc]
initWithData : data
encoding : enc_arr[i]
];
if (data_str!=nil) {
break;
}
}
return data_str;
}
You can download the whole category library from GitHub and just run it. I wish this helps you.
https://github.com/weed/p120801_CharacterEncodingLibrary
Maybe the answer to this question can be found at: NSRegularExpression enumerateMatchesInString: [...] usingBlock does never stop .
I had this issue solved by passing NSMatchingReportCompletion as option and by setting stop to YES when the match is nil.

XML data crashing on numbers

hi friends
this is my xml file
1)
<sDescrizione>Crociera nei fiordi</sDescrizione>
2)
<sDescrizione>Fiat 500</sDescrizione>
3)
<sDescrizione>Orologio donna Glam sport Tissot</sDescrizione>
4)
<sDescrizione>Buoni La Rinascente 1000€</sDescrizione>
5)
<sDescrizione>Buoni Unieuro 1000€</sDescrizione>
this is what i want to retrieve from that xml file using CXML parsing method
the first 3 title are successfully retrived but when it comes at 4th it gives me error in my console like this
Entity: line 80: parser error : Input is not proper UTF-8, indicate encoding !
Bytes: 0x80 0x5D 0x5D 0x3E
<sDescrizione><![CDATA[Buoni La Rinascente 1000\200]]></sDescrizione>
^
this is my retrieving code:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
CXMLDocument *xmlParser = [[[CXMLDocument alloc] initWithData:data options:0 error:nil] autorelease];
NSArray *resultNodes = [xmlParser nodesForXPath:#"//premio" error:nil];
for (CXMLElement *resultElement in resultNodes) {
for (int j=0; j<[resultElement childCount]; j++) {
NSString *tagName = [NSString stringWithString:[[resultElement childAtIndex:j] name]];
if ([tagName isEqualToString:#"sDescrizione"])
{
NSString *temp = [[resultElement childAtIndex:j] stringValue];
[catArray addObject:temp];
}
else if([tagName isEqualToString:#"idPremioSodexho"])
{
NSString *trmp = [[resultElement childAtIndex:j] stringValue];
}
}
}
Looks like the XML file is not in UTF-8 and CXMLDocument is assuming it is. When it hits the € sign its crashing. Set the correct encoding in the header of the XML file. If the XML file is encoded with ISO 8859-1 then set the header like:
<?xml version="1.0" encoding="ISO-8859-1"?>
This will allow CXMLDocument to correctly interpret the characters/codepage of your XML document.
I think you are facing the problem due to invalid Character-sets.
See, here is the line of code that you have used.
// when you don't specify any encoding, TouchXML will use NSUTF8Encoding as default
// which may lead to some problems
CXMLDocument *xmlParser = [[[CXMLDocument alloc] initWithData:data options:0 error:nil] autorelease];
// So, I recommend you to use following line of code, which may not lead you with messy situations.
CXMLDocument *doc = [[CXMLDocument alloc] initWithData:[request responseData] encoding:[request responseEncoding] options:0 error:nil];

Converting NSMutableString to NSUrl in Objective C

I actually stuck with a problem while parsing xml-file from a dynamic url in Objective-C.
The Parser works fine for the whole project, but now I have to set a dynamic URL to parse the needed XML-File.
I have two Variables: One for the BaseURL and one for the Params.
Here is my documented Code:
//The Baseurl
NSMutableString* baselink = [NSMutableString stringWithString:zimmertyp.typlink];
//Adds the params to URL
[baselink appendString:aSlice.link];
//In Log it shows the right url to my XML-File with params
NSLog(#"Selected-URL: %#", url);
//I tried to convert the String to NSURL here
NSURL *url = [NSURL URLWithString: baselink];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
self.navigationItem.prompt = #" ";
//Initialize the delegate.
XMLParser *parser = [[XMLParser alloc] initXMLParser];
//Set delegate
[xmlParser setDelegate:parser];
//Start parsing the XML file.
BOOL success = [xmlParser parse];
if(success)
NSLog(#"No Errors");
else
NSLog(#"Error Error Error!!!");
Everytime the Parser tries to walk through, I get:
2011-02-16 16:40:03.371 Project[15566:207] Selected-URL: http://xml.projectwebsite.de/price/doppelzimmer.xml
?Zimmertyp=Doppelzimmer+Classic
2011-02-16 16:40:03.373 Project[15566:207] Error Error Error!!!
2011-02-16 16:40:03.374 Project[15566:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSCFString stringByAppendingString:]: nil argument'
It seems like the NSUrl is empty, or am I wrong?
The App crashes right at the point when the Parser initialized with the url.
Can anyone tell me what's my fault?
greeting,
Zarakas
I solved the problem by myself. The AppendString method added whitespaces to the String... dunno why. I escaped the spaces from the string. Now parser works fine.. ;)