string convert in array Ios , get by webservices - ios

In ios i am using Xml soap parsing This is my response
<InsertResponse xmlns="http://OrderMe.solyn.in/"><InsertResult>[{"Result":"Success","AccessToken":"f60da1f1-40d7-483d-880a-82348dc20934","AppUserId":"35"}]</InsertResult></InsertResponse>
Then i am using This code for Get Response
-(void)parser:(NSXMLParser *) parser foundCharacters:(NSString *)string {
if (elementFound) {
// NSLog(#"%#",soapResults);
[soapResults appendString: string];
if ([Type isEqualToString:#"InsertResponse"] ) {
//--- Retrieving text of an element that is found---
NSLog(#"%#",string);
NSString *str = [[NSString alloc]initWithData:string encoding:NSUTF8StringEncoding];
NSArray *allData = [str JSONValue];
//NSString *loginID=[NSString stringWithFormat:#"%#",string];
//NSLog(#"Login ID Returned from web service is : %#",loginID);
}
}
}
in this code ** NSLog(#"%#",string);** this string is print
[{"Result":"Success","AccessToken":"f60da1f1-40d7-483d-880a-82348dc20934","AppUserId":"35"}]
so i dont know how to convert this string in array
I am wating response
please share your valuable knowledge
Regards,
Nishant Chandwani
Thanks .

You need to parse this string as JSON:
NSString *string = #"[{\"Result\":\"Success\",\"AccessToken\":\"f60da1f1-40d7-483d-880a-82348dc20934\",\"AppUserId\":\"35\"}]";
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];

First this is xml parser.So how can we get the values from this.Let's come to below coding
In your .h part
//Step 1 : Add the Delegate classes
First of all you should add <NSXMLParserDelegate>
//Step 2 : Create necessary objects
NSXMLParser *parser;
NSMutableData *ReceviedData;
NSMutableString *currentStringValue;
NSMutableArray *arrayResult;
NSMutableArray *arrayAccessToken;
NSMutableArray *arrayAppUserId;
In your .m part
//Step 3 - Allocate your all Arrays in your viewDidLoad method
arrayAppUserId = [NSMutableArray alloc]init];
arrayResult = [NSMutableArray alloc]init];
arrayAccessToken = [NSMutableArray alloc]init];
//Step 4 - Create Connection in your viewDidLoad Like
[self createConnection:#"http://www.google.com"];//give your valid url.
-(void)createConnection:(NSString *)urlString
{
NSURL *url = [NSURL URLWithString:urlString];
//Step 5 - parser delegate methods are using NSURLConnectionDelegate class or not.
BOOL success;
if (!parser)
{
parser = [[NSXMLParser alloc] initWithContentsOfURL:url];
parser.delegate = self;
parser.shouldResolveExternalEntities = YES;
success = [parser parse];
NSLog(#"Success : %c",success);
}
}
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
NSLog(#"Current Element Name : %#",elementName);
if ([elementName isEqualToString:#"Result"])
{
NSLog(#"The Result is==%#",elementName);
}
if ([elementName isEqualToString:#"AccessToken"])
{
NSLog(#"The AccessToken is==%#",elementName);
}
if ([elementName isEqualToString:#"AppUserId"])
{
NSLog(#"The appUserId is==%#",elementName);
}
}
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
currentStringValue = [[NSMutableString alloc] initWithString:string];
NSLog(#"Current String Value : %#",currentStringValue);
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:#"Result"])
{
[arrayResult addObject:currentStringValue];
}
if ([elementName isEqualToString:#"AccessToken"])
{
[arrayAccessToken addObject:currentStringValue];
}
if ([elementName isEqualToString:#"AppUserId"])
{
[arrayAppUserId addObject:currentStringValue];
}
currentStringValue = nil;
}

Related

iOS NSXMLParser - Consistently Derive Image Source URL From XML Tag

I'm working with RSS feeds in my app, specifically with Drudge Report's. I'm quite new to this sort of stuff, along with being new to using Xcode's NSXMLParser. Each feed apparently represents an article. Each feed is represented by the <item></item> tags.
Within these tags, there's a description of info enclosed by the <description></description> tags. In the description, some articles might have an image associated with that article, as seen in the following screenshot:
The part I highlighted is the image I need to get (specifically, the URL string). I'm able to derive the description each article as an NSMutableString, but how do I derive the image's URL when I parse the XML with NSXMLParser? The following is my code so far as to how I'm getting all of this done:
#interface ViewController () <NSXMLParserDelegate, UITableViewDataSource, UITableViewDelegate> {
NSXMLParser *parser;
NSMutableArray *feeds;
NSMutableDictionary *item;
NSMutableString *title;
NSMutableString *link;
NSMutableString *description;
NSString *element;
}
.
.(other code)
.
#pragma mark - NSXMLParserDelegate
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
element = elementName;
if ([element isEqualToString:#"item"]) {
item = [[NSMutableDictionary alloc] init];
title = [[NSMutableString alloc] init];
link = [[NSMutableString alloc] init];
description = [[NSMutableString alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if ([element isEqualToString:#"title"]) {
[title appendString:string];
}
else if ([element isEqualToString:#"feedburner:origLink"]) {
[link appendString:string];
}
else if ([element isEqualToString:#"description"]) {
[description appendString:string];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if ([elementName isEqualToString:#"item"]) {
NSString *filteredTitle = [title stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSString *filteredLink = [link stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if (![filteredLink containsString:#"https://itunes.apple.com/"]) {
[item setObject:filteredTitle forKey:#"title"];
[item setObject:filteredLink forKey:#"link"];
[item setObject:description forKey:#"description"];
[feeds addObject:[item copy]];
}
}
}
- (void)parserDidEndDocument:(NSXMLParser *)parser {
[self.tableView reloadData];
}
PROGRESS
So far, I added the following in my didEndElement method:
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if ([elementName isEqualToString:#"item"]) {
NSString *filteredTitle = [title stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSString *filteredLink = [link stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if (![filteredLink containsString:#"https://itunes.apple.com/"]) {
[item setObject:filteredTitle forKey:#"title"];
[item setObject:filteredLink forKey:#"link"];
[item setObject:description forKey:#"description"];
if ([description rangeOfString:#"img style"].location != NSNotFound)
{
}
[feeds addObject:[item copy]];
}
}
}
Now that I know that the description has the img style string in it, I need to get the src="whateverImageURL". How do I use a regular expression to get the first occurrence of this image URL?
You'l have to do the following in ur
foundCharacters: method.
else if ([element isEqualToString:#"description"])
{
[description appendString:string];
if ([description rangeOfString:#"img"].location != NSNotFound)
{
NSRange firstRange = [previewImage rangeOfString:#"src="];
NSRange endRange = [[previewImage substringFromIndex:firstRange.location] rangeOfString:#" width=\""];
NSString *finalLink = [[NSString alloc] init];
finalLink = [previewImage substringWithRange:NSMakeRange(firstRange.location, endRange.location)];
NSString *match = #"src=\"";
NSString *postMatch;
NSScanner *scanner = [NSScanner scannerWithString:finalLink];
[scanner scanString:match intoString:nil];
postMatch = [finalLink substringFromIndex:scanner.scanLocation];
NSString *finalURL = [postMatch stringByAppendingString:#""];
description = finalURL;
}
}
}
Since in ur foundCharacters u are already getting the description tag
u need to search for the text in ur description array where u append
the string.
that u can do by scanning the entire string then store the required
substring in a variable...i.e ur URL link
Use firstRange variable to set the range from where ull take the string
and endrange variable to set the text till where u want the string to end (in ur case the url)
Here i m storing the URL in previewImage.
Hope it works for u good luck.....
After some research, I've managed to solve my problem. I just needed a little practice with using NSRange. The idea is, in my case, that when I have a description that has the NSString "img style" in it, I know for a fact that I need the first "src="whateverImageURL" string that I can get. I do this in the following code:
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:#"item"]) {
NSString *filteredTitle = [title stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSString *filteredLink = [link stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if (![filteredLink containsString:#"https://itunes.apple.com/"]) {
[item setObject:filteredTitle forKey:#"title"];
[item setObject:filteredLink forKey:#"link"];
[item setObject:description forKey:#"description"];
if ([description rangeOfString:#"img style"].location != NSNotFound) {
NSString *finalImageURL;
NSRange startRange = [description rangeOfString:#"src=\""];
finalImageURL = [description substringFromIndex:startRange.location];
finalImageURL = [finalImageURL substringFromIndex:startRange.length];
NSRange endRange = [finalImageURL rangeOfString:#"\""];
finalImageURL = [finalImageURL substringToIndex:endRange.location];
}
[feeds addObject:[item copy]];
}
}
}
you have to implement this protocol
- (void)parser:(NSXMLParser *)parser foundAttributeDeclarationWithName:(NSString *)attributeName forElement:(NSString *)elementName type:(nullable NSString *)type defaultValue:(nullable NSString *)defaultValue;
this allow you to get all attribute for each element found.
Let me know if this help you :)
UPDATE
Here a code that find the url of first img found in a given string
NSString *descriptionString = #"<br><tt><font size=\"3\" color=\"blue\"><b><u>LIST: 10 Worst Winter Storms in Washington History...</u></b></font></tt><br><br><br><font face=\"Arial\" size=\"1\"><i>(Top headline, 3rd story, <a href=\"http://www.nbcwashington.com/news/local/Ten-Worst-Storms-in-DC-History-365815301.html\">link</a>)</i></font><hr style=\"height: 1px; border-style: none; color: #666666; background-color: #666666;\"/><font face=\"Arial\" size=\"2\">Related stories:<div class=\"related-links\" id=\"R:H1:S3\"><a href=\"http://www.wunderground.com/US/DC/001.html#WIN\">BLIZZARD WARNING ISSUED FOR DC; BURBS UP TO 30\"...</a><br><a href=\"http://washington.cbslocal.com/2016/01/19/winter-is-finally-here-deep-freeze-and-snow-in-the-forecast/\">Mayor Requests Help From National Guard...</a><br><a href=\"http://www.accuweather.com/en/weather-news/snow-storm-travel-disruptions-aim-for-nyc-dc-boston-philadelphia-friday-saturday/54870622\">UPDATE...</a><br><a href=\"http://www.infowars.com/snowmaggedon2016-empty-store-shelves-as-panicked-shoppers-ransack-grocery-stores/\">Anxious Shoppers Ransack Grocery Stores...</a><br><a href=\"http://motherboard.vice.com/read/dark-web-users-are-worried-snowstorm-jonas-will-disrupt-their-deliveries\">Dark Web Users Fear Delivery Disruptions...</a><br><a href=\"https://www.washingtonpost.com/news/to-your-health/wp/2016/01/21/heres-why-some-people-drop-dead-while-shoveling-snow/\">Cold weather, shoveling form heart attack 'perfect storm'...</a><br></div></font><br><div class=\"feedflare\"> <a href=\"http://feeds.feedburner.com/~ff/DrudgeReportFeed?a=Mtf4NlmV8XU:vDGXzaysxPw:yIl2AUoC8zA\"><img src=\"http://feeds.feedburner.com/~ff/DrudgeReportFeed?d=yIl2AUoC8zA\" border=\"0\"></img></a> <a href=\"http://feeds.feedburner.com/~ff/DrudgeReportFeed?a=Mtf4NlmV8XU:vDGXzaysxPw:V_sGLiPBpWU\"><img src=\"http://feeds.feedburner.com/~ff/DrudgeReportFeed?i=Mtf4NlmV8XU:vDGXzaysxPw:V_sGLiPBpWU\" border=\"0\"></img></a> <a href=\"http://feeds.feedburner.com/~ff/DrudgeReportFeed?a=Mtf4NlmV8XU:vDGXzaysxPw:qj6IDK7rITs\"><img src=\"http://feeds.feedburner.com/~ff/DrudgeReportFeed?d=qj6IDK7rITs\" border=\"0\"></img></a> <a href=\"http://feeds.feedburner.com/~ff/DrudgeReportFeed?a=Mtf4NlmV8XU:vDGXzaysxPw:gIN9vFwOqvQ\"><img src=\"http://feeds.feedburner.com/~ff/DrudgeReportFeed?i=Mtf4NlmV8XU:vDGXzaysxPw:gIN9vFwOqvQ\" border=\"0\"></img></a> </div><img src=\"http://feeds.feedburner.com/~r/DrudgeReportFeed/~4/Mtf4NlmV8XU\" height=\"1\" width=\"1\" alt=\"\"/&gt";
NSString *stringWithoutWhiteSpace = [descriptionString stringByReplacingOccurrencesOfString:#" " withString:#""];
NSInteger srcLocation = [stringWithoutWhiteSpace rangeOfString:#"src="].location;
if ( srcLocation!= NSNotFound) {
NSString *firstSrcImg = [stringWithoutWhiteSpace substringFromIndex:srcLocation];
NSArray *componment = [firstSrcImg componentsSeparatedByString:#"\""];
NSString *url = componment[1];
NSLog(#"%#", url);
}
i invite you to try it and tell me if it respond to your question ...
i can give another code that return all img urls :)
SECOND UPDATE
For the example i have done here a method that you can use:
- (NSString*) getNextURLFromString:(NSString*) str withURLTag:(NSString*) urlTag{
NSString *stringWithoutWhiteSpace = [str stringByReplacingOccurrencesOfString:#" " withString:#""];
NSInteger srcLocation = [stringWithoutWhiteSpace rangeOfString:urlTag].location;
if ( srcLocation!= NSNotFound) {
NSString *firstSrcImg = [stringWithoutWhiteSpace substringFromIndex:srcLocation];
NSArray *componment = [firstSrcImg componentsSeparatedByString:#"\""];
NSString *url = componment[1];
return url;
}
return nil;
}
for the urlTag param put #"src="
and for the str param put the description tag value
UPDATE N° 3
here a method that return all images url
- (NSArray*) getAllURLFromString:(NSString*) str withURLTag:(NSString*) urlTag{
NSMutableArray *result = [NSMutableArray array];
NSString *stringWithoutWhiteSpace = [str stringByReplacingOccurrencesOfString:#" " withString:#""];
NSInteger srcLocation = [stringWithoutWhiteSpace rangeOfString:urlTag].location;
if ( srcLocation!= NSNotFound) {
NSString *firstSrcImg = [stringWithoutWhiteSpace substringFromIndex:srcLocation];
NSArray *componment = [firstSrcImg componentsSeparatedByString:#"\""];
if ([componment count]>1) {
NSString *url = componment[1];
[result addObject:url];
NSArray *nextComponent = [stringWithoutWhiteSpace componentsSeparatedByString:url];
if ([nextComponent count]>1) {
[result addObjectsFromArray:[self getAllURLFromString:nextComponent[1] withURLTag:urlTag]];
}
}
return result;
}
return result;
}
for the urlTag param put #"src="
and for the str param put the description tag value

JSON parsing in iOS and storing the results into Array

I'm fledgling in iOS, so please bare with the naive question. So I'm trying to work .net web service. I'm able to fetch the response from web service, the response is like beow
<?xml version="1.0" encoding="utf-8"?><soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><getDoctorListResponse
xmlns="http://tempuri.org/"><getDoctorListResult>
[
{
"Zone": "CENTRAL NORTH",
"DoctorName": "Dr Ang Kiam Hwee",
},
{
"Zone": "CENTRAL",
"DoctorName": "Dr Lee Eng Seng",
}
]
</getDoctorListResult>
</getDoctorListResponse>
</soap:Body>
</soap:Envelope>
With the below code I'm able to get the only json
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if ([currentElement isEqualToString:#"getDoctorListResult"]) {
NSDictionary *dc = (NSDictionary *) string;
NSLog(#"Dictionary is = \n%#", dc);
}
}
The variable dc which looks like json is equal to
[
{
"Zone": "CENTRAL NORTH",
"DoctorName": "Dr Ang Kiam Hwee",
},
{
"Zone": "CENTRAL",
"DoctorName": "Dr Lee Eng Seng",
}
]
I have checked many similar questions like Xcode how to parse Json Objects, json parsing+iphone and other similar questions but couldn't solve my problem.
How can I get the values of Zone and DoctorName and store it in Array then display it in TableView?
You need to collect the content of the <getDoctorListResult> element into an instance variable, so add the following as a private class extension
#interface YourClass ()
{
NSMutableString *_doctorListResultContent;
}
And then collect the element content using the XML parser delegate:
- (void) parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict
{
self.currentElement = elementName;
if ([self.currentElement isEqualToString:#"getDoctorListResult"]) {
_doctorListResultContent = [NSMutableString new];
}
}
- (void) parser:(NSXMLParser *)parser
foundCharacters:(NSString *)string
{
if ([self.currentElement isEqualToString:#"getDoctorListResult"]) {
[_doctorListResultContent appendString:string];
}
}
and finally parse the JSON in the did end element delegate method:
- (void)parser:(NSXMLParser *)parser
didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:#"getDoctorListResult"]) {
NSError *error = nil;
NSData *jsonData = [_doctorListResultContent dataUsingEncoding:NSUTF8StringEncoding];
id parsedJSON = [NSJSONSerialization JSONObjectWithData:jsonData
options:0
error:&error];
if (parsedJSON) {
NSAssert([parsedJSON isKindOfClass:[NSArray class]], #"Expected a JSON array");
NSArray *array = (NSArray *)parsedJSON;
for (NSDictionary *dict in array) {
NSString *zone = dict[#"Zone"];
NSString *doctorName = dict[#"DoctorName"];
// Store in array and then reload tableview (exercise to the reader)
}
} else {
NSLog(#"Failed to parse JSON: %#", [error localizedDescription]);
}
}
}
I would recommend storing "dc" as property and use it as UITableView data source.
self.dataSourceDict = dc;
To get values for given cell (in tableView:cellForRowAtIndexPath: method):
//deque cell before that
NSDictionary* cellData = [self.dataSourceDict objectAtIndex:indexPath.row];
//assuming cell is cutom class extending UITableViewCell
cell.zone = cellData[#"Zone"];
cell.doctorName = cellData[#"DoctorName"];
for (id key in dc)
{
NSString *doctorName = [key objectForKey:#"DoctorName"];
NSString *zone = [key objectForKey:#"Zone"];
}
Create one model file and store these value into array using that model file.

Parse XML response in IOS

I am creating an IOS application. In which I have to use SOAP web-service to get some details. So that I have used SUDZ-C to generate the stub. I can able to call web-service and got the response. But I can't parse the response. The below is the XML response.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<ViewAppTrackResponse xmlns="http://service.cmp.app.com">
<ViewAppTrackResponseReturn>
<ns1:monthBO xmlns:ns1="http://response.cmp.app.com">
<monthListItem>
<ns2:date xmlns:ns2="http://bean.cmp.app.com">1-2-2014, Saturday (nonworking day)</ns2:date>
<ns3:lockStatus xmlns:ns3="http://bean.cmp.app.com">N</ns3:lockStatus>
<ns4:dailyTime xsi:nil="true" xmlns:ns4="http://bean.cmp.app.com"/>
<ns5:taskListNew xsi:nil="true" xmlns:ns5="http://bean.cmp.app.com"/>
</monthListItem>
<monthListItem>
<ns6:date xmlns:ns6="http://bean.cmp.app.com">2-2-2014, Sunday (nonworking day)</ns6:date>
<ns7:lockStatus xmlns:ns7="http://bean.cmp.app.com">N</ns7:lockStatus>
<ns8:dailyTime xmlns:ns8="http://bean.cmp.app.com">04:00</ns8:dailyTime>
<ns9:taskListNew xmlns:ns9="http://bean.cmp.app.com">
<taskListItem>
<ns9:trackId>1070</ns9:trackId>
<ns9:taskId>14</ns9:taskId>
</taskListItem>
<taskListItem>
<ns9:trackId>1094</ns9:trackId>
<ns9:taskId>44</ns9:taskId>
</taskListItem>
</ns9:taskListNew>
</monthListItem>
<monthListItem>
<ns10:date xmlns:ns10="http://bean.cmp.app.com">3-2-2014, Monday</ns10:date>
<ns11:lockStatus xmlns:ns11="http://bean.cmp.app.com">N</ns11:lockStatus>
<ns12:dailyTime xmlns:ns12="http://bean.cmp.app.com">08:00</ns12:dailyTime>
<ns13:taskListNew xmlns:ns13="http://bean.cmp.app.com">
<taskListItem>
<ns13:trackId>1071</ns13:trackId>
<ns13:taskId>14</ns13:taskId>
</taskListItem>
<taskListItem>
<ns13:trackId>1073</ns13:trackId>
<ns13:taskId>44</ns13:taskId>
</taskListItem>
</ns13:taskListNew>
</monthListItem>
</ns1:monthBO>
<ns14:userId xsi:nil="true" xmlns:ns114="http://response.cmp.app.com"/>5</ns14:userId>
</ViewAppTrackResponseReturn>
</ViewAppTrackResponse>
</soapenv:Body>
</soapenv:Envelope>
Can anyone help me to parse this response. This will helpful for me.
LibXML2 is included in Cocoa.
http://www.raywenderlich.com/553/xml-tutorial-for-ios-how-to-choose-the-best-xml-parser-for-your-iphone-project
http://www.cocoawithlove.com/2008/10/using-libxml2-for-parsing-and-xpath.html
You can use NSXMLParser class to parse this.Using its delegate methods you can parse. I am posting my try to parse your xml.It is not completed.I am giving you a basic code for parsing. You have to do the remaining.
Here "xmlInput" is of type NSString with your xmlstring.
NSData* xmlData = [xmlInput dataUsingEncoding:NSUTF8StringEncoding];
NSXMLParser * xmlParser = [[NSXMLParser alloc] initWithData:[xmlData copy]];
[xmlParser setDelegate:(id)self];
[xmlParser setShouldResolveExternalEntities: YES];
[xmlParser parse];
Create an xmlparser object and input your xmlData.Set its delegates.
//this delegate calls when parsing start.Only once.
- (void)parserDidStartDocument:(NSXMLParser *)parser
{
recordResults = NO;//declared in .h
MonthFlag = NO;//declared in .h
TaskFlag = NO;//declared in .h
Arry = nil;//declared in .h
}
// This delgate calls when each tag name is found.
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *) namespaceURI qualifiedName:(NSString *)qName
attributes: (NSDictionary *)attributeDict
{
strElementName = [elementName copy];//strElementName is declared in .h
NSLog(#"%#",strElementName);
if([elementName isEqualToString:#"monthListItem"]){
MonthFlag = YES;
}
if([elementName isEqualToString:#"taskListItem"]){
TaskFlag = YES;
}
strElementValue = #""; //strElementValue is declared in .h
}
//This is called when each tag value is found.
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
strElementValue = [NSString stringWithFormat:#"%#%#", strElementValue,[string copy]];
NSLog(#"%#",strElementValue);
//NSLog(#"%# : %#",strElmentName,strElementValue);
recordResults=(strElementValue.length > 0);
}
// This deleagte will call in the end of each tag name.
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI: (NSString *)namespaceURI qualifiedName:(NSString *)qName
{
NSLog(#"%# - %#",elementName,strElementValue);
if (recordResults) {
if (MonthFlag) {
if(dicTemp==nil){
dicTemp = [[NSMutableDictionary alloc] init];
for (int i=0; i<10; i++) {
[dicTemp setObject:#"" forKey:strElementName];
}
}
[dicTemp setObject:strElementValue forKey:elementName ];
}
}
if(([elementName isEqualToString:#"monthListItem"] ) && dicTemp!=nil) {
if(Arry==nil)Arry = [[NSMutableArray alloc] init];
[Arry addObject:[dicTemp copy]];
dicTemp = nil;
[dicTemp release];
MonthFlag = NO;
NSLog(#"arry test %#",[Arry description]);
}
}
// This delegate will call when parsing finishes . only once
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
recordResults = NO;
}

How to grab an XML element and store it? Objective C

I am trying to grab a token from a website. Upon successful authentication, an XML document would be displayed.
I created a connection as shown below:
NSString *strURLQueryString = [NSString stringWithFormat:#"%#?username=%#&password=%#", kURL_LOGIN, nameString, passwordString];
NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:strURLQueryString]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
In order to display the output, I used this:
unsigned char byteBuffer[[receivedData length]];
[receivedData getBytes:byteBuffer];
NSLog(#"Output: %s", (char *)byteBuffer);
So some of the output of the returned document is as shown below:
<status>0</status><reason>User fetched.</reason><token>9cb7396dccabe68c067521db219afb83</token>
I have read many XML parsing implementation but I just could not implement it as it does not fulfil my need, and I just could not understand the complexity of its explanation.
Would appreciate if anyone could give me a good advice on how to go about.
- (XMLParserViewController *) initXMLParser {
appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
return self;
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict
{
if([elementName isEqualToString:#"Books"]) {
appDelegate.books = [[NSMutableArray alloc] init];
}
else if([elementName isEqualToString:#"Book"])
{
aBook = [[Books alloc] init];
}
NSLog(#"Processing Element: %#", elementName);
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if(!currentElementValue)
currentElementValue = [[NSMutableString alloc] initWithString:string];
else
[currentElementValue appendString:string];
NSLog(#"Processing Value: %#", currentElementValue);
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if([elementName isEqualToString:#"Books"])
return;
if([elementName isEqualToString:#"Book"])
{
[appDelegate.books addObject:aBook];
aBook = nil;
}
else if([elementName isEqualToString:#"name"])
{
aBook.name=currentElementValue;
}
else if([elementName isEqualToString:#"address"])
{
aBook.address=currentElementValue;
}
else if([elementName isEqualToString:#"country"])
{
aBook.country=currentElementValue;
}
currentElementValue = nil;
NSLog(#"%#",aBook.name);
NSLog(#"%#",aBook.address);
NSLog(#"%#",aBook.country);
}
Try this ,, I hope this works....
The relevant NSXMLParserDelegate methods:
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName //etc
{ _inToken = [elementName isEqualToString:#"token"]; }
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName //etc
{ _inToken = NO; }
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if (_inToken) {
_token = string;
[parser abortParsing];
}
}
You should use XML parser.
It is easy to use, go all below steps to get best result:
Create XMLParser class subclasses from NSXMLParser, so you have a NSXMLParser.h and NSXMLParser.m class
your .h class must be like this:
#import <Foundation/Foundation.h>
#interface XMLParser : NSXMLParser <NSXMLParserDelegate>{
NSUInteger parsedCounter;
BOOL accumulatingParsedCharacterData;
BOOL didAbortParsing;
}
#property (nonatomic, strong) NSMutableString *currentParsedCharacterData;
#property (nonatomic, strong) NSMutableArray *currentParsedCharacterArray;
#end
And .m class :
#import "XMLParser.h"
#implementation XMLParser
#pragma mark Parser constants
// Limit the number of parsed data to 100.
static const NSUInteger kMaximumNumberOfFilesToParse = 100;
static NSUInteger const kSizeOfFileBatch = 10;
// Reduce potential parsing errors by using string constants declared in a single place.
static NSString * const kEntryElementName = #"dlResult";
static NSString * const kStringElementName = #"string";
#pragma mark NSXMLParser delegate methods
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
// NSLog(#"didStart");
// If the number of parsed earthquakes is greater than kMaximumNumberOfEarthquakesToParse, abort the parse.
if (parsedCounter >= kMaximumNumberOfFilesToParse) {
// Use the flag didAbortParsing to distinguish between this deliberate stop and other parser errors.
didAbortParsing = YES;
[self abortParsing];
}
if ([elementName isEqualToString:kEntryElementName]) {
_currentParsedCharacterArray = [[NSMutableArray alloc]init];
} else if ([elementName isEqualToString:kStringElementName]) {
accumulatingParsedCharacterData = YES;
_currentParsedCharacterData = [[NSMutableString alloc]init];
}
}
// return string between tags
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
// NSLog(#"foundCh");
if (accumulatingParsedCharacterData) {
// If the current element is one whose content we care about, append 'string'
// to the property that holds the content of the current element.
[_currentParsedCharacterData appendString:string];
NSLog(#"currentParsedCharacterData:%#",_currentParsedCharacterData);
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
// NSLog(#"didEnd");
if ([elementName isEqualToString:kStringElementName]) {
[_currentParsedCharacterArray addObject:_currentParsedCharacterData];
}
accumulatingParsedCharacterData = NO;
}
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
if (didAbortParsing == NO) {
// Pass the error to the main thread for handling.
[self performSelectorOnMainThread:#selector(handleError:) withObject:parseError waitUntilDone:NO];
}
}
#end
In .m class there are two const string:
static NSString * const kEntryElementName = #"dlResult";
static NSString * const kStringElementName = #"string";
those are string tags,the tags that you should implement are "status", "reason" "token"
from connection class, send data connection to XMLParser class like below:
#autoreleasepool {
// It's also possible to have NSXMLParser download the data, by passing it a URL, but this is not desirable
// because it gives less control over the network, particularly in responding to connection errors.
//
XMLParser *parser = [[XMLParser alloc] initWithData:data];
parser.currentParsedCharacterArray = [NSMutableArray array];
parser.currentParsedCharacterData = [NSMutableString string];
[parser setDelegate:parser];
[parser parse];
// depending on the total number of earthquakes parsed, the last batch might not have been a "full" batch, and thus
// not been part of the regular batch transfer. So, we check the count of the array and, if necessary, send it to the main thread.
if ([parser.currentParsedCharacterArray count] > 0) {
// send parsed data to another class or ...
// parser.currentParsedCharacterArray is parsed data
}
parser.currentParsedCharacterArray = nil;
parser.currentParsedCharacterData = nil;
}
if you have any question, ask me!

How to implement this method in my NSXMLParser to extract images

i'm new in iOS development, and at this moment i have implemented the NSXMLparser , but i really don't know how to separate tags with the same name, but different content, like the <description>. In some feeds, this tag has only the summary and in other, contains the " img src ", which i want to extract too. (with or without CDATA)
Example of description tags wich i need to grab the images and then pass to my UIImageView:
<description><![CDATA[ <p>Roger Craig Smith and Troy Baker to play Batman and the Joker respectively in upcoming action game; Deathstroke confirmed as playable character. </p><p><img src="http://image.com.com/gamespot/images/2013/139/ArkhamOrigins_29971_thumb.jpg"
<description><img src="http://cdn.gsmarena.com/vv/newsimg/13/05/samsung-galaxy-s4-active-photos/thumb.jpg" width="70" height="92" hspace="3" alt="" border="0" align=left style="background:#333333;padding:0px;margin:0px 4px 0px 0px;border-style:solid;border-color:#aaaaaa;border-width:1px" /> <p>
I think that #Rob example solves my case but i don't know how to include in my NSXMLParser, described below, to separate data and images. I'm able to grab only the data (summary) on this parser.
My NSXMLParser:
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
{
element = [elementName copy];
if ([elementName isEqualToString:#"item"])
{
elements = [[NSMutableDictionary alloc] init];
title = [[NSMutableString alloc] init];
date = [[NSMutableString alloc] init];
summary = [[NSMutableString alloc] init];
link = [[NSMutableString alloc] init];
img = [[NSMutableString alloc] init];
imageLink = [[NSMutableString alloc]init];
}
if([elementName isEqualToString:#"media:thumbnail"]) {
NSLog(#"thumbnails media:thumbnail: %#", attributeDict);
imageLink = [attributeDict objectForKey:#"url"];
}
if([elementName isEqualToString:#"media:content"]) {
NSLog(#"thumbnails media:content: %#", attributeDict);
imageLink = [attributeDict objectForKey:#"url"];
}
if([elementName isEqualToString:#"enclosure"]) {
NSLog(#"thumbnails Enclosure %#", attributeDict);
imageLink = [attributeDict objectForKey:#"url"];
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if ([element isEqualToString:#"title"])
{
[title appendString:string];
}
else if ([element isEqualToString:#"pubDate"])
{
[date appendString:string];
}
else if ([element isEqualToString:#"description"])
{
[summary appendString:string];
}
else if ([element isEqualToString:#"media:description"])
{
[summary appendString:string];
}
else if ([element isEqualToString:#"link"])
{
[link appendString:string];
}
else if ([element isEqualToString:#"url"]) {
[imageLink appendString:string];
}
else if ([element isEqualToString:#"src"]) {
[imageLink appendString:string];
}
else if ([element isEqualToString:#"content:encoded"]){
NSString *imgString = [self getImage:string];
if (imgString != nil) {
[img appendString:imgString];
NSLog(#"Content of img:%#", img);
}
}
-(NSString *) getImage:(NSString *)htmlString {
NSString *url = nil;
NSScanner *theScanner = [NSScanner scannerWithString:htmlString];
[theScanner scanUpToString:#"<img" intoString:nil];
if (![theScanner isAtEnd]) {
[theScanner scanUpToString:#"src" intoString:nil];
NSCharacterSet *charset = [NSCharacterSet characterSetWithCharactersInString:#"\"'"];
[theScanner scanUpToCharactersFromSet:charset intoString:nil];
[theScanner scanCharactersFromSet:charset intoString:nil];
[theScanner scanUpToCharactersFromSet:charset intoString:&url];
}
return url;
}
#end
In your example you just have two description elements, each which has the img tag embedded within it. You just parse the description like normal, and then pull out the img tags (using regular expressions, using my retrieveImageSourceTagsViaRegex below, or a scanner).
Note, you do not have to handle the CDATA and non-CDATA renditions differently if you don't want. While NSXMLParserDelegate provides a foundCDATA routine, I'd actually be inclined to not implement that. In the absence of a foundCDATA, the standard foundCharacters routine of NSXMLParser will gracefully handle both renditions of your description tag (with and without CDATA) seamlessly.
Consider the following hypothetical XML:
<xml>
<descriptions>
<description><![CDATA[ <p>Roger Craig Smith and Troy Baker to play Batman and the Joker respectively in upcoming action game; Deathstroke confirmed as playable character. </p><p><img src="http://image.com.com/gamespot/images/2013/139/ArkhamOrigins_29971_thumb.jpg">]]></description>
<description><img src="http://cdn.gsmarena.com/vv/newsimg/13/05/samsung-galaxy-s4-active-photos/thumb.jpg" width="70" height="92" hspace="3" alt="" border="0" align=left style="background:#333333;padding:0px;margin:0px 4px 0px 0px;border-style:solid;border-color:#aaaaaa;border-width:1px" /> <p></description>
</descriptions>
</xml>
The following parser will parse both of those description entries, grabbing the image URLs out of them. And as you'll see, there is no special handling for CDATA needed:
#interface ViewController () <NSXMLParserDelegate>
#property (nonatomic, strong) NSMutableString *description;
#property (nonatomic, strong) NSMutableArray *results;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSURL *filename = [[NSBundle mainBundle] URLForResource:#"test" withExtension:#"xml"];
NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:filename];
parser.delegate = self;
[parser parse];
// full array of dictionary entries
NSLog(#"results = %#", self.results);
}
- (NSMutableArray *)retrieveImageSourceTagsViaRegex:(NSString *)string
{
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"(<img\\s[\\s\\S]*?src\\s*?=\\s*?['\"](.*?)['\"][\\s\\S]*?>)+?"
options:NSRegularExpressionCaseInsensitive
error:&error];
NSMutableArray *results = [NSMutableArray array];
[regex enumerateMatchesInString:string
options:0
range:NSMakeRange(0, [string length])
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
[results addObject:[string substringWithRange:[result rangeAtIndex:2]]];
}];
return results;
}
#pragma mark - NSXMLParserDelegate
- (void)parserDidStartDocument:(NSXMLParser *)parser
{
self.results = [NSMutableArray array];
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqualToString:#"description"])
self.description = [NSMutableString string];
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if (self.description)
[self.description appendString:string];
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:#"description"])
{
NSArray *imgTags = [self retrieveImageSourceTagsViaRegex:self.description];
NSDictionary *result = #{#"description": self.description, #"imgs" : imgTags};
[self.results addObject:result];
self.description = nil;
}
}
#end
That yields the following results (note, no CDATA):
results = (
{
description = " <p>Roger Craig Smith and Troy Baker to play Batman and the Joker respectively in upcoming action game; Deathstroke confirmed as playable character. </p><p><img src=\"http://image.com.com/gamespot/images/2013/139/ArkhamOrigins_29971_thumb.jpg\">";
imgs = (
"http://image.com.com/gamespot/images/2013/139/ArkhamOrigins_29971_thumb.jpg"
);
},
{
description = "<img src=\"http://cdn.gsmarena.com/vv/newsimg/13/05/samsung-galaxy-s4-active-photos/thumb.jpg\" width=\"70\" height=\"92\" hspace=\"3\" alt=\"\" border=\"0\" align=left style=\"background:#333333;padding:0px;margin:0px 4px 0px 0px;border-style:solid;border-color:#aaaaaa;border-width:1px\" /> <p>";
imgs = (
"http://cdn.gsmarena.com/vv/newsimg/13/05/samsung-galaxy-s4-active-photos/thumb.jpg"
);
}
)
So, bottom line, just parse the XML like normal, don't worry about CDATA, and just parse out the image URL using a NSScanner or NSRegularExpression as you see fit.

Resources