How to remove new line characters from NSString in a webservice response? - iphone

I am presently getting a Webservice Response which contains many new line characters. I have tried the following approaches but still i am not able to eliminate the New Line Characters.
1)
responseString = [responseString stringByReplacingOccurrencesOfString:#"\n" withString:#""];
2)
responseString = [responseString stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]];
3)
NSRange foundRange = [responseString rangeOfString:#"\n"];
if (foundRange.location != NSNotFound)
[responseString stringByReplacingOccurrencesOfString:#"\n"
withString:#""
options:0
range:foundRange];
My Webservice respsonse is in this format.
META NAME="ColdFusionMXEdition" CONTENT="ColdFusion DevNet Edition - Not for Production Use."?
wddxPacket version='1.0'><header/><data><string>{"MESSAGE":"","CODE":1,"RESPONSE":{"FILENAME":"CustomerSkillsIntro","PLAYLIST":[{"TIMEOUT":73,"TITLE":"Greet","QUESTIONNUMBER":1,"TIMEIN":71,"VALIDRESPONSE":1},{"TIMEOUT":77,"TITLE":"Have Name Tag","QUESTIONNUMBER":2,"TIMEIN":74,"VALIDRESPONSE":1},{"TIMEOUT":83,"TITLE":"Greet","QUESTIONNUMBER":3,"TIMEIN":78,"VALIDRESPONSE":1},{"TIMEOUT":112,"TITLE":"Helping Do My Job","QUESTIONNUMBER":4,"TIMEIN":109,"VALIDRESPONSE":1},{"TIMEOUT":134,"TITLE":"Greet Happily","QUESTIONNUMBER":5,"TIMEIN":131,"VALIDRESPONSE":1},{"TIMEOUT":144,"TITLE":"Stay cheerful when resident is crabby","QUESTIONNUMBER":6,"TIMEIN":141,"VALIDRESPONSE":1},{"TIMEOUT":154,"TITLE":"Bond with the new resident","QUESTIONNUMBER":7,"TIMEIN":151,"VALIDRESPONSE":1},...................
My requirement is to capture only the part of the string from {"MESSAGE":"","CODE":1, till the end. But i am getting too many white spaces and new line characters before the required part.

It looks like you could simplify your problem by taking string from first occurance of '{' to last occurance of '}'.
Code below ensures the result you want with different approach. Why go trough the process of removing white space if you say you need only the part "from {"MESSAGE":"","CODE":1, till the end.`"
NSRange start = [responseString rangeOfString:#"{"];
NSRange end = [responseString rangeOfString:#"}" options:NSBackwardsSearch];
NSString *result = nil;
if ((start.location != NSNotFound)&&(start.location != NSNotFound))
{
NSRange resultRange = NSMakeRange(start.location,end.location - start.location + 1);
result = [responseString substringWithRange: resultRange];
NSLog (#"returning with result: %#", result);
}
else
{
NSLog (#"abort mission");
}

Related

regex to find hashtags in tweet not working correctly

I am trying to build a function to find a hashtags in tweest. And surround them with an HTML <a> tag. so that I can link to them. Here is what I do.
NSError* error = nil;
NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:#"(?:\\s|\\A)[##]+([A-Za-z0-9-_]+)" options:0 error:&error];
NSArray* matches = [regex matchesInString:tweetText options:0 range:NSMakeRange(0, [tweetText length])];
for ( NSTextCheckingResult* match in matches )
{
NSString* matchText = [tweetText substringWithRange:[match range]];
NSString *matchText2 = [matchText stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSString *search = [matchText2 stringByReplacingOccurrencesOfString:#"#"
withString:#""];
NSString *searchHTML= [NSString stringWithFormat:#"<a href='https://twitter.com/search?q=%%23%#'>%#</a>",search,matchText];
tweetText = [tweetText stringByReplacingOccurrencesOfString:matchText
withString:searchHTML];
NSLog(#"match: %#", tweetText);
}
Before I execute this function, the tweetText is looped through another function to find the URL. so the tweet can contain the following. <a href='http://google.be' target='_blank'>http://google.be</a>
Now sometimes it places another tag around other links and not only around the hashtags.
Can somebody help me with this.
TIP
I am trying to transform the following JAVA code into OBJ-C
String patternStr = "(?:\\s|\\A)[##]+([A-Za-z0-9-_]+)"
Pattern pattern = Pattern.compile(patternStr)
Matcher matcher = pattern.matcher(tweetText)
String result = "";
// Search for Hashtags
while (matcher.find()) {
result = matcher.group();
result = result.replace(" ", "");
String search = result.replace("#", "");
String searchHTML="<a href='http://search.twitter.com/search?q=" + search + "'>" + result + "</a>"
tweetText = tweetText.replace(result,searchHTML);
}
EDIT
Gers, we kijken er al naar uit! “#GersPardoel: We zitten in België straks naar Genk!!<a href='<a href<a href='https://twitter.com/search?q=%23='http'>='http</a>s://twitter.com/search?q=%23https:/'>https:/</a>/twitter.com/search?q=%23engaan'> #engaan</a>” #GOS12 #genk #fb
The problem is that you're modifying your tweetText variable (tweetText = ...) as you're looping through matches. Imagine what happens the next time code enters the loop? The substringWithRange will not work properly since it was created on the original string. Try to rectify the problem and if you're unable to do it, check the solution here: http://pastebin.com/DyQqtRzA
EDIT: Adding solution here:
NSError* error = nil;
NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:#"(?:\\s|\\A)[##]+([A-Za-z0-9-_]+)" options:0 error:&error];
NSArray* matches = [regex matchesInString:tweetText options:0 range:NSMakeRange(0, [tweetText length])];
NSString* processedString = [[tweetText copy] autorelease];
for ( NSTextCheckingResult* match in matches )
{
NSString* matchText = [tweetText substringWithRange:[match range]];
NSString *matchText2 = [matchText stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSString *search = [matchText2 stringByReplacingOccurrencesOfString:#"#"
withString:#""];
NSString *searchHTML= [NSString stringWithFormat:#"<a href='https://twitter.com/search?q=%%23%#'>%#</a>",search,matchText];
processedString = [processedString stringByReplacingOccurrencesOfString:matchText
withString:searchHTML];
NSLog(#"match: %#", processedString);
}

Replacing instances of a character with two different characters in Objective-C

I have a huge amount of NSStrings in a database that get passed to a view controller in an iOS app. They are formatted as "This is a message with $specially formatted$ content".
However, I need to change the '$' at the start of the special formatting with a '[' and the '$' at the end with ']'. I have a feeling I can use an NSScanner but so far all of my attempts have produced wackily concatenated strings!
Is there a simple way to recognise a substring encapsulated by '$' and swap them out with start/end characters? Please note that a lot of the NSStrings have multiple '$' substrings.
Thanks!
You can use regular expressions:
NSMutableString *str = [#"Hello $World$, foo $bar$." mutableCopy];
NSRegularExpression *regex;
regex = [NSRegularExpression regularExpressionWithPattern:#"\\$([^$]*)\\$"
options:0
error:NULL];
[regex replaceMatchesInString:str
options:0
range:NSMakeRange(0, [str length])
withTemplate:#"[$1]"];
NSLog(#"%#", str);
// Output:
// Hello [World], foo [bar].
The pattern #"\\$([^$]*)\\$" searches for
$<zero_or_more_characters_which_are_not_a_dollarsign>$
and all occurrences are then replaced by [...]. The pattern contains so many backslashes because the $ must be escaped in the regular expression pattern.
There is also stringByReplacingMatchesInString if you want to create a new string instead of modifying the original string.
I think replaceOccurrencesOfString: won't work cause you have start$ and end$.
But if you seperate the Strings with [string componentsSeperatedByString:#"$"] you get an Array of substrings, so every second string is your "$specially formatted$"-string
This should work!
NSString *str = #"This is a message with $specially formatted$ content";
NSString *original = #"$";
NSString *replacement1 = #"[";
NSString *replacement2 = #"]";
BOOL start = YES;
NSRange rOriginal = [str rangeOfString: original];
while (NSNotFound != rOriginal.location) {
str = [str stringByReplacingCharactersInRange: rOriginal withString:(start?replacement1:replacement2)];
start = !start;
rOriginal = [str rangeOfString: original];
}
NSLog(#"%#", str);
Enjoy Programming!
// string = #"This is a $special markup$ sentence."
NSArray *components = [string componentsSeparatedByString:#"$"];
// sanity checks
if (components.count < 2) return; // maybe no $ characters found
if (components.count % 2) return; // not an even number of $s
NSMutableString *out = [NSMutableString string];
for (int i=0; i< components.count; i++) {
[out appendString:components[i]];
[out appendString: (i % 2) ? #"]" : #"[" ];
}
// out = #"This is a [special markup] sentence."
Try this one
NSMutableString *string=[[NSMutableString alloc]initWithString:#"This is a message with $specially formatted$ content. This is a message with $specially formatted$ content"];
NSMutableString *string=[[NSMutableString alloc]initWithString:#"This is a message with $specially formatted$ content. This is a message with $specially formatted$ content"];
BOOL open=YES;
for (NSUInteger i=0; i<[string length];i++) {
if ([string characterAtIndex:i]=='$') {
if (open) {
[string replaceCharactersInRange:NSMakeRange(i, 1) withString:#"["];
open=!open;
}
else{
[string replaceCharactersInRange:NSMakeRange(i, 1) withString:#"]"];
open=!open;
}
}
}
NSLog(#"-->%#",string);
Output:
-->This is a message with [specially formatted] content. This is a message with [specially formatted] content

Objective-C: Find consonants in string

I have a string that contains words with consonants and vowels. How can I extract only consonants from the string?
NSString *str = #"consonants.";
Result must be:
cnsnnts
You could make a character set with all the vowels (#"aeiouy")
+ (id)characterSetWithCharactersInString:(NSString *)aString
then use the
- (NSString *)stringByTrimmingCharactersInSet:(NSCharacterSet *)set
method.
EDIT: This will only remove vowels at the beginning and end of the string as pointed out in the other post, what you could do instead is use
- (NSArray *)componentsSeparatedByCharactersInSet:(NSCharacterSet *)separator
then stick the components back together. You may also need to include capitalized versions of the vowels in the set, and if you want to also deal with accents (à á è è ê ì etc...) you'll probably have to include that also.
Unfortunately stringByTrimmingCharactersInSet wont work as it only trim leading and ending characters, but you could try using a regular expression and substitution like this:
[[NSRegularExpression
regularExpressionWithPattern:#"[^bcdefghjklmnpqrstvwx]"
options:NSRegularExpressionCaseInsensitive
error:NULL]
stringByReplacingMatchesInString:str
options:0
range:NSMakeRange(0, [str length])
withTemplate:#""]
You probably want to tune the regex and options for your needs.
Possible, for sure not-optimal, solution. I'm printing intermediate results for your learning. Take care of memory allocation (I didn't care). Hopefully someone will send you a better solution, but you can copy and paste this for the moment.
NSString *test = #"Try to get all consonants";
NSMutableString *found = [[NSMutableString alloc] init];
NSInteger loc = 0;
NSCharacterSet *consonants = [NSCharacterSet characterSetWithCharactersInString:#"bcdfghjklmnpqrstvwxyz"];
while(loc!=NSNotFound && loc<[test length]) {
NSRange r = [[test lowercaseString] rangeOfCharacterFromSet:consonants options:0 range:NSMakeRange(loc, [test length]-loc)];
if(r.location!=NSNotFound) {
NSString *temp = [test substringWithRange:r];
NSLog(#"Range: %# Temp: %#",NSStringFromRange(r), temp);
[found appendString:temp];
loc=r.location+r.length;
} else {
loc=NSNotFound;
}
}
NSLog(#"Found: %#",found);
Here is a NSString category that does the job:
- (NSString *)consonants
{
NSString *result = [NSString stringWithString:self];
NSCharacterSet *characterSet = [NSCharacterSet characterSetWithCharactersInString:#"aeiou"];
while(1)
{
NSRange range = [result rangeOfCharacterFromSet:characterSet options:NSCaseInsensitiveSearch];
if(range.location == NSNotFound)
break;
result = [result stringByReplacingCharactersInRange:range withString:#""];
}
return result;
}

NSRegularExpression and capture groups on iphone

I need a little kickstart on regex on the iphone.
Basically I have a list of dates in a private MediaWiki in the form of
*185 BC: SOME EVENT HERE
*2001: SOME OTHER EVENT MUCH LATER
I now want to parse that into an Object that has a NSDate property and a -say- NSString property.
I have this so far: (rawContentString contains the mediawiki syntax of the page)
NSString* regexString =#"\\*( *[0-9]{1,}.*): (.*)";
NSRegularExpressionOptions options = NSRegularExpressionCaseInsensitive;
NSError* error = NULL;
NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:regexString options:options error:&error];
if (error) {
NSLog(#"%#", [error description]);
}
NSArray* results = [regex matchesInString:rawContentString options:0 range:NSMakeRange(0, [rawContentString length])];
for (NSTextCheckingResult* result in results) {
NSString* resultString = [rawContentString substringWithRange:result.range];
NSLog(#"%#",resultString);
}
unfortunately I think the regex is not working the way I hope and I dont know how to capture the matched date and text.
Any help would be great.
BTW: there is not by any chance a regex Pattern compilation for MediaWiki Syntax out there somewhere ?
Thanks in advance
Heiko
*
My issue was that I was using matchesInString and I needed to use firstMatchInString because it returns multiple ranges in a single NSTextCheckingResult.
This is counter intuitive, but it worked.
I got the answer from http://snipplr.com/view/63340/
My Code (to parse credit card track data):
NSRegularExpression *track1Pattern = [NSRegularExpression regularExpressionWithPattern:#"%.(.+?)\\^(.+?)\\^([0-9]{2})([0-9]{2}).+?\\?." options:NSRegularExpressionCaseInsensitive error:&error];
NSTextCheckingResult *result = [track1Pattern firstMatchInString:trackString options:NSMatchingReportCompletion range:NSMakeRange(0, trackString.length)];
self.cardNumber = [trackString substringWithRange: [result rangeAtIndex:1]];
self.cardHolderName = [trackString substringWithRange: [result rangeAtIndex:2]];
self.expirationMonth = [trackString substringWithRange: [result rangeAtIndex:3]];
self.expirationYear = [trackString substringWithRange: [result rangeAtIndex:4]];
As for the regex, i think something around these lines:
\*([ 0-9]{1,}.*):(.*)
should work better to what you need. You're not escaping the first *, and why is there a * in the first group statement?

Remove newline character from first line of NSString

How can I remove the first \n character from an NSString?
Edit: Just to clarify, what I would like to do is:
If the first line of the string contains a \n character, delete it else do nothing.
ie: If the string is like this:
#"\nhello, this is the first line\nthis is the second line"
and opposed to a string that does not contain a newline in the first line:
#"hello, this is the first line\nthis is the second line."
I hope that makes it more clear.
[string stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]]
will trim your string from any kind of newlines, if that's what you want.
[string stringByReplacingOccurrencesOfString:#"\n" withString:#"" options:0 range:NSMakeRange(0, 1)]
will do exactly what you ask and remove newline if it's the first character in the string
This should do the trick:
NSString * ReplaceFirstNewLine(NSString * original)
{
NSMutableString * newString = [NSMutableString stringWithString:original];
NSRange foundRange = [original rangeOfString:#"\n"];
if (foundRange.location != NSNotFound)
{
[newString replaceCharactersInRange:foundRange
withString:#""];
}
return [[newString retain] autorelease];
}
Rather than creating an NSMutableString and using a few retain/release calls, you can use only the original string and simplify the code by using the following instead: (requires 10.5+)
NSRange foundRange = [original rangeOfString:#"\n"];
if (foundRange.location != NSNotFound)
[original stringByReplacingOccurrencesOfString:#"\n"
withString:#""
options:0
range:foundRange];
(See -stringByReplacingOccurrencesOfString:withString:options:range: for details.)
The result of the last call method call can even be safely assigned back to original IF you autorelease what's there first so you don't leak the memory.