ios - How to parse HTML content in ios? - iphone

How do I parse HTML file?
I'm getting an HTML file in the below code,I just want to get data in between BinarySecurityToken XML node.
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
if(_data)
{
//Here am getting the below HTML content
NSString* content = [[NSString alloc] initWithData:_data
encoding:NSUTF8StringEncoding];
}
}
<input type="hidden" name="wa" value="wsignin1.0" />
<input type="hidden" name="wresult"
value="<t:RequestSecurityTokenResponse xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
<t:Lifetime>
<wsu:Created >2013-04-29T11:50:29.895Z</wsu:Created>
<wsu:Expires>2013-04-29T12:00:29.895Z</wsu:Expires>
</t:Lifetime>
<wsp:AppliesTo>
<EndpointReference>
<Address>urn:orin.converse</Address>
</EndpointReference></wsp:AppliesTo>
<t:RequestedSecurityToken>
<wsse:BinarySecurityToken>
aHR0cCUzYSUyZiUyZnNjaGVtYWd0Sjk0JTNk
</wsse:BinarySecurityToken>
Any ideas? Thanks in advance.

You can get using this code
NSRange divRange = [content rangeOfString:#"<wsse:BinarySecurityToken>" options:NSCaseInsensitiveSearch];
if (divRange.location != NSNotFound)
{
NSRange endDivRange;
endDivRange.location = divRange.length + divRange.location;
endDivRange.length = [content length] - endDivRange.location;
endDivRange = [content rangeOfString:#"</wsse:BinarySecurityToken>" options:NSCaseInsensitiveSearch range:endDivRange];
if (endDivRange.location != NSNotFound)
{
divRange.location += divRange.length;
divRange.length = endDivRange.location - divRange.location;
NSLog(#"BinarySecurityToken : %#",[content substringWithRange:divRange]);
}
}
Output :
aHR0cCUzYSUyZiUyZnNjaGVtYWd0Sjk0JTNk

You need and XML parser for that.
There's a tutorial here

For this particular case you can get the ranges of <wsse:BinarySecurityToken> and </wsse:BinarySecurityToken>, construct new range that will provide you location of the token, and get substring in that range.
Sample code:
NSRange openingTagRange = [htmlString rangeOfString:#"<wsse:BinarySecurityToken>"];
NSRange closingTagRange = [htmlString rangeOfString:#"</wsse:BinarySecurityToken>"];
NSRange tokenRange = NSMakeRange(openingTagRange.location + openingTagRange.length, closingTagRange.location - (openingTagRange.location + openingTagRange.length));
NSString *token = [htmlString substringWithRange:tokenRange];
Since your input comes from outside, you should probably check if the ranges' locations are not equal to NSNotFound.

NSString *filePath = [[NSBundle mainBundle] pathForResource:#"index" ofType:#"html"];
NSData * data = [NSData dataWithContentsOfFile:filePath];
TFHpple * tutorialsParser = [[TFHpple alloc] initWithHTMLData:data];
NSString *query = #"//div[#id='BinarySecurityToken']";
NSArray *nodes = [tutorialsParser searchWithXPathQuery:query];
for (TFHppleElement * element in nodes) {
NSLog(#"%#", element);
NSLog(#"%#", [element tagName]);
NSLog(#"%#", [element attributes]);
NSLog(#"%#", [element children]);
for (TFHppleElement *childElement in [element children]) {
NSLog(#"%#", childElement);
}
}
hope this will help you For more try this blog and Git Project Resource may help you and
Good blog by RAYWENDERLICH
or another option if you have all the HTML data in NSString you can get data between specific NSString with this function.
-(NSString*)stringBetweenString:(NSString*)start andString:(NSString)end {
NSRange startRange = [self rangeOfString:start];
if (startRange.location != NSNotFound) {
NSRange targetRange;
targetRange.location = startRange.location + startRange.length;
targetRange.length = [self length] - targetRange.location;
NSRange endRange = [self rangeOfString:end options:0 range:targetRange];
if (endRange.location != NSNotFound) {
targetRange.length = endRange.location - targetRange.location;
return [self substringWithRange:targetRange];
}
}
return nil;
}

Related

ios - How to parse HTML file?

I'm getting HTML content in below format.
wsse:BinarySecurityToken wsu:Id="uuid:07747f2a-4be4-48fa-9654-5e12235f6040" ValueType="http://schemas.xmlsoap.org/ws/2009/11/swt-token-profile-1.0" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
aHR0cCUzYSUyZiUyZnNjaGVtYXMubWNk</wsse:BinarySecurityToken><
In the below code I'm getting
wsu:Id="uuid:07747f2a-4be4-48fa-9654-5e12235f6040" ValueType="http://schemas.xmlsoap.org/ws/2009/11/swt-token-profile-1.0" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
aHR0cCUzYSUyZiUyZnNjaGVtYXMubWNk
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
if(_data)
{
NSString* content = [[NSString alloc] initWithData:_data
encoding:NSUTF8StringEncoding];
NSLog(#"Content :%#",content);
NSRange divRange = [content rangeOfString:#"wsse:BinarySecurityToken" options:NSCaseInsensitiveSearch];
if (divRange.location != NSNotFound)
{
NSRange endDivRange;
endDivRange.location = divRange.length + divRange.location;
endDivRange.length = [content length] - endDivRange.location;
endDivRange = [content rangeOfString:#"=<" options:NSCaseInsensitiveSearch range:endDivRange];
if (endDivRange.location != NSNotFound)
{
divRange.location += divRange.length;
divRange.length = endDivRange.location - divRange.location;
NSLog(#"BinarySecurityToken : %#",[content substringWithRange:divRange]);
}
}
[webView loadHTMLString:content baseURL:_url];
}
}
I want the Output as aHR0cCUzYSUyZiUyZnNjaGVtYXMubWNk.
Any ideas? Thanks in advance.
As you discussing you have NSString *token = #"<wsse:BinarySecurityToken>aHR0cCUzYSUyZiUyZnNjaGVtYWd0Sjk0JTNk</wsse:BinarySecurityToken>";
and what the token between tags then you can replace the unwanted character like .
NSString *str = [token stringByReplacingOccurrencesOfString:#"<wsse:BinarySecurityToken>"
withString:#""];;
and then
NSString *correctToken = [str stringByReplacingOccurrencesOfString:#"</wsse:BinarySecurityToken>"
withString:#""];;

How can I parse this xml using GDataXML parser?

<list>
<OrderData HASH="1408108039"></OrderData>
<OrderData HASH="208524692">
<id>97</id>
<customer>
<CustomerData HASH="2128670187"></CustomerData></customer>
<billingAddress></billingAddress><deliveryAddress></deliveryAddress>
<orderDetail>
<list>
<OrderDetailData HASH="516790072"></OrderDetailData>
<OrderDetailData HASH="11226247"></OrderDetailData>
<OrderDetailData HASH="11226247"></OrderDetailData>
</list>
</orderDetail>
<log/>
</OrderData>
<OrderData HASH="1502226778"></OrderData>
</list>
I cannot find a solution to find the number of OrderDetailData elements? I also read http://iphonebyradix.blogspot.com/2011/03/using-gdata-to-parse-xml-file.html this url.
Thanks in advance.
Edit:
I am explaining my requirement again. In this xml there will be multiple OrderData element. Now I have to count the number of OrderDetailData elemnts from a particular OrderData element. Suppose that, according to my xml, the current parsed xml has one OrderData element, named id and its value is 97. Now, I have to count how many OrderDetailData elements are contained in the OrderData(whichid` is 97).
This is a simple example how to retrieve some data. This example is very simple and not use XPath expression. I suggest you first understand how it works and then use XPath expression. In my opinion it is not useful to use XPath expression if you cannot understand how the parser works.
NSString* path = [[NSBundle mainBundle] pathForResource:#"test2" ofType:#"xml"];
NSData *xmlData = [[NSMutableData alloc] initWithContentsOfFile:path];
NSError *error;
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:xmlData
options:0 error:&error];
//NSLog(#"%#", doc.rootElement); // print the whole xml
NSArray *orderDataArray = [doc.rootElement elementsForName:#"OrderData"];
for (GDataXMLElement *orderDataElement in orderDataArray) {
if([orderDataElement childCount] > 0)
{
NSString *attributeForOrderDataElement = [(GDataXMLElement *) [orderDataElement attributeForName:#"HASH"] stringValue];
NSLog(#"attributeForOrderDataElement has value %#", attributeForOrderDataElement);
GDataXMLElement* idElement = (GDataXMLElement*)[[orderDataElement elementsForName:#"id"] objectAtIndex:0];
NSLog(#"id has value %#", idElement.stringValue);
GDataXMLElement* orderDetailElement = (GDataXMLElement*)[[orderDataElement elementsForName:#"orderDetail"] objectAtIndex:0];
GDataXMLElement* listElement = (GDataXMLElement*)[[orderDetailElement elementsForName:#"list"] objectAtIndex:0];
NSArray* orderDetailDataArray = [listElement elementsForName:#"OrderDetailData"];
int count = 0;
for (GDataXMLElement *orderDetailDataElement in orderDetailDataArray) {
NSString *attributeForOrderDetailDataElement = [(GDataXMLElement *) [orderDetailDataElement attributeForName:#"HASH"] stringValue];
NSLog(#"attributeForOrderDetailDataElement has value %#", attributeForOrderDetailDataElement);
count++;
}
NSLog(#"%d", count);
}
}
[doc release];
[xmlData release];
This is the output console:
attributeForOrderDataElement has value 208524692 <-- HASH value
id has value 97 <-- id value
attributeForOrderDetailDataElement has value 516790072 <-- HASH value
attributeForOrderDetailDataElement has value 11226247
attributeForOrderDetailDataElement has value 11226247
3 <-- the count
Hope it helps.
Edit
test2.xml contains your file but you could pass it as a string. You can also pass as parameters as string like the following:
NSString* xmlString = #"<list>"
"<OrderData HASH=\"1408108039\"></OrderData>"
"<OrderData HASH=\"208524692\">"
"<id>97</id>"
"<customer>"
"<CustomerData HASH=\"2128670187\"></CustomerData>"
"</customer>"
"<billingAddress></billingAddress>"
"<deliveryAddress></deliveryAddress>"
"<orderDetail>"
"<list>"
"<OrderDetailData HASH=\"516790072\"></OrderDetailData>"
"<OrderDetailData HASH=\"11226247\"></OrderDetailData>"
"<OrderDetailData HASH=\"11226247\"></OrderDetailData>"
"</list>"
"</orderDetail>"
"<log/>"
"</OrderData>"
"<OrderData HASH=\"1502226778\"></OrderData>"
"</list>";
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithXMLString:xmlString options:0 error:&error];
I found TouchXML easy in parsing and you can directly access data needed from xml
First of all Download TouchXML and add libxml2.dylib framework to your project.
change buildsetting for "Header Search Path" and add "/usr/include/libxml2"
Import TouchXML.h to your file
//Access document
CXMLDocument *parserDoc = [[CXMLDocument alloc] initWithContentsOfURL:url options:0 error:&err];
//Access root element and access children in heirarchy
CXMLElement *root = [parserDoc rootElement];
NSArray *places = [[[root children] objectAtIndex:0] children];
Else
//Access node by node
NSString *location =[[[[[parserDoc nodesForXPath:#"/xml_api_reply/weather/forecast_information/city" error:nil] objectAtIndex:0] attributeForName:#"data"] stringValue] retain];
If the OrderDetailData is present in 2nd object of array all the time, u can use the below
NSArray* arr = [[XMLelement elementForName:#"list"] elementsForName:#"OrderData"];
NSXMLElement* listElement = [[[arr objectAtIndex:1] elementForName:#"orderDetail"] elementForName:#"list"];
NSArray* orderDetailArray* = [listElement elementsForName:#"OrderDetailData"];
In this u can get the OrderDetailData elements in the array, and u can parse the data in loop. to get HASH value use.
NSString* hash = [[orderDetailArray objectAtIndex:0] stringValueForAttribute:#"HASH"];
This is the below code, i have tried. I got the right output.. check out
NSString* xmlString = #"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
"<list>"
"<OrderData HASH=\"1408108039\"></OrderData>"
"<OrderData HASH=\"208524692\">"
"<id>97</id>"
"<customer>"
"<CustomerData HASH=\"2128670187\"></CustomerData></customer>"
"<billingAddress></billingAddress><deliveryAddress></deliveryAddress>"
"<orderDetail>"
"<list>"
"<OrderDetailData HASH=\"516790072\"></OrderDetailData>"
"<OrderDetailData HASH=\"11226247\"></OrderDetailData>"
"<OrderDetailData HASH=\"11226247\"></OrderDetailData>"
"</list>"
"</orderDetail>"
"<log/></OrderData>"
"<OrderData HASH=\"1502226778\"></OrderData>"
"</list>";
NSXMLDocument* doc = [[NSXMLDocument alloc] initWithData:[xmlString dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];
NSXMLElement* rootElement = [doc rootElement];
NSArray* arr = [rootElement elementsForName:#"OrderData"];
NSXMLElement* orderDataElement;
for (int i = 0; i < [arr count]; i++)
{
int Id = 0;
Id = [[arr objectAtIndex:i] integerValueForNode:#"id"];
if (Id != 0)
{
orderDataElement = [arr objectAtIndex:i];
break;
}
}
NSArray* orderDetailArray = [[[orderDataElement elementForName:#"orderDetail"]
elementForName:#"list"]
elementsForName:#"OrderDetailData"];
for (int j = 0; j < [orderDetailArray count]; j++)
{
NSLog(#"%#", [[orderDetailArray objectAtIndex:j] stringValueForAttribute:#"HASH"]);
}

Retrieving a filename for an ALAsset

How can the filename be extracted from an ALAsset?
Is there a way to get this via the url or some other way?
From iOS 5.0 you can get the file from ALAssetRepresentation Class.
ALAssetRepresentation *rep = [anAssetItem defaultRepresentation];
NSString *fileName = [rep filename];
Update: As yeonsh notes below, from iOS 5.0 there is a better way. This answer is relevant for iOS < 5.0.
You can extract an URL from the ALAsset, but all the filenames are the same, on the form
assets-library://asset/asset.JPG?id=1000000001&ext=JPG
If you for some reason need different file names, try making an internal-external paradigm:
#import <Foundation/Foundation.h>
#interface NSURL (NSURL_Asset)
- (NSURL*) toExternalForm;
- (NSURL*) fromExternalForm;
- (NSString*) toExternalFilename;
#end
#import "NSURL+Asset.h"
#import "URLParser.h" // from http://iphone.demay-fr.net/2010/04/parsing-url-parameters-in-a-nsstring/
static NSString *const EXTERNAL_TOKEN = #"/assetExternalForm/";
#implementation NSURL (NSURL_Asset)
// assets-library://asset/asset.JPG/assetExternalForm/1000000001.JPG -> assets-library://asset/asset.JPG?id=1000000001&ext=JPG
- (NSURL*) fromExternalForm {
if([self.scheme isEqualToString:#"assets-library"]) {
NSRange slash = [self.absoluteString rangeOfString:EXTERNAL_TOKEN options:NSBackwardsSearch];
if(slash.location != NSNotFound) {
NSRange dot = [self.absoluteString rangeOfString:#"." options:NSBackwardsSearch];
if(dot.location != NSNotFound) {
NSString* extention = [self.absoluteString substringFromIndex:(dot.location + dot.length)];
NSString* identifier = [self.absoluteString substringWithRange:NSMakeRange(slash.location + slash.length, dot.location - (slash.location + slash.length))];
return [NSURL URLWithString:[NSString stringWithFormat:#"%#?id=%#&ext=%#", [self.absoluteString substringToIndex:slash.location], identifier, extention]];
}
}
}
return self;
}
// assets-library://asset/asset.JPG?id=1000000001&ext=JPG -> assets-library://asset/asset.JPG/assetExternalForm/1000000001.JPG
- (NSURL*) toExternalForm {
if([self.scheme isEqualToString:#"assets-library"]) {
NSRange range = [self.absoluteString rangeOfString:#"?"];
if(range.location != NSNotFound) {
URLParser *parser = [[[URLParser alloc] initWithURLString:self.absoluteString] autorelease];
NSString* extention = [parser valueForVariable:#"ext"];
NSString* identifier = [parser valueForVariable:#"id"];
if(extention != NULL && identifier != NULL) {
return [NSURL URLWithString:[NSString stringWithFormat:#"%#%#%#.%#", [self.absoluteString substringToIndex:range.location], EXTERNAL_TOKEN, identifier, extention]];
}
}
}
return self;
}
// assets-library://asset/asset.JPG?id=1000000001&ext=JPG -> 1000000001.JPG
- (NSString*) toExternalFilename {
if([self.scheme isEqualToString:#"assets-library"]) {
NSRange range = [self.absoluteString rangeOfString:#"?"];
if(range.location != NSNotFound) {
URLParser *parser = [[[URLParser alloc] initWithURLString:self.absoluteString] autorelease];
NSString* extention = [parser valueForVariable:#"ext"];
NSString* identifier = [parser valueForVariable:#"id"];
if(extention != NULL && identifier != NULL) {
return [NSString stringWithFormat:#"%#.%#", identifier, extention];
}
}
}
return NULL;
}
#end
Note that you do not need a filename to read the content of an ALAsset. Use the ALAsset.defaultRepresentation.getBytes method for that.

Sorting an NSArray like the MPMediaPickerController/iPod Library

I'm developing a custom UIViewController for iPhone that emulates a subset of the MPMediaPickerController for files in my application's local documents directory. In particular, I'm attempting to re-create the Songs tab. I've been successful in creating my new controller, except I can't get the song titles to sort like they do in the iPod Library or the MPMediaPickerController. Here's an example of how the song names need to be sorted:
Awesome Song Title
Cool Song
The Darkest Song Ever
My Song Title
A Really Cool Song
Why Me?
4 Hours Wasted
As you can see, the sorting excludes the leading articles in the song titles and also places songs that begin with a numeric value at the end of the list. Can anyone suggest an efficient sorting function that takes these tules into account?
Since it looks like no one could offer up a solution, I thought I would post the solution I came up with. First, I created a model for my data:
#interface MyModel : NSObject
{
NSString* _value;
NSString* _sortableValue;
}
#property (nonatomic,copy) NSString* value;
- (NSString*)sortableValue;
- (NSString*)comparableString:(NSString*)str;
#end
They key to the model is the comparableString method, which gets used to create the sortableValue. Here's the implementation of the model:
#implementation MyModel
#synthesize value=_value;
-(void)dealloc
{
[_value release];
[_sortableValue release];
[super dealloc];
}
- (void)setValue:(NSString*)value
{
[_value release];
_value = [value copy];
[_sortableValue release];
_sortableTValue = nil;
}
- (NSString*)sortableValue
{
if (_sortableValue == nil)
_sortableValue = [[self comparableString:_value] retain];
return _sortableValue;
}
- (NSString*)comparableString:(NSString*)str
{
if (str == nil)
return nil;
else if ([str length] == 0)
return [NSString stringWithString:str];
NSCharacterSet* numbersSet = [NSCharacterSet decimalDigitCharacterSet];
if ([str rangeOfCharacterFromSet:numbersSet options:0 range:NSMakeRange(0, 1)].location != NSNotFound)
return [NSString stringWithString:str];
NSRange range = NSMakeRange(0, [str length]);
if ([str compare:#"a " options:(NSAnchoredSearch|NSCaseInsensitiveSearch) range:NSMakeRange(0, 2)] == NSOrderedSame)
range.location = 2;
else if ([str compare:#"an " options:(NSAnchoredSearch|NSCaseInsensitiveSearch) range:NSMakeRange(0, 3)] == NSOrderedSame)
range.location = 3;
else if ([str compare:#"the " options:(NSAnchoredSearch|NSCaseInsensitiveSearch) range:NSMakeRange(0, 4)] == NSOrderedSame)
range.location = 4;
range.length -= range.location;
NSCharacterSet* lettersSet = [NSCharacterSet letterCharacterSet];
NSUInteger letterOffset = [str rangeOfCharacterFromSet:lettersSet options:0 range:range].location;
if (letterOffset == NSNotFound)
return [NSString stringWithString:str];
letterOffset -= range.location;
range.location += letterOffset;
range.length -= letterOffset;
return [str substringWithRange:range];
}
#end
In addition to the removing the leading articles from the string, it also removes any leading non-letter characters. I have a song in my iPod library entitled "$ell Your $oul", which ends up in the E section in the MPMediaPickerController. I'm not sure that's what I would have done had I crated the initial sorting algorithm, but I was going to consistency with the MPMediaPickerController, so there you go.
The final piece of the puzzle is the UILocalizedIndexedCollation class. This handy little helper class will help you sort your data to make supplying it to a UITableView via a UITableViewDataSource a piece of cake. Here's a snippet on how to use the UILocalizedIndexedCollation class in conjunction with the model:
// tableData will contain an NSArray for each populated section in the table view
NSMutableDictionary* tableData = [NSMutableDictionary dictionary];
NSMutableArray* myArray = [NSMutableArray array];
// Populate myArray with instances of MyModel
UILocalizedIndexedCollation* indexer = [UILocalizedIndexedCollation currentCollation];
for (MyModel* data in myArray)
{
NSInteger index = [indexer sectionForObject:data collationStringSelector:#selector(sortableValue)];
NSNumber* key = [[NSNumber alloc] initWithInteger:index];
NSMutableArray* array = [tableData objectForKey:key];
if (array == nil)
{
array = [NSMutableArray new]; // Will be released after creating a sorted array in the following section
[tableData setObject:array forKey:key];
}
[array addObject:data];
[key release];
}
[tableData enumerateKeysAndObjectsUsingBlock:^(id key, id array, BOOL* stop)
{
NSMutableArray* sortedArray = [[indexer sortedArrayFromArray:array collationStringSelector:#selector(sortableValue)] mutableCopy];
[tableData setObject:sortedArray forKey:key];
[array release];
}];
One quick note about UILocalizedIndexedCollation (from Apple's documentation):
If the application provides a
Localizable.strings file for the
current language preference, the
indexed-collation object localizes
each string returned by the method
identified by selector.
So make sure you provide a Localizable.strings for each language you want to support, or your table view will only have sections A-Z and #.
It took me a while to work out all of the details on this, so I hope it becomes useful for other people. If you see any ways I can improve this, please let me know!
You may need to consider certain characters with accents as well such as è, é, ò, à, ù, ì.
So I slightly modified your code to incorporate this. Your code is a great contribution to all of us iphone developers
- (NSString*)comparableString:(NSString*)str
{
if (str == nil)
return nil;
else if ([str length] == 0)
return [NSString stringWithString:str];
NSCharacterSet* numbersSet = [NSCharacterSet decimalDigitCharacterSet];
if ([str rangeOfCharacterFromSet:numbersSet options:0 range:NSMakeRange(0, 1)].location != NSNotFound)
return [NSString stringWithString:str];
NSRange range = NSMakeRange(0, [str length]);
if ([str compare:#"a " options:(NSAnchoredSearch|NSCaseInsensitiveSearch) range:NSMakeRange(0, 2)] == NSOrderedSame)
range.location = 2;
else if ([str compare:#"an " options:(NSAnchoredSearch|NSCaseInsensitiveSearch) range:NSMakeRange(0, 3)] == NSOrderedSame)
range.location = 3;
else if ([str compare:#"the " options:(NSAnchoredSearch|NSCaseInsensitiveSearch) range:NSMakeRange(0, 4)] == NSOrderedSame)
range.location = 4;
range.length -= range.location;
NSCharacterSet* lettersSet = [NSCharacterSet letterCharacterSet];
NSUInteger letterOffset = [str rangeOfCharacterFromSet:lettersSet options:0 range:range].location;
if (letterOffset == NSNotFound)
return [NSString stringWithString:str];
letterOffset -= range.location;
range.location += letterOffset;
range.length -= letterOffset;
//my modification starts here.........
NSString * finalString = [str substringWithRange:range];
NSString * firstCharString = [finalString substringToIndex:1];
NSData * encodedData = [firstCharString dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString * encodedString = [[NSString alloc] initWithBytes:[encodedData bytes] length:[encodedData length] encoding:NSASCIIStringEncoding];
if ([encodedString isEqualToString:#"?"]) {
return finalString;
}
NSString * finalProcessedString = [finalString stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:encodedString];
[encodedString release];
return finalProcessedString;
}

iPhone parsing url for GET params

I have an string which is got from parsing an xml site.
http://www.arijasoft.com/givemesomthing.php?a=3434&b=435edsf&c=500
I want to have an NSString function that will be able to parse the value of c.
Is there a default function or do i have to write it manually.
You could use Regular expression via RegExKit Lite:
http://regexkit.sourceforge.net/RegexKitLite/
Or you could separate the string into components (which is less nice):
NSString *url=#"http://www.arijasoft.com/givemesomthing.php?a=3434&b=435edsf&c=500";
NSArray *comp1 = [url componentsSeparatedByString:#"?"];
NSString *query = [comp1 lastObject];
NSArray *queryElements = [query componentsSeparatedByString:#"&"];
for (NSString *element in queryElements) {
NSArray *keyVal = [element componentsSeparatedByString:#"="];
if (keyVal.count > 0) {
NSString *variableKey = [keyVal objectAtIndex:0];
NSString *value = (keyVal.count == 2) ? [keyVal lastObject] : nil;
}
}
I made a class that does this parsing for you using an NSScanner, as an answer to the same question a few days ago. You might find it useful.
You can easily use it like:
URLParser *parser = [[[URLParser alloc] initWithURLString:#"http://www.arijasoft.com/givemesomthing.php?a=3434&b=435edsf&c=500"] autorelease];
NSString *c = [parser valueForVariable:#"c"]; //c=500
Try the following:
NSURL *url = [NSURL URLWithString:#"http://www.arijasoft.com/givemesomthing.php?a=3434&b=435edsf&c=500"];
NSMutableString *parameterString = [NSMutableString stringWithFormat:#"{%#;}",[url parameterString]];
[parameterString replaceOccurrencesOfString:#"&" withString:#";"];
// Convert string into Dictionary
NSPropertyListFormat format;
NSString *error;
NSDictionary *paramDict = [NSPropertyListSerialization propertyListFromData:[parameterString dataUsingEncoding:NSUTF8StringEncoding] mutabilityOption: NSPropertyListImmutable format:&format errorDescription:&error];
// Now take the parameter you want
NSString *value = [paramDict valueForKey:#"c"];
Here is the native iOS approach using NSURLComponents and NSURLQueryItem classes:
NSString *theURLString = #"http://www.arijasoft.com/givemesomthing.php?a=3434&b=435edsf&c=500";
NSArray<NSURLQueryItem *> *theQueryItemsArray = [NSURLComponents componentsWithString:theURLString].queryItems;
for (NSURLQueryItem *theQueryItem in theQueryItemsArray)
{
NSLog(#"%# %#", theQueryItem.name, theQueryItem.value);
}