<p><a href="http://vimeo.com/23486376" title="Rebecca Black's Friday on Rock Band"><img src="http://b.vimeocdn.com/ts/152/946/152946954_200.jpg" alt="Rebecca Black's Friday on Rock Band" /></a></p><p></p><p>Cast: <a href="http://vimeo.com/thenerdery" style="color: #2786c2; text-decoration: none;">The Nerdery</a></p>
I got a string like above, I am wondering what's the best way in objective-c to get the "http://b.vimeocdn.com/ts/152/946/152946954_200.jpg" substring? NSScanner? NSString methods? Thanks!
update: the string is actually:
<p><a href="http://vimeo.com/23333305" title="Ad League Bowling Championship"><img src="http://b.vimeocdn.com/ts/151/787/151787049_200.jpg" alt="Ad League Bowling Championship" /></a></p><p></p><p>Cast: <a href="http://vimeo.com/thenerdery" style="color: #2786c2; text-decoration: none;">The Nerdery</a></p>
Here's another approach:
Transform the string into actual HTML. In other words, conver the < and > stuff into < and >
Run it through an NSXMLParser
In the parser delegate, check the attributes dictionary passed into the -parser:didStartElement:namespaceURI:qualifiedName:attributes: method.
If the element name is #"img", then the attributes dictionary should have a key called #"src" that maps to the string #"http://b.vimeocdn.com/ts/152/946/152946954_200.jpg".
Once you have the string, it's trivial to transform it into an NSURL using +[NSURL URLWithString:]
This will work regardless of how the source HTML changes over time. The other approaches suggested are extremely fragile, because they rely on things like src being all lowercase and there only being a single src attribute anywhere in the string (what if you have 2?). You don't want to parse HTML; you want to get an attribute out of an XML element. So use the built-in way of doing it! :)
NSString *strComplete = #"<p><a href="http://vimeo.com/23486376" title="Rebecca Black's Friday on Rock Band"><img src="http://b.vimeocdn.com/ts/152/946/152946954_200.jpg" alt="Rebecca Black's Friday on Rock Band" /></a></p><p></p><p>Cast: <a href="http://vimeo.com/thenerdery" style="color: #2786c2; text-decoration: none;">The Nerdery</a></p>";
NSArray *arrComplete = [strComplete componentSeparatedBy:#"src="];
NSString *strSecond = [arrComplete objectAtIndex:1];
NSArray *arrSecond = [strSecond componentSeparatedBy:#" alt"];
NSString *strURLImage = [arrSecond objectAtIndex:0];
strURLImage will be your desired string.
You can use a framework for URL detection and parsing, such as AutoHyperlinks. On iOS, you will, of course, have to build it statically or build the source directly into your app.
Alternatively, for iOS only (currently), use NSDataDetector. Data detectors can find URLs, physical addresses, phone numbers, etc.; you tell it what you'll want from the string, then use the methods of NSRegularExpression to obtain its findings.
Assuming complete string is called myString, you can do:
NSRange srcRange = [myString rangeOfString:#"src="];
NSRange endrange = [myString rangeOfString:#"\"" options:nil range:
NSMakeRange(srcRange.location + 5, [mystring count] - srcRange.location - 6)];
NSString *url = [myString subStringWithRange:
NSMakeRange(srcRange.location + 5, srcRange.location + 5 + endRange.lenght)];
I haven't tested that so I could have put a +5 instead of a +6, so if the string has got some chars less or more than you want, just change the numbers in the last line.
Related
I need to display subscripts and superscripts (only arabic numerals) within a UILabel. The data is taken from an XML file. Here is the snippet of XML file:
<text><![CDATA[Hello World X\u00B2 World Hello]]></text>
Its supposed to display X2 (2 as superscript). When I read the string from the NSXMLParser and display it in the UILabel, it displays it as X\u00B2. Any ideas on how to make it work?
I think you can do something like this, assuming the CDATA contents have been read into an NSString and passed into this function:
-(NSString *)removeUnicodeEscapes:(NSString *)stringWithUnicodeEscapes {
unichar codeValue;
NSMutableString *result = [stringWithUnicodeEscapes mutableCopy];
NSRange unicodeLocation = [result rangeOfString:#"\\u"];
while (unicodeLocation.location != NSNotFound) {
// Get the 4-character hex code
NSRange charCodeRange = NSMakeRange(unicodeLocation.location + 2, 4);
NSString *charCode = [result substringWithRange:charCodeRange];
[[NSScanner scannerWithString:charCode] scanHexInt:&codeValue];
// Convert it to an NSString and replace in original string
NSString *unicodeChar = [NSString stringWithFormat:%C", codeValue];
NSRange replacementRange = NSMakeRange(unicodeLocation.location, 6);
[result replaceCharactersInRange:replacementRange withString:unicodeChar];
unicodeLocation = [result rangeOfString:#"\\u"];
}
return result;
}
I haven't had a chance to try this out, but I think the basic approach would work
\u00B2 is not any sort of XML encoding for characters. Apparently your data source has defined their own encoding scheme (which, frankly, is pretty stupid as XML is capable of encoding these directly, using entities outside of CDATA blocks).
In any case, you'll have to write your own parser that handles \u#### and converts that to the correct character.
I asked the question to my colleague and he gave me a nice and simple workaround. Am describing it here, in case others also get stuck at this.
Firstly goto this link. It has a list of all subscripts and superscripts. For example, in my case, I clicked on "superscript 0". In the following HTML page detailing "superscript 0", goto "Java Data" section and copy the "⁰". You can either place this directly in XML or write a simple regex in obj-c to replace \u00B2 with "⁰". And you will get nice X⁰. Do the same fro anyother superscript or subscript that you might want to display.
I have a NSString which is an address:
"210 Queen Street East Brampton"
I need to ping Google's Geocoding server with a URL constructed from this string that needs to look like this:
http://maps.googleapis.com/maps/api/geocode/xml?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=true_or_false
Clearly, I can append strings together to create a master string
called temp and then just
use this code to send the request:
NSMutableString *url = [[NSMutableString alloc] initWithString:temp];
The challenge I am facing is: How do I introduce the '+' signs between words instead of the spaces?
Can anyone suggest if there are built in functions in Objective C that can do this or what's the simplest way to robustly implement this?
Thanks.
I was hoping to find some method that would let you replace characters, but haven't found it yet. The simplest solution I can think of so far would be the following:
NSString *myAddress = #"210 Queen Street East Brampton"; // or whatever the current address is
NSArray *components = [myAddress componentsSeparatedByString:#" "];
// this will strip the words out;
NSString *addressForURL = [components componentsJoinedByString:#"+"];
This should return addressForURL as 210+Queen+Street+East+Brampton. If there is more you need to do with it, this should at least give you a base to start from
#"/News/some news text/"
#"/News/some other news text/"
#"/About/Some about text/"
#"/Abcdefg/Some abcdefg text/some more abcdefg text"
How do I cut out the first part of the strings, so that I end up with the following strings?
#"/News/"
#"/News/"
#"/About/"
#"/Abcdefg/"
Use componentsSeparatedByString: to break the string up:
NSArray *components=[string componentsSeparatedByString:#"/"];
if ([components count]>=2) {
// Text after the first slash is second item in the array
return [NSString stringWithFormat:#"/%#/",[components objectAtIndex:1]];
} else {
return nil; // Up to you what happens in this situation
}
If these are pathnames, you may want to look into the path-related methods of NSString, such as pathComponents and pathByDeletingLastPathComponent.
While it's pretty unlikely that the path separator is ever going to change, it's nonetheless a good habit to not rely on such things and use dedicated path-manipulation methods in preference to assuming that the path separator will be a certain character.
EDIT from the year 2013: Or use URLs (more specifically, NS/CFURL objects), which Apple has made pretty clear are the proper way to refer to files from now on, and are necessary for some tasks in a sandbox.
I have an NSString with a number of sentences, and I'd like to split it into an NSArray of sentences. Has anybody solved this problem before? I found enumerateSubstringsInRange:options:usingBlock: which is able to do it, but it looks like it isn't available on the iPhone (Snow Leopard only). I thought about splitting the string based on periods, but that doesn't seem very robust.
So far my best option seems to be to use RegexKitLite to regex it into an array of sentences. Solutions?
Use CFStringTokenizer. You'll want to create the tokenizer with the kCFStringTokenizerUnitSentence option.
I would use a scanner for it,
NSScanner *sherLock = [NSCanner scannerWithString:yourString]; // autoreleased
NSMutableArray *theArray = [NSMutableArray array]; // autoreleased
while( ![sherLock isAtEnd] ){
NSString *sentence = #"";
// . + a space, your sentences probably will have that, and you
// could try scanning for a newline \n but iam not sure your sentences
// are seperated by it
[sherLock scanUpToString:#". " inToString:&sentence];
[theArray addObject:sentence];
}
This should do it, there could be some little mistakes in it but this is how I would do it.
You should lookup NSScanner in the docs though.. you might come across a method that is
better for this situation.
I haven't used them for a while but I think you can do this with NSString, NSCharacterSet and NSScanner. You create a character set that holds end sentence punctuation and then call -[NSScanner scanUpToCharactersFromSet:intoString:]. Each Scan will suck out a sentence into a string and you keep calling the method until the scanner runs out of string.
Of course, the text has to be well punctuated.
How about:
NSArray *sentences = [string componentsSeparatedByString:#". "];
This will return an array("One","Two","Three") from a string "One. Two. Three."
NSArray *sentences = [astring componentsSeparatedByCharactersInSet:[NSCharacterSet punctuationCharacterSet] ];
I'd like to make a URL click able in the email app. The problem is that a parameterized URL breaks this because of "&" in the URL. The body variable below is the problem line. Both versions of "body" are incorrect. Once the email app opens, text stops at "...link:". What is needed to encode the ampersand?
NSString *subject = #"This is a test";
NSString *encodedSubject =
[subject stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
//NSString *body = #"This is a link: <a href='http://somewhere.com/two.woa/wa?id=000¶m=0'>click me</a>"; //original
NSString *body = #"This is a link: <a href='http://somewhere.com/two.woa/wa?id=000¶m=0'>click me</a>"; //have also tried &
NSString *encodedBody =
[body stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *formattedURL = [NSString stringWithFormat: #"mailto:myname#somedomain.com?subject=%#&body=%#", encodedSubject, encodedBody];
NSURL *url = [[NSURL alloc] initWithString:formattedURL];
[[UIApplication sharedApplication] openURL:url];
the ampersand would be %26 for HEX in URL Encoding standards
I've been using -[NSString gtm_stringByEscapingForURLArgument], which is provided in Google Toolbox for Mac, specifically in GTMNSString+URLArguments.h and GTMNSString+URLArguments.m.
You can use a hex representation of the character, in this case %26.
you can simply use CFURLCreateStringByAddingPercentEscapes with CFBridgingRelease for ARC support
NSString *subject = #"This is a test";
// Encode all the reserved characters, per RFC 3986
// (<http://www.ietf.org/rfc/rfc3986.txt>)
NSString *encodedSubject =
(NSString *) CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
(CFStringRef)subject,
NULL,
(CFStringRef)#"!*'();:#&=+$,/?%#[]",
kCFStringEncodingUTF8));
You use stringByAddingPercentEscapesUsingEncoding, exactly like you are doing.
The problem is that you aren't using it enough. The format into which you're inserting the encoded body also has an ampersand, which you have not encoded. Tack the unencoded string onto it instead, and encode them (using stringByAddingPercentEscapesUsingEncoding) together.
<a href='http://somewhere.com/two.woa/wa?id=000¶m=0'>click me</a>
Is correct, although ‘&’ is more commonly used than ‘&’ or ‘,’.
If the ‘stringByAddingPercentEscapesUsingEncoding’ method does what it says on the tin, it should work(*), but the NSString documentation looks a bit unclear on which characters exactly are escaped. Check what you are ending up with, the URL should be something like:
mailto:bob#example.com?subject=test&body=Link%3A%3Ca%20href%3D%22http%3A//example.com/script%3Fp1%3Da%26amp%3Bp2%3Db%22%3Elink%3C/a%3E
(*: modulo the usual disclaimer that mailto: link parameters like ‘subject’ and ‘body’ are non-standard, will fail in many situations, and should generally be avoided.)
Once the email app opens, text stops at "...link:".
If ‘stringByAddingPercentEscapesUsingEncoding’ is not escaping ‘<’ to ‘%3C’, that could be the problem. Otherwise, it might not be anything to do with escapes, but a deliberate mailer-level restriction to disallow ‘<’. As previously mentioned, ?body=... is not a reliable feature.
In any case, you shouldn't expect the mailer to recognise the HTML and try to send an HTML mail; very few will do that.
Example of use of %26 instead of & without this attributes arrived in PHP as an array!
var urlb='/tools/lister.php?type=101%26ID='+ID; // %26 instead of &
window.location.href=urlb;