Parse an XML stored in NSData with libxml2 - iphone

please can you help me using libxml2 to parse an XML stored in a NSMutableData object? I get the XML using
NSString *path = "http://www.mySite.com/XMLPATH.xml";
NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:path] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
and
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data_
{
[data appendData:data_];
}
where data is an instance of NSMutableData.
Now how can i start the libxml2 to parse this data? I need the equivalent of
NSString *xml; // string containing XML
mlDocPtr doc = xmlParseMemory([xml UTF8String], [xml lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
where xml is my NSMutabledata and not a NSString.
Thanks!
EDIT:
I'm currently using NSXMLParser to do the job, but i'd like to have a parser that automatically parses all the XML, with its node structure. With NSXMLParser i need to manually set the node structure of my XML

Any reason you are not using the NSXMLParser. It is a nice wrapper written by Apple and included on all iOS versions.
http://developer.apple.com/library/mac/ipad/#documentation/Cocoa/Reference/Foundation/Classes/NSXMLParser_Class/Reference/Reference.html

Related

iOS Unable to store URL contents into array

I have to connect to a URL to check whether the records is empty. The response looks something like this:
<?xml version = "1.0" encoding = "UTF-8"?>
<find>
<record_id>1234</record_id>
<no_record>00001</no_record>
<entry_num>00001</entry_num>
<session-id>aijheifaohqrihelrkqn324tlejaofjaf</session-id>
</find>
My codes:
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init]
autorelease];
[request setURL:[NSURL URLWithString: finalSearchURL]];
// Content-Type related.
[request setValue:#"application/x-www-form-urlencoded"
forHTTPHeaderField:#"Content-Type"];
// Create Connection.
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if (conn) {
// The connection was established.
NSMutableData *receivedData = [[NSMutableData alloc] initWithContentsOfURL:[NSURL URLWithString:request]];
NSLog( #"Data will be received from URL: %#", request.URL );
NSLog(#"Recieved Data 2: %#", receivedData);
}
else
{
// The download could not be made.
NSLog( #"Data could not be received from: %#", request.URL );
}
But it returns me:
Recieved Data : <3c3f786d 6c207665 7273696f 6e203d20 22312e30 2220656e 636f6469 6e67203d 20225554 462d3822 3f3e0a3c 66696e64 3e0a3c73 65745f6e 756d6265 723e3031 39303633 3c2f7365 745f6e75 6d626572 3e0a3c6e 6f5f7265 636f7264 733e3030 30303030 3030313c 2f6e6f5f 7265636f 7264733e 0a3c6e6f 5f656e74 72696573 3e303030 30303030 30313c2f 6e6f5f65 6e747269 65733e0a 3c736573 73696f6e 2d69643e 4d505843 33323433 58564336 4534454a 41464232 45473541 39374237 584e3832 43554631 4e314234 584e4c37 424c5947 4e533c2f 73657373 696f6e2d 69643e0a 3c2f6669 6e643e0a 20>
Can anyone help to tell me what am I doing wrong? This is my first attempt for getting response from a url please help thanks!
See the data as a string this way:
NSString *string = [[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding];
NSLog(#"the xml string is %#", string);
If the parsing goal is simple enough - like just to find the value of one tag - you can use string methods to parse. Otherwise, NSXMLParser or several other options are available.
To see if the string contains a substring, you can do something like this:
if (string) {
NSRange range = [string rangeOfString:#"<session-id>"];
if (range.location != NSNotFound) {
// session-id tag is at index range.location, so we know it's there
}
}
The method you used is to get the raw data from the url. You need a parser to convert the raw data to the understandable structure (probably NSDictionary rather than NSArray).
Apple has provided NSXMLParser for you to retrieve the xml structure from the url or you can find other xml parser libraries.
Actually, your code is returning the correct data. Since NSData can hold any kind of data, it will just display the hex value. If you convert the hex data to a sting, you'll see that it has the correct text.
Now, your code can be simplified a lot. All the code for setting up the NSURLConnection is not needed at all. All you need is the following line.
NSString *recievedText = [NSString stringWithContentsOfFile:finalSearchURL encoding:NSUTF8StringEncoding error:NULL];

ASIFormDataRequest responseString return nscfstring or nscfconstant string

I am using ASIFormDataRequest to call a web service with video file. it workes fine if video is small but if video is about 30 seconds or above then its response return as __NSCFString or sometime __NSCFConstantString
my code is as below.
__block ASIFormDataRequest *request=[[ASIFormDataRequest alloc] initWithURL:[NSURL URLWithString:APP_APIURL]];
[request setPostValue:strVal forKey:#"jsonRequest"];
if (videoData) {
[request setData:videoData withFileName:videoName andContentType:nil forKey:#"videoFile"];
}
[request startSynchronous];
request.timeOutSeconds=999999999;
// response
NSString *strResponse=[request responseString];
if (strResponse) {
SBJsonParser *parser=[[SBJsonParser alloc] init];
NSMutableDictionary *dicData=[[parser objectWithString:strResponse] valueForKey:#"uploadVideo"];
Please help me to solve this issue.
Shivam
Here are few solutions to your problem:
Use introspection and check the returned object for it's class. If you're getting a "constant" string, probably it's not what you're expecting. Print it or check it's contents.
If you're receiving a video file - use [request responseData] or better, use the file saving techniques described in ASIHTTPRequest library. How can you download a file and parse json response at the same time?
Use JSONKit - IMHO the fastest json parser.

Check if URL-file exist or not

I wonder how I can check if a file exist on a server or not, without downloading the data first.
I have around 30 different objects and some of them is connected to a movie on a server. At the moment I use NSData to control if the the URL exist, and then shows the movie, or if it doesn't and then alerts the user that there is no video for that object. The code I use for the moment:
NSString *fPath = [[NSString alloc] initWithFormat:#"http://www.myserver/%#", [rows idNr]];
NSURL *videoURL = [NSURL URLWithString:fPath];
NSData *videoData = [NSData dataWithContentsOfURL:videoURL];
url = [NSURL URLWithString:fPath];
[fPath release];
if (videoData) {
[self performSelectorOnMainThread:#selector(playVideo:) withObject:url waitUntilDone:NO];
} else {
NSLog(#"videodata false");
errorLabel.hidden = NO;
activityView.hidden = YES;
}
"rows idNr" is the name of the object. This method is doing what I want, but the problem is that with NSData it first "downloading" the file, and when the URL is validated as a file, the movie is loading once again in the movieplayer. This means that it takes twice as long to load the file.
Suggestions?
It took me a while to dig out my answer to one of the previous questions on this topic. Quote:
You can use a NSMutableURLRequest to send a HTTP HEAD request
(there’s a method called setHTTPMethod). You’ll get the same
response headers as with GET, but you won’t have to download the whole
resource body. And if you want to get the data synchronously, use the
sendSynchronousRequest… method of NSURLConnection.
This way you’ll know if the file exists and won’t download it all if it does.
Make an URLConnecion object with desired url request and add NSURLConnectionDelegate into .h file like I want to check "yoururl" is exist or not then you need to do is
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString: #"http://www.google.com"]];
NSURLConnection *urlConnection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self];
and then you can track http status code in delegate function of NSURLConnectionDelegate
-(void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
int code = [(NSHTTPURLResponse *)response statusCode];
if (code == 404)
{
// website not found
// do your stuff according to your need
}
}
You can also find various status code here.
NSError *err;
if ([videoURL checkResourceIsReachableAndReturnError:&err] == NO)
NSLog(#"wops!");
Here's the code for the accepted answer (for your convenience):
How to make call
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:urlString]];
[request setHTTPMethod:#"HEAD"];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
You could do this by checking the size of the file via an FTP server, using the SIZE command. If the file size is zero then the file simply do not exist.
Check here on how to do this.
You could of course also do this by using a NSURLRequest with NSURLConnection, checking for the status to be either 200 (success) or 404 (failed). The 404 status doesn't have to be that the file doesn't exist though, it could also be that the file just couldn't be retrieved.

How do I make initWithContentsOfURL wait for an xml page that is generated dynamically?

I am trying to send a query as part a the URL to obtain an XML file, and then trying to parse the XML file using NSXMLParser and initWithContentsOfURL. However the parser is not able to parse the file. I tested the parser with the same file, but this time the file was saved on the server (it was not being generated) and it worked just fine, so I know it is not a problem with the parser.
I have come to think that it does not parse it because I need to load the file before I try to parse it, or give the initWithContentsOfURL time to load the contents. So I tried to put those contents in a NSString and a NSData and using a sleep function as well as using a block but that did not work either.
What would be the best way to go about this problem?
Here is some of the code:
NSString *surl = [NSString stringWithFormat:#"http://lxsrv7.oru.edu/~maria_hernandez/query.xml"];
url = [NSURL URLWithString:surl];
NSString *curl = [[NSString alloc] initWithContentsOfURL:url];
NSLog(#"URL: %#", surl);
NSLog(#"URL Content: %#", curl);
SXMLParser *xmlParser = [[NSXMLParser alloc] initWithData:receivedData];
//Other stuff we have tried:
NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:surl] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSURLResponse = nil;
NSError = nil;
receivedData = [NSURLConnection sendSynchronousRequest: theRequest returningResponse: &theResponse error: &error];
Let me know if you have more questions or if you wish to see more code.
Thanks!
have you tried setting a delegate for the NSXMLParse that implements the NSXMLParserDelegate which has events for parsing the document
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSXMLParser_Class/Reference/Reference.html

iphone: Getting xml with UIWebView?

I have the following url http://gdata.youtube.com/feeds/api/standardfeeds/recently_featured?&start-index=1&max-results=15&v=2
I am trying to load it in UIWebView and then use javascript to get its contents, and parse it with NSXMLParser.
My code looks like that:
-(void)startDownloading{
NSString *urlStr = [NSString stringWithFormat:#"http://gdata.youtube.com/feeds/api/standardfeeds/recently_featured?&start-index=%d&max-results=%d&v=2", range.location, range.length];
NSLog(urlStr);
NSURL *url = [NSURL URLWithString:urlStr];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[browser loadRequest:request];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView{
NSString *theStr = [webView stringByEvaluatingJavaScriptFromString:#"document.body.firstChild.innerHTML"];
NSLog(theStr);
NSData *receivedData = [theStr dataUsingEncoding:NSUTF8StringEncoding];
}
the problem is that the data that I receive can't be parsed with NSXMLParser. The text looks like that:
<?xml version='1.0' encoding='UTF-8'?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:app='http://www.w3.org/2007/app' xmlns:media='http://search.yahoo.com/mrss/' xmlns:openSearch='http://a9.com/-/spec/opensearch/1.1/' xmlns:gd='http://schemas.google.com/g/2005' xmlns:yt='http://gdata.youtube.com/schemas/2007' gd:etag='W/"DUADR347eCp7ImA9Wx5UFkg."'><id>tag:youtube.com,2008:standardfeed:us:recently_featured</id><updated>...
while if I had used just the regular approach of getting data (without browser) I would get:
<?xml version='1.0' encoding='UTF-8'?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:app='http://www.w3.org/2007/app' xmlns:media='http://search.yahoo.com/mrss/' xmlns:openSearch='http://a9.com/-/spec/opensearch/1.1/' xmlns:gd='http://schemas.google.com/g/2005' xmlns:yt='http://gdata.youtube.com/schemas/2007' gd:etag='W/"DUADR347eCp7ImA9Wx5UFkg."'><id>tag:youtube.com,
Why are the characters changing? And how can I prevent it
BTW to those who are wondering why I'm even bothering to do this - I think that this method gets the data quicker.
The data is being escaped, you need to unescape it. Take a look at:
- (NSString *)stringByReplacingPercentEscapesUsingEncoding:(NSStringEncoding)encoding
"BTW to those who are wondering why I'm even bothering to do this - I think that this method gets the data quicker."
Don't prematurely optimize.