I am trying to parse XML file which contains arabic words as follow:
<NewsComponent>
<HeadLine>العلاجية</HeadLine>
</NewsComponent>
when I NSLog the string on the NSXMLParser delegate it prints empty string, and even when i parse the data to the UITableView it shows empty text.
I am encoding the data as UTF-8 before passing it to the parser.
How can I parse the XMl without losing the content of the tag HeadLine?
notes:
1. The same XML with English language is working correctly.
2. Showing the XML in Any browser shows the data correctly.
3. converting the NSData to NSString and NSLog-ing before parsing the NSString show the xml correctly too.
Edit How am I doing this?
NSString *sURLREST = #"http://www.example.com/getXml";
NSURL *url = [NSURL URLWithString:sURLREST];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
NSURLResponse *response;
NSError *error = nil;
NSData *data = [NSURLConnection sendSynchronousRequest: request returningResponse: &response error: &error];
NSString* output = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSData* dataOutput = [output dataUsingEncoding: NSUTF8StringEncoding];
NSXMLParser *parser = [[NSXMLParser alloc] dataOutput];
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if([sCurrentItem isEqualToString:#"HeadLine"])
{
[mutuableArray addObject:string];
// I am just adding the string value to a NSMutuableArray to bind it with the UITableView.
NSLog(#"%#",string);
}
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
sCurrentItem = elementName;
}
Your error lies in parser:foundCharacters:. You cannot expect that that method will be called only once per element. It may be called multiple times. You have to create an empty mutable string before the method is called the first time per element (in parser:didStartElement:) and then append the new characters to that string. The string is not complete until parser:didEndElement: is called.
See Apple's sample code. They do it correctly.
Related
i have an XML file as url where the file contains like this,
<Products>
<products id="1">
<name>product1</name>
<price>$150</price>
<img>http://www.myimage.com/Main_pic.png</img>
</products>
</Products>
Now using NSXMLParser i can retrieve the data and the image but after i get those data am not understanding how to store in NSMutableArray or NSDictionary. Also i tried to implement lazyloading asynchronous image download from Lazy Loading Table Images Asynchronous Downloading from Apple. But i failed to load the images. Do we have any alternative for aynchronous loading.
Kindly describe me in detail about,
how to store a data retieved from url XML file in aysnchronous downloading.
how to separate data and image.
how to implement those in UIImage and data to view in iPhone.
EDITED
for better understanding i need the data and the image like below picture and not in the table view.
EDITED-2
By using the lazyloading parsing i modified according to my content here the code for your reference,
- (void)main{
self.workingArray = [NSMutableArray array];
self.workingPropertyString = [NSMutableString string];
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:dataToParse];
[parser setDelegate:self];
[parser parse];
if (![self isCancelled]){
self.completionHandler(self.workingArray);}
self.workingArray = nil;
self.workingPropertyString = nil;
self.dataToParse = nil;}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
if ([elementName isEqualToString:#"Products"]){
self.workingEntry = [[egsLists alloc] init];}
storingCharacterData = [elementsToParse containsObject:elementName];}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if (self.workingEntry){
if (storingCharacterData){
NSString *trimmedString = [workingPropertyString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
[workingPropertyString setString:#""];
if ([elementName isEqualToString:sIDStr]){
self.workingEntry.ProductID = trimmedString;}
else if ([elementName isEqualToString:sImageStr]){
self.workingEntry.img = trimmedString;}}
else if ([elementName isEqualToString:#"Products"]){
[self.workingArray addObject:self.workingEntry];
self.workingEntry = nil;}}}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
if (storingCharacterData){
[workingPropertyString appendString:string];}}
take a NSObject Class say DataClass
// create objects for your data in DataClass.h And Synthesize them in DataClass.m
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
DataClass *mydata=[[DataClass alloc]init];
if ([elementName isEqualToString:#"id"])
{
mydata.idvalue=[currentNodeContent stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}
if ([elementName isEqualToString:#"name"])
{
mydata.namevalue=[currentNodeContent stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}
if ([elementName isEqualToString:#"price"])
{
mydata.pricevalue=[currentNodeContent stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}
if ([elementName isEqualToString:#"img"])
{
mydata.imgLink=[currentNodeContent stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}
[myArray addObject:mydata];
}
After That When You Need you can Retrive the Data From Array if you are Using TableView
then in your CellForRowAtindexPath method use the following:
DataClass *mydata=[[DataClass alloc]init];
mydata=[myarray objectAtindex:indexPath.row];
cell.textlabel.text=mydata.nameValue;
cell.imageView.image=[UIImage imageWithData: [NSData dataWithContentsOfURL: [NSURL URLWithString:mydata.imglink]]];
You can Use LazyTableImages SampleCode from Apple for Loading Images.
http://developer.apple.com/library/ios/#samplecode/LazyTableImages/Introduction/Intro.html
For Complete XML parsing See the Tutorial or use Below Code:
Source : http://www.theappcodeblog.com/2011/05/09/parsing-xml-in-an-iphone-app-tutorial/
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://opentestdrive.com/Products.xml"]];
// Perform request and get JSON as a NSData object
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *responseString = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding] ;
NSLog(#"responseString=%#", responseString);
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:url]];
[request setHTTPMethod:#"GET"];
NSURLConnection *conn=[[NSURLConnection alloc] initWithRequest:request delegate:self];
if (conn)
{
receivedData = [[NSMutableData data] retain];
}
else
{
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[receivedData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[receivedData appendData:data];
}
- (void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementname namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if ([elementname isEqualToString:#"imgName"])
{
//if you Taking any NSObject Class then Alloc init here.
}
}
- (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementname namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ([elementname isEqualToString:#"name"])
{
namelable.text=currentNodeContent;
}
if ([elementname isEqualToString:#"price"])
{
pricelabel.text = currentNodeContent;
}
if ([elementname isEqualToString:#"imgName"])
{
imageView.image=[UIImage imageWithData: [NSData dataWithContentsOfURL: [NSURL URLWithString:currentNodeContent]]];
}
}
- (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
currentNodeContent = (NSMutableString *) [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}
Hi iam parsing an xml file and i got the response also which i have stored in a responseString.My problem with the delegate methods which are not being called, here's my parsing code
-(void)getData
{
NSURL *url = [NSURL URLWithString:#"http://quizpro.testshell.net/api/quiz/4"];
NSData *data = [NSData dataWithContentsOfURL:url]; // Load XML data from web
NSString *applicationDocumentsDir =
[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *storePath = [applicationDocumentsDir stringByAppendingPathComponent:#"quiz.xml"];
NSLog(#"store path is %#",storePath);
[data writeToFile:storePath atomically:TRUE];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
request.delegate=self;
[request startSynchronous];
NSError *error = [request error];
if (!error)
{
NSData *responseData=[request responseData];
NSString *data =[[[NSString alloc]initWithData:responseData encoding:NSUTF8StringEncoding] autorelease];
NSString *usableXmlString = [data stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSLog(#"usableXmlString is %#",usableXmlString);
NSData *usableData = [usableXmlString dataUsingEncoding:NSUTF8StringEncoding];
NSXMLParser *xmlParser = [[NSXMLParser alloc]initWithData:usableData];
[xmlParser setDelegate:self];
[xmlParser parse];
}
}
- (void)requestFinished:(ASIHTTPRequest *)request
{
NSLog(#"requestFinished method");
// Use when fetching text
NSString *responseString = [request responseString];
** I get the entire data here **
NSLog(#"responseString is %#",responseString);
NSData *xData = [responseString dataUsingEncoding:NSUTF8StringEncoding];
//myCode.text = responseString;
//NSLog(#" response %#", responseString);
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:xData];
[parser setDelegate:self];
[parser parse];
[parser release];
}
And i wrote the NSXMLParser delegate methods like below
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
NSLog(#"parser/didStartElement");
currentTag = elementName;
if ([currentTag isEqualToString:#"questions"])
{
exams_object=[[ExamsObject alloc]init];
NSLog(#"%#",currentTag);
}
if ([currentTag isEqualToString:#"Question"])
{
exams_object=[[ExamsObject alloc]init];
}
if ([currentTag isEqualToString:#"Response"])
{
exams_object.responseArray=[[NSMutableArray alloc]init];
}
NSLog(#"%#",currentTag);
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
NSLog(#"parser/didEndElement");
if ([currentTag isEqualToString:#"questions"])
{
exams_object=[[ExamsObject alloc]init];
}
if([elementName isEqualToString:#"Question"])
{
[mainArray addObject:exams_object];
}
}
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)str
{
NSLog(#"parser/foundCharacters");
if ([currentTag isEqualToString:#"questionText"])
{
[exams_object.questionArray addObject:str];
}
if ([currentTag isEqualToString:#"responseText"])
{
[exams_object.responseArray addObject:str];
}
}
Thanks for help me
Have you included NSXMLParserDelegate and ASIHTTPRequestDelegate in your .h file ?
You are calling the method to parse the XML from delegate of ASIHTTPRequest
Check the flow of execution using breakpoints.
#interface yourClassName: NSObject <NSXMLParserDelegate, ASIHTTPRequestDelegate>
Also check these stackoverflow questions
Question 1
Question 2
Check whether you have added NSXMLParserDelegate in #interface and set parser.delegate=self in the class where you are using.
I need to call an XML file from a WCF Service and parse the content of XML in iPhone. I'm able to call the service URL but when parsing using NSXMLParser, I couldn't get a patricular attribute value in XML. I'm using a ViewController application in XCode.
My XML file is like this:
<GetCompanyResponse xmlns="http://schemas.datacontract.org/2004/07/DomainModel"
xmlns:i="http://www.w3.org/2001/XMLSchema-
<CompanyList>
<Company>
<Id>b9ca2e32-ce88-4d72-99ce-9bc592511e85</Id>
</Company>
</CompanyList>
NSString *urlString = [NSString stringWithFormat:#"http://192.168.0.107:8732/Design_Time_Addresses/IServices/
AppointmentService/json/GetCompany";
NSURL *jsonUrl =[NSURL URLWithString:urlString];
NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:jsonUrl];
[parser setDelegate:self];
[parser setShouldProcessNamespaces:NO];
[parser setShouldReportNamespacePrefixes:NO];
[parser setShouldResolveExternalEntities:NO];
[parser parse];
[parser release];
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:
(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqualToString:#"Company"]) {
NSString *name=[attributeDict objectForKey:#"Id"];
}
}
But when I check for the value in 'name' it is returning nil. I don't know what's wrong. What should I change? How can I get the value of the ID attribute?
Any help would be appreciated. Thanks in advance.
id is not attribute of the name. Put code in didEndElement:
define strVal NSString in .h;
Inside found character:
{
strVal=string;
}
Inside parserDidEndElement method:
{
if ([elementName isEqualToString:#"Id"]) {
NSString *name=strVal;
}
}
This will work for you.
I have the following method, I have one more method through which I am calling this method, but have no luck yet.
- (void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict{
if ([elementName isEqualToString:#"isphone-config"]) {
Pusername = [attributeDict valueForKey:#"authentication_username"];
Ppassword = [attributeDict valueForKey:#"authentication_password"];
Pidentity = [attributeDict valueForKey:#"sip_identity"];
Pdomain = [attributeDict valueForKey:#"domain"];
Pprotocol = [attributeDict valueForKey:#"protocol"];
Pudpport = [attributeDict valueForKey:#"registrar_port"];
Ptcpport = [attributeDict valueForKey:#"listening_port"];
NSLog(#"Title: %#, ID: %#", Pusername, Ppassword);
}
}
}
And I am calling it from the following method..
NSString* username = [[NSUserDefaults standardUserDefaults] stringForKey:#"username_preference"];
NSString* accountPassword = [[NSUserDefaults standardUserDefaults] stringForKey:#"password_preference"];
NSString* urlString = [NSString stringWithFormat:#"https://%#:%##test.com/test.php",username,accountPassword];
NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString]];
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
parser = [[NSXMLParser alloc] initWithData: response];
NSLog(#"at parser %#", parser);
[parser setDelegate:self];
I am having issues in the last line of the code from where I am calling parser. I assume that this line will call the method parser, correct me if I am wrong. I don't know which files, interfaces and classes I have to import, include or implement.
XML parsing with NSXMLParser is much more difficult, check Apple's example "earthquakes".
Instead I suggest you to use another XML parser. For example, this one:
Also, good article about how to choose parser.
http://www.raywenderlich.com/725/how-to-read-and-write-xml-documents-with-gdataxml
I'm creating an app. I'm sending the login info using HTTP POST method and the replyI'm getting from server is in HTML format. How can I parse that HTML and add different methods for succession or failure? What I'm trying to achieve is, upon login failure it should show the message using UIAlerView and upon successful login, the app should change the view with animation. :)
The code I'm using right now:
- (IBAction) loginButton: (id) sender {
indicator.hidden = NO;
[indicator startAnimating];
loginbutton.enabled = NO;
// Create the username and password string.
// username and password are the username and password to login with
NSString *postString = [[NSString alloc] initWithFormat:#"username=%#&password=%#",userName, password];
// Package the string in an NSData object
NSData *requestData = [postString dataUsingEncoding:NSASCIIStringEncoding];
// Create the URL request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL: [NSURL URLWithString:#"http://localhost/dologin.php"]]; // create the URL request
[request setHTTPMethod: #"POST"]; // you're sending POST data
[request setHTTPBody: requestData]; // apply the post data to be sent
// Call the URL
NSURLResponse *response; // holds the response from the server
NSError *error; // holds any errors
NSData *returnData = [NSURLConnection sendSynchronousRequest: request returningResponse:&response error:&error]; // call the URL
/* If the response from the server is a web page, dataReturned will hold the string of the HTML returned. */
NSString *dataReturned = [[NSString alloc] initWithData:returnData encoding:NSASCIIStringEncoding];
alertWithOkButton = [[UIAlertView alloc] initWithTitle:#"Status..." message:[NSString stringWithFormat:#"%#",dataReturned] delegate:self cancelButtonTitle:#"Okay" otherButtonTitles:nil];
[alertWithOkButton show];
[alertWithOkButton release];
}
What I did exactly is I used HTMLparser class. This class is very useful if you're getting response in HTML format.
-(void)startParsingForLogin:(NSString *)userIdStr Password:(NSString *)passwordStr
{
NSString *urlString = [NSString stringWithFormat:#"http://www.example.com/loginxml.php?username=%#&password=%#",userIdStr,passwordStr];
////////NSLog(#"urlString : %#",urlString);
NSURL *xmlURL = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] initWithURL:xmlURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0]autorelease];
NSURLResponse *returnedResponse = nil;
NSError *returnedError = nil;
NSData *itemData = [NSURLConnection sendSynchronousRequest:request returningResponse:&returnedResponse error:&returnedError];
//NSString *itemString = [[[NSString alloc] initWithBytes:[itemData bytes] length:[itemData length] encoding:NSUTF8StringEncoding]autorelease];
//////NSLog(#"itemString : %#",itemString);
xmlParser = [[NSXMLParser alloc] initWithData:itemData];
[xmlParser setDelegate:self];
[xmlParser parse];
}
- (void)parserDidStartDocument:(NSXMLParser *)parser
{
////////NSLog(#"parserDidStartDocument");
}
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
{
////////NSLog(#"parseErrorOccurred");
NSString * errorString = [NSString stringWithFormat:#"Error (Error code %i )", [parseError code]];
UIAlertView * errorAlert = [[UIAlertView alloc] initWithTitle:#"Error loading data" message:errorString delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[errorAlert show];
[errorAlert release];
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes: (NSDictionary *)attributeDict
{
////NSLog(#"didStartElement");
////NSLog(#"elementName : %#",elementName);
////NSLog(#"namespaceURI : %#",namespaceURI);
////NSLog(#"qualifiedName : %#",qualifiedName);
////NSLog(#"attributeDict : %#",attributeDict);
[registerNewArr addObject:attributeDict];
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
////NSLog(#"foundCharacters");
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
/////NSLog(#"didEndElement");
}
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
}