Get specific Value between Javascript Function by NSRegularExpression? - iphone
I am creating a project for learning purpose:
FOR INFO : I have not used UIWebView
In my project I got HTML data(content) from server. This data contains all information about places(from google map). For getting specific data from HTML content I need to parse HTML. I parse HTML using Hpple. And I could successfully parse HTML to get specific data (Such as name,address…etc), but when I need to parse latitude and longitude from HTML content, I am confused about how to get latitude and longitude of places, because those are part of Javascript. I mean these latitude and longitude data are available in Javascript's functions.
Javascript content that I got from Server: (My limitation is that, I can only put piece of javascript code bacause this code is very very long)
function()
{
window.gHomeVPage=
{
title:'Hostel, Bhavnagar, Gujarat, India - Google Maps',url:'/?q\\x3dHostel,+Bhavnagar,+Gujarat,+India\\x26hq\\x3dHostel,\\x26hnear\\x3dBhavnagar,+Gujarat,+India\\x26t\\x3dm\\x26ie\\x3dUTF8',urlViewport:false,ei:'jp8tUb3uNK2ciAeQroGACw',
form:{
selected:'q',
q:{q:'Hostel, Bhavnagar, Gujarat, India',what:'Hostel,',near:'Bhavnagar, Gujarat, India'},d:{saddr:'',daddr:'',dfaddr:'Bhavnagar, Gujarat, India'},geocode:''},
query:{type:'l'},viewport:{center:{lat:21.757528,lng:72.15303},span:{lat:0.034314,lng:0.039956},zoom:14,mapType:'m',source:0},modules:['','strr','pphover','act_s','appiw','rst'],
overlays:{sxcar:false,
markers:
[{id:'A',cid:'7569356420090555589',latlng:{lat:21.747064,lng:72.169678},image:'http://maps.gstatic.com/intl/en_ALL/mapfiles/markers2/circleA.png',sprite:{width:20,height:34,top:0,image:'http://maps.gstatic.com/mapfiles/markers2/red_circle_markers_A_J2.png'},icon_id:'A',ext:{width:20,height:34,shadow:'http://maps.gstatic.com/intl/en_ALL/mapfiles/circle-shadow45.png',shadow_width:37,shadow_height:34,mask:false},drg:true,laddr:'Shree Sahajanand Girls Ptc Hostel, Ghogha Road, Bhavnagar, Gujarat 364001, India',geocode:'CfYWJFjKQj0mFXjVSwEdzjhNBCmN5-3pPlpfOTHF7NFVj8ELaQ',sxti:'Shree Sahajanand Girls Ptc Hostel',name:'Shree Sahajanand Girls Ptc Hostel',infoWindow:{title:'Shree Sahajanand Girls Ptc \\x3cb\\x3eHostel\\x3c/b\\x3e',addressLines:['Ghogha Road','Bhavnagar, Gujarat 364001, India'],phones:[{number:'0278 2562529'}],basics:'\\x3cdiv transclude\\x3d\\x22iw\\x22\\x3e\\x3c/div\\x3e',moreInfo:'more info',place_url:'http://maps.google.com/local_url?dq\\x3dHostel,+Bhavnagar,+Gujarat,+India\\x26q\\x3dhttps://plus.google.com/106028699675431268945/about%3Fhl%3Den\\x26s\\x3dANYYN7mCKtIBT1JPxwi6G2b9gVDdCuVyyA',zrvOk:true,loginUrl:'https://www.google.com/accounts/ServiceLogin?service\\x3dlocal\\x26hl\\x3den\\x26nui\\x3d1\\x26continue\\x3dhttp://maps.google.com/maps/place%3Fcid%3D7569356420090555589%26q%3DHostel,%2BBhavnagar,%2BGujarat,%2BIndia%26t%3Dm%26cd%3D1%26cad%3Dsrc:ppwrev%26ei%3Djp8tUb3uNK2ciAeQroGACw%26action%3Dopenratings',lbcurl:'http://www.google.com/local/add/choice?hl\\x3den\\x26gl\\x3dIN\\x26latlng\\x3d7569356420090555589\\x26q\\x3dHostel,\\x26near\\x3dBhavnagar,+Gujarat,+India',link_jsaction:''},ss:{edit:true,detailseditable:true,deleted:false,rapenabled:true,mmenabled:true},b_s:2,approx:true,elms:[4,1,6,2,12,1,9,1,5,2,11]
}
}
Here in above code I want to get value of lat: and lon: from latlng:{lat:21.747064,lng:72.169678}
For getting it from javascript, I googled and found that I need to use NSRegularExpression class for get specific matches(of Data) form content.
Then I tried with following code
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"(?-imsx:latlng:)" options:NSRegularExpressionCaseInsensitive error:&error];
NSArray *arrayOfAllMatches = [regex matchesInString:locationStr options:0 range:NSMakeRange(0, [locationStr length])];
for (NSTextCheckingResult *match in arrayOfAllMatches)
{
NSString* substringForMatch = [locationStr substringWithRange:match.range];
NSLog(#"%#",substringForMatch);
}
I got output in console like this:
2013-02-28 11:35:25.051 MapExample[949:13d03] latlng:
2013-02-28 11:35:25.766 MapExample[949:13d03] latlng:
2013-02-28 11:35:26.208 MapExample[949:13d03] latlng:
2013-02-28 11:35:26.799 MapExample[949:13d03] latlng:
2013-02-28 11:35:27.303 MapExample[949:13d03] latlng:
2013-02-28 11:35:27.722 MapExample[949:13d03] latlng:
How can I get content of searched node from NSRegularExpression ?
If you really want to use a regular expression, this following pattern should work:
NSString *pattern = #"latlng:\\{lat:([0-9.]+),lng:([0-9.]+)\\}";
[0-9.]+ matches one or more characters which are a digit or ., and the parentheses around it make it a "capture group", so that the part of the string that matches this part of the pattern is available using rangeAtIndex:.
To verify this, I have added the exact input data from your question as a resource file "data.txt" to my test application, and loaded that data with
NSURL *url = [[NSBundle mainBundle] URLForResource:#"data.txt" withExtension:nil];
NSError *error;
NSString *locationStr = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];
and then parsed the string with the regular expression
NSString *pattern = #"latlng:\\{lat:([0-9.]+),lng:([0-9.]+)\\}";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:&error];
NSArray *matches = [regex matchesInString:locationStr options:0 range:NSMakeRange(0, [locationStr length])];
for (NSTextCheckingResult *match in matches)
{
NSString *lat = [locationStr substringWithRange:[match rangeAtIndex:1]];
NSString *lng = [locationStr substringWithRange:[match rangeAtIndex:2]];
NSLog(#"latidude = %#, longitude = %#", lat, lng);
}
Output:
latidude = 21.747064, longitude = 72.169678
While not a direct answer to your question, there's actually an easier way to do this, using UIWebView:
+(NSString *)valueFromJSON:(NSString *)json andKey:(NSString *)key {
UIWebView webView = [[UIWebView alloc] init];
return [webView stringByEvaluatingJavaScriptFromString:[NSString withFormat:#"(function(){ var v = %#; return var.%#; }())", json, key]];
}
I'll apologize in advance for any syntax errors I've invariably made due to not being on my Mac and it being rather late. If you call this code repeatedly, it might be wise not to initialize a new WebView every time. This exploits the ability of WebKit's Javascript engine to do easy JSON parsing for you. Replace the return in the Javascript function to match your data structure.
Related
Iphone Dev : Google Currency Convert read only the nomber
I got this result {lhs: "1 U.S. dollar", rhs: "44.5097254 Indian rupees", error: "", icc: true} in NSString with ASIHTTPRequest method. But I wanna read only 44.5097254 in one NSString. How to do so?
That's a JSON object, you need to parse it and then get the values you need. Here's a nice tuto: http://ios-blog.co.uk/tutorials/parsing-json-on-ios-with-asihttprequest-and-sbjson/
You can get it with the following Methode -(NSString*)getNumberFromString(NSString*)theString{ NSError *error = NULL; NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"rhs: \"(([0-9]*[.]*[0-9]*)*)" options:NSRegularExpressionCaseInsensitive | NSRegularExpressionAnchorsMatchLines error:&error]; NSArray *matches = [regex matchesInString:theString options:0 range:NSMakeRange(0, [theString length])]; NSTextCheckingResult *match = [matches objectAtIndex:0]; return [theString substringWithRange:[match rangeAtIndex:1]]); } You can find more information about NSRegularExpressionin the Apple Documentation
Get the extension of a file contained in an NSString
I have an NSMutable dictionary that contains file IDs and their filename+extension in the simple form of fileone.doc or filetwo.pdf. I need to determine what type of file it is to correctly display a related icon in my UITableView. Here is what I have done so far. NSString *docInfo = [NSString stringWithFormat:#"%d", indexPath.row]; //Determine what cell we are formatting NSString *fileType = [contentFiles objectForKey:docInfo]; //Store the file name in a string I wrote two regex to determine what type of file I'm looking at, but they never return a positive result. I haven't used regex in iOS programming before, so I'm not entirely sure if I'm doing it right, but I basically copied the code from the Class Description page. NSError *error = NULL; NSRegularExpression *regexPDF = [NSRegularExpression regularExpressionWithPattern:#"/^.*\\.pdf$/" options:NSRegularExpressionCaseInsensitive error:&error]; NSRegularExpression *regexDOC = [NSRegularExpression regularExpressionWithPattern:#"/^.*\\.(doc|docx)$/" options:NSRegularExpressionCaseInsensitive error:&error]; NSUInteger numMatch = [regexPDF numberOfMatchesInString:fileType options:0 range:NSMakeRange(0, [fileType length])]; NSLog(#"How many matches were found? %#", numMatch); My questions would be, is there an easier way to do this? If not, are my regex incorrect? And finally if I have to use this, is it costly in run time? I don't know what the average amount of files a user will have will be. Thank you.
You're looking for [fileType pathExtension] NSString Documentation: pathExtension
//NSURL *url = [NSURL URLWithString: fileType]; NSLog(#"extension: %#", [fileType pathExtension]); Edit you can use pathExtension on NSString Thanks to David Barry
Try this : NSString *fileName = #"resume.doc"; NSString *ext = [fileName pathExtension];
Try this, it works for me. NSString *fileName = #"yourFileName.pdf"; NSString *ext = [fileName pathExtension]; Documentation here for NSString pathExtension
Try using [fileType pathExtension] to get the extension of the file.
In Swift 3 you could use an extension: extension String { public func getExtension() -> String? { let ext = (self as NSString).pathExtension if ext.isEmpty { return nil } return ext } }
Parse NSString from right hand side?
> (2009 RX7)</font></td> >monospace" size="-1">214869 (2007 PAZ)</font></td> >monospace" size="-1"> 4155 Accord</font></td> I wonder if someone could offer me a little help, I have a list of NSString items (See Above) that I want to parse some data from. My problem is that there are no tags that I can use within the strings nor do the items I want have fixed positions. The data I want to extract is: 2009 RX7 2007 PAZ 4155 Accord My thinking is that its going to be easier to parse from the right hand end, remove the </font></td> and then use ";" to separate the data items: (2009  RX7) (2007  PAZ) 4155  Accord which can them be cleaned up to match the example given. Any pointers on doing this or working through from the right would be very much appreciated.
Personally I think you are better off with a regex. So my solution would be: Regex of: ([0-9]+)[^;]+;([A-Za-z0-9]+) Which for all the example text provides 3 matches. ie for: (2009 RX7)</font></td> 0: 2009 RX7)< 1: 2009 2: RX7 I haven't coded this up, but did test the Regex at www.regextester.com Regex's are implemented via NSRegularExpression and are available in iOS 4.0 and later. Edit Given that this appears to be a web scraping application, you never know when those pesky HTML code monkeys will change their output and break your carefully crafted matching methodology. As such I would change my regex to: ([0-9]+)([^;]+;)+([A-Za-z0-9]+) Which adds an extra group, but allows for any number of elements between the number and the string.
Try this code: NSString *str = #"> (2009 RX7)</font></td>"; NSRange fontRange = [str rangeOfString:#"</Font>" options:NSBackwardsSearch]; NSRange lastSemi = [str rangeOfString:#";" options:NSBackwardsSearch range:NSMakeRange(0, fontRange.location-1)]; NSRange priorSemi = [str rangeOfString:#";" options:NSBackwardsSearch range:NSMakeRange(0, lastSemi.location-1)]; NSString *yourString = [str substringWithRange:NSMakeRange(priorSemi.location+1, fontRange.location-1)]; The key element here is the NSBackwardsSearch search option.
This should do the trick: NSString *s = #">monospace\" size=\"-1\"> 4155 Accord</font></td>"; NSArray *strArray = [s componentsSeparatedByString:#";"]; // you're interested in last two objects NSArray *tmp = [strArray subarrayWithRange:NSMakeRange(strArray.count - 2, 2)]; In tmp you'll have something like: "4155 ", "Accord</font></td>" strip unneeded chars and you're all set.
Using NSRegularExpression: NSRegularExpression *regex; NSTextCheckingResult *match; NSString *pattern = #"([0-9]+) ([A-Za-z0-9]+)[)]?</font></td>"; NSString *string = #"> (2009 RX7)</font></td>"; regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:nil]; match = [regex firstMatchInString:string options:0 range:NSMakeRange(0, [string length])]; NSLog(#"'%#'", [string substringWithRange:[match rangeAtIndex:1]]); NSLog(#"'%#'", [string substringWithRange:[match rangeAtIndex:2]]); NSLog output: '2009' 'RX7'
How to get find and get URL in a NSString in iPhone?
I have a text with http:// in NSString. I want to get that http link from the NSString. How can i get the link/url from the string? Eg: 'Stack over flow is very useful link for the beginners https://stackoverflow.com/'. I want to get the 'https://stackoverflow.com/' from the text. How can i do this? Thanks in advance.
I am not sure what you exactly mean by link but if you want to convert your NSString to NSURL than you can do the following: NSString *urlString = #"http://somepage.com"; NSURL *url = [NSURL URLWithString:urlString]; EDIT This is how to get all URLs in a given NSString: NSString *str = #"This is a grate website http://xxx.xxx/xxx you must check it out"; NSArray *arrString = [str componentsSeparatedByString:#" "]; for(int i=0; i<arrString.count;i++){ if([[arrString objectAtIndex:i] rangeOfString:#"http://"].location != NSNotFound) NSLog(#"%#", [arrString objectAtIndex:i]); }
Rather than splitting the string into an array and messing about that way, you can just search for the substring beginning with #"http://": NSString *str = #"Stack over flow is very useful link for the beginners http://stackoverflow.com/"; // get the range of the substring starting with #"http://" NSRange rng = [str rangeOfString:#"http://" options:NSCaseInsensitiveSearch]; // Set up the NSURL variable to hold the created URL NSURL *newURL = nil; // Make sure that we actually have found the substring if (rng.location == NSNotFound) { NSLog(#"URL not found"); // newURL is initialised to nil already so nothing more to do. } else { // Get the substring from the start of the found substring to the end. NSString *urlString = [str substringFromIndex:rng.location]; // Turn the string into an URL and put it into the declared variable newURL = [NSURL URLWithString:urlString]; }
try this : nsstring *str = #"Stack over flow is very useful link for the beginners http://stackoverflow.com/"; nsstring *http = #"http"; nsarray *arrURL = [str componentsSeparatedByString:#"http"]; this will give two objects in the nsarray. 1st object will be having:Stack over flow is very useful link for the beginners and 2nd will be : ://stackoverflow.com/ (i guess) then you can do like: NSString *u = [arrURL lastObject]; then do like: nsstring *http = [http stringByAppendingFormat:#"%#",u]; Quite a lengthy,but i think that would work for you. Hope that helps you.
stringByReplacingOccurrencesOfString not working as expected
Having a problem. Here's my code: Latitude = [TBXML textForElement:lat]; //Latitude & Longitude are both NSStrings Longitude= [TBXML textForElement:lon]; NSLog(#"LAT:%# LON:%#",Latitude,Longitude); NSString *defaultURL = #"http://api.wxbug.net/getLiveWeatherRSS.aspx?ACode=000000000&lat=+&long=-&unittype=1"; newURL = [[defaultURL stringByReplacingOccurrencesOfString:#"+" withString:Latitude] stringByReplacingOccurrencesOfString:#"-" withString:Longitude]; NSLog(#"%#",newURL); And here's the output: LAT:-33.92 LON:18.42 http://api.wxbug.net/getLiveWeatherRSS.aspxACode=000000000&lat=18.4233.92&long=18.42&unittype=1 As you can see, something strange is happening to the appending code. Am I doing something wrong here?
Before replacing the longitude, the string is http://....&lat=-33.92&long=-&... ^ ^ The system sees that there are two -, and thus both of them will be replaced by the latitude. You should use a more descriptive string to replace with, e.g. NSString *defaultURL = #"http://....&lat={latitude}&long={longitude}&unittype=1"; newURL = [defaultURL stringByReplacingOccurrencesOfString:#"{latitude}" withString:Latitude]; newURL = [newURL stringByReplacingOccurrencesOfString:#"{longitude}" withString:Longitude]; or simply use +stringWithFormat:. NSString* newURL = [NSString stringWithFormat:#"http://....&lat=%#&long=%#&...", Latitude, Longitude];
Here's where we started: url = #"http://...?ACode=000000000&lat=+&long=-&unittype=1" Latitude = #"-33.92" Longitude = #"18.42" Then you replaced all occurrences of #"+" with #"-33.92": url = #"http://...?ACode=000000000&lat=-33.92&long=-&unittype=1" Then you replaced all occurrences of #"-" with #"18.42". Note that there are two '-' characters; one after lat= and one after long=. The one after 'lat' is there because the string you pasted in had a - in it. url = #"http://...?ACode=000000000&lat=18.4233.92&long=18.42&unittype=1" Thus, your final result.
#KennyTM, BJ Homer, and madmik3 are correct. Your value is getting replaced twice. However, you should technically be building your URL in a totally different manner: NSMutableDictionary *query = [NSMutableDictionary dictionary]; [query setObject:#"000000000" forKey:#"ACode"]; [query setObject:Latitude forKey:#"lat"]; [query setObject:Longitude forKey:#"long"]; [query setObject:#"1" forKey:#"unittype"]; NSMutableArray *queryComponents = [NSMutableArray array]; for (NSString *key in query) { NSString *value = [query objectForKey:key]; key = [key stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]; value = [value stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]; NSString *component = [NSString stringWithFormat:#"%#=%#", key, value]; [queryComponents addObject:component]; } NSString *queryString = [components componentsJoinedByString:#"&"]; NSString *fullURLString = [NSString stringWithFormat:#"http://api.wxbug.net/getLiveWeatherRSS.aspx?%#", queryString]; NSURL *newURL = [NSURL URLWithString:fullURLString]; (ignoring the efficacy of -stringByAddingPercentEscapesUsingEncoding: for now) The reason this is better is that according to the HTTP specification, the keys and values in the query of the URL should be URL encoded. Granted, you're only encoding numbers for simple keys. But if that ever changes, you URL might break. (The flaw with this method is that it only allows a single value per key, and the HTTP spec allows you to specify multiple values. For the sake of simplicity, I've left that out) There are also some issues on using -stringByAddingPercentEscapesUsingEncoding:. For more information on that, check out Objective-c iPhone percent encode a string?.
Your LAT is negative. So the - gets replaced twice.