I am using NSXmlParser to get data from XML. In the parser delegate method I have:
- (void)resetPassCallback: (NSData*) data{
NSLog(#"start parsing the data");
NSXMLParser *nsXmlParser = [[NSXMLParser alloc] initWithData:data];
[nsXmlParser setDelegate:self];
BOOL success = [nsXmlParser parse];
if (success) {
NSLog(#"No errors %#", xmlArray);
} else {
NSLog(#"Error parsing document!");
}
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *) namespaceURI qualifiedName:(NSString *)qualifiedName attributes: (NSDictionary *)attributeDict
{
element = elementName;
if([elementName isEqualToString:#"User"])
{
XmlDict = [[NSMutableDictionary alloc]init];
userId =[[NSMutableString alloc]init];
screenName =[[NSMutableString alloc]init];
xmlArray = [[NSMutableArray alloc]init];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
NSLog(#"foundCharacters ::::: %# :::: ", string);
[xmlArray addObject:string];
}
Although I am able to parse the data, I am not getting the complete data. In the console, the log shows:
foundCharacters ::::: 200 ::::
foundCharacters ::::: f1f47453-04d7-20c8-a9e1-406fdc89a2da ::::
foundCharacters ::::: test ::::
foundCharacters ::::: 62e2092a-eb6e-44ad-7a7b-3deb976569c1 ::::
foundCharacters ::::: Thomas ::::
xmlArray contents : (
"62e2092a-eb6e-44ad-7a7b-3deb976569c1",
Thomas
)
As you can see, why am I not getting the “test” and other values in the xmlArray.
why use for mutableArray. simply try this
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if(!currentElementValue)
currentElementValue = [[NSMutableString alloc] initWithString:string];
else
[currentElementValue appendString:string];
NSLog(#"Processing Value: %#", currentElementValue);
}
I hope that, the Array is getting re-initialed at every time of NSXMLParser delegates called .
You need to initialise the Array, before the NSXMLParser delegates
called.
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *) namespaceURI qualifiedName:(NSString *)qualifiedName attributes: (NSDictionary *)attributeDict
{
//Don't initialise your NSArray here
}
}
-(void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
NSLog(#"foundCharacters ::::: %# :::: ", string);
[xmlArray addObject:string];
}
Use xmlArray = [[NSMutableArray alloc]init]; in
- (void)resetPassCallback: (NSData*) data{
NSLog(#"start parsing the data");
xmlArray = [[NSMutableArray alloc]init];
NSXMLParser *nsXmlParser = [[NSXMLParser alloc] initWithData:data];
[nsXmlParser setDelegate:self];
BOOL success = [nsXmlParser parse];
if (success) {
NSLog(#"No errors %#", xmlArray);
} else {
NSLog(#"Error parsing document!");
}
}
not in
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *) namespaceURI qualifiedName:(NSString *)qualifiedName attributes: (NSDictionary *)attributeDict
{
}
Related
I am new to iOS development. I want to parse my xml web-service array. My xml response is like,
<BookList>
<Book>
<BookID>int</BookID>
<BookName>string</BookName>
<Pages>string</Pages>
<Price>string</Price>
</Book>
<Book>
<BookID>int</BookID>
<BookName>string</BookName>
<Pages>string</Pages>
<Price>string</Price>
</Book>
</BookList>
Here is the code i am using to parse the response,
-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSString *theXML = [[NSString alloc] initWithBytes:
[self.webResponseData mutableBytes] length:[self.webResponseData length] encoding:NSUTF8StringEncoding];
//now parsing the xml
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithData: self.webResponseData];
xmlParser.delegate = self;
// Run the parser
#try{
BOOL parsingResult = [xmlParser parse];
}
#catch (NSException* exception)
{
UIAlertView* alert = [[UIAlertView alloc]initWithTitle:#"Server Error" message:[exception reason] delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
return;
}
}
//Implement the NSXmlParserDelegate methods
-(void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:
(NSString *)qName attributes:(NSDictionary *)attributeDict
{
currentElement = elementName;
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
// NSLog(#"String : %#", string);
if ([currentElement isEqualToString:#"BookID"]) {
NSLog(#"BookID : %#", string);
}else if ([currentElement isEqualToString:#"BookName"]) {
NSLog(#"BookName : %#", string);
}else if ([currentElement isEqualToString:#"Pages"]) {
NSLog(#"Pages : %#", string);
}else if ([currentElement isEqualToString:#"Price"]) {
NSLog(#"Price : %#", string);
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
// NSLog(#"Current Element: %# ",currentElement);
}
Using this code I can view the results, But i can get the number of books.
You can add this in to .h file
NSMutableDictionary *dictBook;
NSMutableArray *arrBook;
NSMutableString *elementValue;
Now use the below code to get the total book counts.
//Implement the NSXmlParserDelegate methods
-(void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:
(NSString *)qName attributes:(NSDictionary *)attributeDict
{
currentElement = elementName;
if ([currentElement isEqualToString:#"BookList"]) {
arrBook = [[NSMutableArray alloc] init];
}
else if ([currentElement isEqualToString:#"Book"]) {
dictBook = [[NSMutableDictionary alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if(!elementValue)
elementValue = [[NSMutableString alloc] initWithString:string];
else
elementValue = string; //[elementValue appendString:string];
NSLog(#"elementValue : %#",elementValue);
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
// NSLog(#"Current Element: %# ",currentElement);
if ([elementName isEqualToString:#"BookID"] ||
[elementName isEqualToString:#"BookName"] ||
[elementName isEqualToString:#"Pages"] ||
[elementName isEqualToString:#"Price"])
{
[dictBook setObject:elementValue forKey:elementName];
}
else if ([elementName isEqualToString:#"Book"])
{
[arrBook addObject:dictBook];
}
// [elementValue setString:#""];
}
- (void)parserDidEndDocument:(NSXMLParser *)parser {
NSLog(#"Arr Book Count : %lu", (unsigned long)arrBook.count);
}
Hope this will help you.
Iv'e set my h as the delegate and I'm calling the "setDelegate:self" method on my xml parser.
here is my code.
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
elementName = element;
if ([elementName isEqualToString:#"offer"]) {
offersDictionary = [[NSMutableDictionary alloc] init];
offerTitle = [[NSMutableString alloc] init];
offerDay = [[NSMutableString alloc] init];
offerDet = [[NSMutableString alloc] init];
NSLog(#"PARSER didStartElement method!");
}
}
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if ([element isEqualToString:#"offerTitle"]) {
[offerTitle appendString:string];
}
if ([element isEqualToString:#"day"]) {
[offerDay appendString:string];
}
if ([element isEqualToString:#"offerDetail"]) {
[offerDet appendString:string];
}
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if ([elementName isEqualToString:#"offer"]) {
[offersDictionary setObject:offerTitle forKey:#"offerTitle"]; NSLog(#"offerTitle:%#",offerTitle);
[offersDictionary setObject:offerDet forKey:#"offerDetail"]; NSLog(#"offerDet:%#",offerDet);
[offersDictionary setObject:offerDay forKey:#"day"]; NSLog(#"OfferDay:%#",offerDay);
NSLog(#"DidEndELEMENT");
//[offersArray addObject:[offersDictionary copy]];
}
}
I've set "NSlog" in my didStartElement and in my didEndElement methods, but I only get output from the didEndElement.
I'm calling the "parse" method of the NSXML from the viewDidLoad method.
here is my viewDidLoad method.
- (void)viewDidLoad
{
[super viewDidLoad];
//alloc and init the array
offersArray = [[NSMutableArray alloc] init];
//create NSUrl with the xml file
NSURL *xmlUrl = [NSURL URLWithString:#"http://mydomain.org/dir/dir/file.xml"];
//alloc and init the xml parser with the data of the file
xmlParser = [[NSXMLParser alloc]initWithContentsOfURL:xmlUrl];
//set some methods on the xml parser
[xmlParser setDelegate:self];
[xmlParser setShouldProcessNamespaces:NO];
[xmlParser setShouldReportNamespacePrefixes:NO];
[xmlParser setShouldResolveExternalEntities:NO];
//create a 'success gate' of the 'parse' method
BOOL xmlParseSuccess = [xmlParser parse];
if (xmlParseSuccess) {
NSLog(#"Successed Parsing! array Has %lu elements.", (unsigned long)offersArray.count);
} else if (!xmlParseSuccess) {
NSLog(#"Error Parsing!");
}
// Do any additional setup after loading the view.
}
Why is the didStartElement method not being called?
Here is your issue:
-(void)parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict {
/*
Your setting elementName to element. So whatever the
value of 'element' is, it will compare to #"offer".
It seems that the value of 'element' is not equal
to #"offer". You should not be Comment this line out
and it should work fine.
*/
elementName = element;
if ([elementName isEqualToString:#"offer"]) {
offersDictionary = [[NSMutableDictionary alloc] init];
offerTitle = [[NSMutableString alloc] init];
offerDay = [[NSMutableString alloc] init];
offerDet = [[NSMutableString alloc] init];
NSLog(#"PARSER didStartElement method!");
}
}
I am trying to parse xml response and want data in NSDictionary.how can I get data in dictionary instead of NSMutableArray. Please help me ,getting response like :
<NewDataSet>
<Table>
<ID>105</ID>
<pk3>Apr 05, 2013</pk3>
<YEAR>2013</YEAR>
<TIME>09:10:46 PM</TIME>
</Table>
</NewDataSet>
Thanks in advance.
You can try with this..
.h /////////////////
#interface LoginWithTauky:UIViewController<NSXMLParserDelegate,NSURLConnectionDelegate>
{
NSXMLParser *xmlParser;
NSMutableString *soapResults;
BOOL xmlResults;
}
.m //////////////
-(void)Viewdidload
{
xmlParser = [[NSXMLParser alloc] initWithData:XMLdata];
[xmlParser setDelegate: self];
[xmlParser setShouldResolveExternalEntities: YES];
[xmlParser parse];
}
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *) namespaceURI qualifiedName:(NSString *)qName
attributes: (NSDictionary *)attributeDict
{
NSLog(#"fsdfsd");
if( [elementName isEqualToString:#"Table"]||[elementName isEqualToString:#"ID"]||[elementName isEqualToString:#"pk3"]||[elementName isEqualToString:#"YEAR"]||[elementName isEqualToString:#"TIME"])
{
if(!soapResults)
{
soapResults = [[NSMutableString alloc] init];
}
xmlResults = YES;
}
}
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if( xmlResults )
{
[soapResults appendString: string];
NSLog(#"soap result %#",soapResults);
}
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if( [elementName isEqualToString:#"Table"])
{
xmlResults = FALSE;
[user_idArray addObject:soapResults];
soapResults = nil;
}
if( [elementName isEqualToString:#"ID"])
{
xmlResults = FALSE;
[IDArray addObject:soapResults];
soapResults = nil;
}
if( [elementName isEqualToString:#"pk3"])
{
xmlResults = FALSE;
[IDArray addObject:soapResults];
soapResults = nil;
}
if( [elementName isEqualToString:#"YEAR"])
{
xmlResults = FALSE;
[IDArray addObject:soapResults];
soapResults = nil;
}
if( [elementName isEqualToString:#"TIME"])
{
xmlResults = FALSE;
[IDArray addObject:soapResults];
soapResults = nil;
}
}
This works fine , i have tested it. Check it out
-(IBAction)parseTheXml:(id)sender
{
NSString * mystr =[[NSString alloc]initWithFormat:#"<NewDataSet>"
"<Table>"
"<ID>105</ID>"
"<pk3>Apr 05, 2013</pk3>"
"<YEAR>2013</YEAR>"
"<TIME>09:10:46 PM</TIME>"
"</Table>"
"</NewDataSet>" ];
NSData * mydata =[mystr dataUsingEncoding:NSUTF8StringEncoding];
if(!parser)
parser =[[NSXMLParser alloc]initWithData:mydata];
[parser setDelegate:self];
[parser setShouldResolveExternalEntities:YES];
BOOL success= [parser parse];
if(success)
{
NSLog(#"SUCCESS");
}
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
NSLog(#"the tag is %#",elementName);
if(!([elementName isEqualToString:#"Table"] ||[elementName isEqualToString:#"NewDataSet"]))
{
if(!dataDict)
dataDict =[[NSMutableDictionary alloc]init];
datastring =[[NSMutableString alloc]init];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
datastring = [NSMutableString stringWithFormat:#"%#",string];
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if(!([elementName isEqualToString:#"Table"] ||[elementName isEqualToString:#"NewDataSet"]))
{
if([elementName isEqualToString:#"VideoThumbnail"])
NSLog(#"the string is : %#",datastring);
[dataDict setObject:datastring forKey:elementName];
}
}
it will give you dictionary like this :
2013-12-05 16:24:05.959 parsingXML[3305:c07] the string we get is {
ID = 105;
TIME = "09:10:46 PM";
YEAR = 2013;
pk3 = "Apr 05, 2013";
}
So I am making an app that one part of it displays the users tweets in a table view. However there's something getting corrupted with some tweets such as its only showing a single character such as (") or an emoji character. In example if the tweet says:
RT #jakemillermusic: Everyone upload your pics that you took today during the ustream and caption it "follow #jakemillermusic #jakemiller"
when shown with NSLog it prints :
2013-04-03 00:34:30.476 ParsingXMLTutorial[3308:c07] RT #jakemillermusic: Everyone upload your pics that you took today during the ustream and caption it
2013-04-03 00:34:30.476 ParsingXMLTutorial[3308:c07] "
2013-04-03 00:34:30.477 ParsingXMLTutorial[3308:c07] follow #jakemillermusic #jakemiller
2013-04-03 00:34:30.478 ParsingXMLTutorial[3308:c07] "
Here's the URL I am using to fetch the XML format:
http://api.twitter.com/1/statuses/user_timeline/LexxiSaal.xml?include_entities=true&include_rts=true&screen_name=twitterapi&trim_user=false&contributor_details=true&count=50
HERES THE PARSING CODE:
-(id) loadXMLByURL:(NSString *)urlString
{
_tweets = [[NSMutableArray alloc] init];
NSURL *url = [NSURL URLWithString:urlString];
NSData *data = [[NSData alloc] initWithContentsOfURL:url];
parser = [[NSXMLParser alloc] initWithData:data];
parser.delegate = self;
[parser parse];
return self;
}
- (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
//string = [string stringByReplacingOccurrencesOfString:#" " withString:#""]; // space
string = [string stringByReplacingOccurrencesOfString:#"\n" withString:#""]; // newline
string = [string stringByReplacingOccurrencesOfString:#"\t" withString:#""];
currentNodeContent = (NSMutableString *) [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}
- (void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementname namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if ([elementname isEqualToString:#"status"])
{
currentTweet = [Tweet alloc];
isStatus = YES;
}
if ([elementname isEqualToString:#"user"])
{
isStatus = NO;
}
}
- (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementname namespaceURI: (NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if (isStatus)
{
if ([elementname isEqualToString:#"created_at"])
{
currentTweet.dateCreated = currentNodeContent;
}
if ([elementname isEqualToString:#"text"])
{
currentTweet.content = currentNodeContent;
}
}
if ([elementname isEqualToString:#"status"])
{
[self.tweets addObject:currentTweet];
currentTweet = nil;
currentNodeContent = nil;
}
}
#end
I would suggest few changes as below
- (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
NSString *value=[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet];
if(currentNodeContent == nil){
currentNodeContent = [[NSMutableString alloc] initWithString:value];
}else
[currentNodeContent appendString:value];
}
and in didEnd
- (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementname namespaceURI: (NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if (isStatus)
{
if ([elementname isEqualToString:#"created_at"])
{
currentTweet.dateCreated = currentNodeContent;
}
if ([elementname isEqualToString:#"text"])
{
currentTweet.content = currentNodeContent;
}
}
if ([elementname isEqualToString:#"status"])
{
[self.tweets addObject:currentTweet];
currentTweet = nil;
//currentNodeContent = nil; REMOVED
}
currentNodeContent = nil; // PUT OUTSIDE
}
The thing is you have to append string in method foundCharacters because the parser doesn't return all the string in between the tags at once..
And at last you should make the currentNodeContent nil, in the didEnd method globally because you are using it for other texts too.
Hope above helps..
I m getting response like this
<NewDataSet>
<Map>
<URL>
https://maps.google.co.in/maps?q=ABIL+House,+Ganeshkhind+Road,+Yashwant+nagar,+Pune,+Maharashtra&hl=en&sll=18.539118,73.834095&sspn=0.011169,0.021136&oq=ABIL+House&t=h&hnear=ABIL+House,+2,+Ganeshkhind+Rd,+Yashwant+nagar,+Pune,+Maharashtra+411007&z=16
</URL>
</Map>
</NewDataSet>
I have to parse url value to show in web view. How to parse xml file having two opening tags, this is my code:
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqualToString:#"Result"]) {
item = [[NSMutableDictionary alloc] init];
currentUser =[[NSMutableString alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:#"Result"]) {
[item setObject:currentUser forKey:#"Result"];
// [item setObject:currentPassword forKey:#"Name"];
[users addObject:[item copy]];
}
}
- (void)parser:(NSXMLParser )parser foundCharacters:(NSString *)string
{
if ([currentElement isEqualToString:#"Result"]) {
[currentUser appendString:string];
}
/* if ([currentElement isEqualToString:#"Name"])
{
[currentPassword appendString:string];
}
*/
}
- (void)viewDidLoad
{
users = [[NSMutableArray alloc] init];
NSURL *xmlURL = [NSURL URLWithString:#"http://abilcms.com.sv2.premiumwebserver.com/WebServiceStatus.aspx?UserID=demo#abil.com"];
xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:xmlURL];
[xmlParser setDelegate:self];
[xmlParser parse];
NSLog(#"name=%#",currentUser);
statuslabel.text= currentUser;
}
Here is a tutorial on xml parsing in ios that shows how it is done. http://theappcodeblog.com/2011/05/09/parsing-xml-in-an-iphone-app-tutorial
Here is another tutorial on accessing multi level XML documents
But as far as I can see you should just replace "Result" with "URL" if this is the only URL tag in your XML, as fa as I understand NSXMLParser will handle the levels for you in this case. Of course if there is more data in this XML that you need to access you should build it like the example in the second link.