XML data crashing on numbers - objective-c

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];

Related

How to find attribute of root node in touch xml?

NSString *xml = #"<?xml version="1.0" encoding="ISO-8859-15"?>
<ServerDateTime DateRequested="" DateSent="20141013_114855">
<DateTime>20141013_114857</DateTime>
</ServerDateTime>";
In above xml, how to find the attribute value of 'DataSent'?
I have tried by following, but i didn't get the value.
CXMLDocument *documentParser = [[CXMLDocument alloc]initWithData:[xml dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];
NSArray *arrayResult = [documentParser nodesForXPath:#"//ServerDateTime" error:nil];
for(CXMLElement *element in arrayResult){
NSString *value = [element name];
if ([value isEqualToString:#"ServerDateTime"]) {
NSString *newLastSyncDate = [[element attributeForName:#"DataSent"] stringValue]; //it gives nil..
}
}
You may want to use XPath-queries to search for elements inside a XML. You have to look up if CXML supports this.
Maybe also take a look at this question.
There someone is searching for a given attribute with an XPath-query.

Unable to write NSArray to file

I am using google contact data objective c APIs for fetching contacts. I got contacts array from google server now i want to write contact to file. i am using writeToFile:atomically: method for writing array to file but This method is not working for me since i feel that output array from gdata API not contain property list objects. Please suggest any alternate solution.
-(void)fetchData{
GDataServiceGoogleContact *service=[[GDataServiceGoogleContact alloc] init];
[service setShouldCacheResponseData:YES];
[service setServiceShouldFollowNextLinks:YES];
[service setUserCredentialsWithUsername:[mUsername stringValue] password:[mPassword stringValue]];
// GENERATING THE URL
NSURL *feedURL=[GDataServiceGoogleContact contactFeedURLForUserID:kGDataServiceDefaultUser];
GDataQuery *contQuery=[GDataQueryContact contactQueryWithFeedURL:feedURL];
[contQuery setShouldShowDeleted:YES];
[contQuery setMaxResults:2000];
GDataServiceTicket *ticket=[service fetchFeedWithQuery:contQuery delegate:self didFinishSelector:#selector(hasFetchedContacts:feed:error:)];
}
-(void) hasFetchedContacts:(GDataServiceTicket*) ticket feed:(GDataFeedContact*) contacts error:(NSError*) err
{
NSArray *contactList=[contacts entries];
NSLog(#"%d",[list writeToFile:#"/Users/subhranil/Desktop/contactList" atomically:NO]);
}
Wrap it up to NSData with:
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:contactList];
Then save NSData to file with:
[data writeToFile:#"/Users/subhranil/Desktop/contactList" atomically:NO];
You can later restore the data back to NSArray using:
NSData *data = [NSData dataWithContentsOfFile: #"yourFilePath"];
NSArray *array = [NSKeyedUnarchiver unarchiveObjectWithData:data]
Just make sure that objects inside your NSArray conform to NSCoding.
You can use byte array for this purpose and NSData for writing to file.
For saving:
NSData *data=[[NSData alloc] initWithBytes:[contacts entries] length:total];
[data writeToFile:#"path" atomically:YES];
total= The total size of the array in bytes
For retrieving:
NSData *newdata = [NSData dataWithContentsOfFile:#"path"];
NSUInteger len = [newdata length];
Byte *byteData = (Byte*)malloc(len);
memcpy(byteData, [newdata bytes], len);
byteData will now contain an array of GDataEntryContact objects and you can use them accordingly.
You can encode/decode GDataObject using an xml as generator.
Encode:
[entry setNamespaces:[entry completeNamespaces]];
NSString *xml = [[entry XMLElement] XMLString];
if (nil != xml)
{
//Store your xml NSString to a file
}
Decode:
NSString *xml = //Read your XML String from file;
NSXMLElement *xmlElement = [[NSXMLElement alloc] initWithXMLString:xml error: &error];
if (!error) {
return [[GDataEntryDocBase alloc] initWithXMLElement:xmlElement parent: nil];
}

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.

Cocoa/Obj-C - Count elements in XML file

Got an application wich read some infos in a specific XML file.
I would like to add one more option, here is the description:
Here is an example of my XML type file:
<?xml version="1.0" ?>
<Report>
<ReportCreationDate>20110307162840</ReportCreationDate>
<ReportTitle>Title sample</ReportTitle>
<ReportDescription>Description sample</ReportDescription>
<Videos>
<Video>
<VideoTitle>Video 1</VideoTitle>
<VideoDescription>Video description sample</VideoDescription>
</Video>
<Video>
<VideoTitle>Video 2</VideoTitle>
<VideoDescription>Video description sample</VideoDescription>
</Video>
</Videos>
</Report>
I would like to count how many <Video> elements is there in the <Videos> node.
For this example it's 2
How can I do that? Using NSXMLDocument?
I would like to write the result in a TextField.
Example: XML file contains 5 videos.
If someone can help, it would be great!
Thanks in advance
Miskia
(and sorry for my poor english, i'm a frenchy :p)
Something like this should get the job done. I'll leave the error handling up to you.
NSData *data = [NSData dataWithContentsOfFile:pathToYourXMLFile];
NSError *error = nil;
NSXMLDocument *document = [[NSXMLDocument alloc] initWithData:data options:0 error:&error];
if(!error)
{
NSXMLElement *rootElement = [document rootElement];
NSUInteger count = [[rootElement nodesForXPath:#"//Video" error:&error] count];
if(!error)
{
NSString *videosCount = nil;
if(count == 0)
videosCount = [NSString stringWithFormat:#"XML file contains no videos."];
else if(count == 1)
videosCount = [NSString stringWithFormat:#"XML file contains 1 video."];
else
videosCount = [NSString stringWithFormat:#"XML file contains %d videos.", count];
[myTextField setStringValue:videosCount];
}
}
[document release]

NSXMLParser with UTF8 Data

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.