Adding HTML to iOS I get expected '[' error - html

I am getting a weird error on XCODE: expected '[' error and my build fails. This is the code
[descWeb loadHTMLString:[NSString stringWithFormat:#"<html><body p style='color:black' text="#000000" face="HelveticaNeue" size="5">%</body></html>",strtemp] baseURL: nil];
This is the whole code block
[descWeb removeFromSuperview];
descWeb = [[UIWebView alloc]init];
descWeb.delegate = self;
descWeb.tag = 1;
[descWeb setOpaque:NO];
[descWeb setBackgroundColor:[UIColor clearColor]];
descWeb.frame = CGRectMake(3, 7, 314, 350);
[descWeb loadHTMLString:[NSString stringWithFormat:#"<html><body p style='color:black' text="#000000" face="HelveticaNeue" size="5">%</body></html>",strtemp] baseURL: nil];
[scrollView addSubview:descWeb];
Thank you for looking and your help

You need to add slashes to the quotation marks.
NSString *string = #"A quotation mark: \"";
NSLog(#"%#", string );
Output:
A quotation mark: "

You're mixing single and double quotes, so the stringWithFormat argument currently ends with text=", and Xcode can't balance the ['s and ]'s after this line:
[descWeb loadHTMLString:[NSString stringWithFormat:#"<html><body p style='color:black' text="#000000" face="HelveticaNeue" size="5">%</body></html>",strtemp] baseURL: nil];
Try using single quotes ' instead of double " inside your HTML.

What the others have said, about escaping the double quotes (and missing an #) is correct.
Another option though, that may keep your code cleaner and is less tedious than escaping the double quotes, is to keep all of your HTML in .html files and load the contents of those files instead.
For example, create a file in your project called desc.html with the HTML you need in there. Then change your code to:
__autoreleasing NSError* error = nil;
NSStringEncoding encoding = 0;
NSString* htmlString = [NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"desc" ofType:#"html"] usedEncoding:&encoding error:&error];
if (!htmlString)
{
NSLog(#"Error: %#", error);
return;
}
[descWeb loadHTMLString:[NSString stringWithFormat:htmlString, strtemp] baseURL:nil];
Besides keeping your project cleaner, this also makes it easier for you or someone else (designer etc) to update the HTML without changing your code.

Related

IOS parse HTML but get weird value " "

Hi i'm doing my assignment and I want to get some information from this website:. I used TFHpple.h from Raywenderlich tutorial .Every thing went fine until I try to get the view count(this number: 8.024.835 ) but in my code it return this number "
" I NSLOG its element.raw then I see this code:
<p>
Số lượt xem:
<span class="color-fuchsia" id="PageViews"/>    
Yêu thích:
<span class="color-hotpink" id="LikeCount"/>
</p>
but when I use firebug to its html, it display like this:
<p>
Số lượt xem:
<span id="PageViews" class="color-fuchsia">8.024.835</span>
     Yêu thích:
<span id="LikeCount" class="color-hotpink">1.565</span>
</p>
How to get the correct value please help me.
this is my code to parse and nslog the html.
-(void) GetBookViewCount{
NSURL *url = [NSURL URLWithString:#“http://blogtruyen.com/truyen/conan”];
NSData *htmlData = [NSData dataWithContentsOfURL:url];
TFHpple *parser = [TFHpple hppleWithHTMLData:htmlData];
NSString* XpathQueryString = #"//div[#class='description']/p";
NSArray *Nodes = [parser searchWithXPathQuery:XpathQueryString];
for (TFHppleElement *element in Nodes) {
NSLog(#"%#",element.raw);
}
}
It looks like there a bunch of odd whitespace characters in between the two spans there.
    
This number here:
Looks like an ascii code for a symbol (though I can't find one that matches), so when you parse the code it might be breaking when you hit those characters. I'm not familiar with TFHpple.h but you may need to implement some input sanitization (stripping out those characters).

Getting the HTML tags in hpple as well as text?

The code below takes all of the text from a certain div. Is it possible for me to take all the text from the div as well as the html attributes? So it also adds all of the <p> </p>'s and <br> </br>'s to the string, myString?
//trims string from previous page
NSString *trimmedString = [stringy stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSData *data = [[NSString stringWithContentsOfURL:[NSURL URLWithString:trimmedString]] dataUsingEncoding:NSUTF8StringEncoding];
TFHpple *xpathParser = [[TFHpple alloc] initWithHTMLData:data];
NSArray *elements = [xpathParser searchWithXPathQuery:#"//div[#class='field-item even']"];
TFHppleElement *element = [elements lastObject]; //may need to change this number?!
NSString *mystring = [self getStringForTFHppleElement:element];
trimmedTextView.text = [trimmedTextView.text stringByAppendingString:mystring];
Method here:
-(NSString*) getStringForTFHppleElement:(TFHppleElement *)element
{
NSMutableString *result = [NSMutableString new];
// Iterate recursively through all children
for (TFHppleElement *child in [element children])
[result appendString:[self getStringForTFHppleElement:child]];
// Hpple creates a <text> node when it parses texts
if ([element.tagName isEqualToString:#"text"])
[result appendString:element.content];
return result;
}
Any ideas would be appreciated. Cheers.
Try this:
NSString *htmlDataString = [webView stringByEvaluatingJavaScriptFromString: #"document.documentElement.outerHTML"];
This will take all the HTML out to string. You can then parse it in your native code and find div which is your interest what you have did in above example.
You can do it as well with any DOM element in your HTML like:
NSString *htmlDataString = [webView stringByEvaluatingJavaScriptFromString: #"document.documentElement.getElemenById('mydiv')"];
which is more efficient but requires a bit of javascript skill.

iOS: Strip <img...> from NSString (a html string)

So I have an NSString which is basically an html string with all the usual html elements. The specific thing I would like to do is to just strip it from all the img tags.
The img tags may or may not have max-width, style or other attributes so I do not know their length up front. They always end with />
How could I do this?
EDIT: Based on nicolasthenoz's answer, I came up with a solution that requires less code:
NSString *HTMLTagss = #"<img[^>]*>"; //regex to remove img tag
NSString *stringWithoutImage = [htmlString stringByReplacingOccurrencesOfRegex:HTMLTagss withString:#""];
You can use the NSString method stringByReplacingOccurrencesOfString with the NSRegularExpressionSearch option:
NSString *result = [html stringByReplacingOccurrencesOfString:#"<img[^>]*>" withString:#"" options:NSCaseInsensitiveSearch | NSRegularExpressionSearch range:NSMakeRange(0, [html length])];
Or you can also use the replaceMatchesInString method of NSRegularExpression. Thus, assuming you have your html in a NSMutableString *html, you can:
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"<img[^>]*>"
options:NSRegularExpressionCaseInsensitive
error:nil];
[regex replaceMatchesInString:html
options:0
range:NSMakeRange(0, html.length)
withTemplate:#""];
I'd personally lean towards one of these options over the stringByReplacingOccurrencesOfRegex method of RegexKitLite. There's no need to introduce a third-party library for something as simple as this unless there was some other compelling issue.
Use a regular expression, find the matchs in your string and remove them !
Here is how
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"<img[^>]*>"
options:NSRegularExpressionCaseInsensitive
error:nil];
NSMutableString* mutableString = [yourStringToStripFrom mutableCopy];
NSInteger offset = 0; // keeps track of range changes in the string due to replacements.
for (NSTextCheckingResult* result in [regex matchesInString:yourStringToStripFrom
options:0
range:NSMakeRange(0, [yourStringToStripFrom length])]) {
NSRange resultRange = [result range];
resultRange.location += offset;
NSString* match = [regex replacementStringForResult:result
inString:mutableString
offset:offset
template:#"$0"];
// make the replacement
[mutableString replaceCharactersInRange:resultRange withString:#""];
// update the offset based on the replacement
offset += ([match length] - resultRange.length);
}
You can use below function in Swift 4,5:
func filterImgTag(text: String) -> String{
return text.replacingOccurrences(of: "<img[^>]*>", with: "", options: String.CompareOptions.regularExpression)
}
Hope it can help you all! comment below if it work for you. Thanks.

Format link with parentheses for TWRequest

I am trying to embed a link in a twee sent out from iPhone. The URL ends with a closing parentheses. That parentheses gets dropped and causes the t.co link to fail. I have tried encoding, tagging with href. Nothing seems to bring that closing parentheses into the resulting URL. See what I tried last, it failed for having too many characters. Why didn't it get shortened?:
if (tweetsEnabled && twitToSendTo != nil) {
// Build the string
NSString *mapURL = [NSString stringWithFormat:#"http://maps.google.com/maps?q=%#,%#+(%#)",newLogEvent.lattitude,newLogEvent.longitude,eventString];
NSString *encodedURL = [mapURL encodeString:NSUTF8StringEncoding];
NSString *tweetString = [NSString stringWithFormat:#"%#\n<a href>=\"%#\"></a>",note,encodedURL];
NSLog(#"%#",tweetString);
// Send it
[self performSelectorOnMainThread:#selector(postToTwitterWithString:) withObject:tweetString waitUntilDone:NO];
}
In its simplest form,without encoding, without the tags and without the +(%#), the link works. It displays as a t.co shortened link and brings up the webpage as intended. But I need the string in the parentheses to give text to the label and it seems it should be very easy to get that in.
Here is the output of the NSLog:
2012-08-14 09:57:43:551 app[2683:34071] -[logger insertLogEvent:withLocation:isArrival:] [Line 641] Arrival logged for Home
<a href>="http%3A%2F%2Fmaps.google.com%2Fmaps%3Fq%3D26.17071170827948%2C-80.16628238379971%2B%28Arrival%29"></a>
This worked:
// Build the string
NSString *mapURL = [NSString stringWithFormat:#"http://maps.google.com/maps?q=%#,%#+%%28%#%%29",newLogEvent.lattitude,newLogEvent.longitude,eventString];
NSString *tweetString = [NSString stringWithFormat:#"%#\n%#",note,mapURL];
I am not now encoding the entire string but only the parenthesis. This handy post, How to add percent sign to NSString , is where I found the correct way to get the percent signs in for the encoding.

HTML from NSAttributedString

Rather than converting HTML to an attributed string, I need to convert it back to HTML. This can easily be done on Mac as can be seen here: http://www.justria.com/2011/01/18/how-to-convert-nsattributedstring-to-html-markup/
Unfortuately, the method dataFromRange:documentAttributes: is only available on Mac via the NSAttributedString AppKit Additions.
My question is how can you do this on iOS?
Not the 'easy' way, but what about iterating through the attributes of the string using:
- (void)enumerateAttributesInRange:(NSRange)enumerationRange
options:(NSAttributedStringEnumerationOptions)opts
usingBlock:(void (^)(NSDictionary *attrs, NSRange range, BOOL *stop))block
Have an NSMutableString variable to accumulate the HTML (lets call it 'html'). In the block, you would construct the HTML manually using strings. For instance if the text attributes 'attrs' specify red, bold text:
[html appendFormat:#"<span style='color:red; font-weight: bold;'>%#</span>", [originalStr substringWithRange:range]]
EDIT: Stumbled across this yesterday:
NSAttributedString+HTMLFromRange category from "UliKit"
(https://github.com/uliwitness/UliKit/blob/master/NSAttributedString+HTMLFromRange.m)
Looks like it will do what you want.
Use the below code. it works well.
NSAttributedString *s = ...;
NSDictionary *documentAttributes = #{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType};
NSData *htmlData = [s dataFromRange:NSMakeRange(0, s.length) documentAttributes:documentAttributes error:NULL];
NSString *htmlString = [[NSString alloc] initWithData:htmlData encoding:NSUTF8StringEncoding];