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";
}
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.
I have an XML file somewhere on the web with a couple of profiles inside it and I want the number of profiles to be displayed in a textfield.
I have a textfield called: numberOfProfiles.. so what should I do in viewDidLoad?
numberOfProfiles.Text = ???
The XML file is being parsed like this:
NSMutableString *currentNodeContent;
NSXMLParser *parser;
ViewController *currentProfile;
bool isStatus;
ViewController *xmlParser;
-(id)loadXMLByURL:(NSString *)urlString
{
profile = [[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
{
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:#"firstname"])
{
currentProfile = [ViewController alloc];
isStatus = YES;
}
if([elementName isEqualToString:#"lastname"])
{
currentProfile = [ViewController alloc];
isStatus = YES;
}
if([elementName isEqualToString:#"email"])
{
currentProfile = [ViewController alloc];
isStatus = YES;
}
if([elementName isEqualToString:#"address"])
{
currentProfile = [ViewController alloc];
isStatus = YES;
}
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if([elementName isEqualToString:#"firstname"])
{
currentProfile->firstName = currentNodeContent;
NSLog(#"%#",currentProfile->firstName);
[profile addObject:currentProfile];
}
if([elementName isEqualToString:#"lastname"])
{
currentProfile->lastName = currentNodeContent;
NSLog(#"%#",currentProfile->lastName);
[profile addObject:currentProfile];
}
if([elementName isEqualToString:#"email"])
{
currentProfile->eMail = currentNodeContent;
NSLog(#"%#",currentProfile->eMail);
[profile addObject:currentProfile];
}
if([elementName isEqualToString:#"address"])
{
currentProfile->address = currentNodeContent;
NSLog(#"%#",currentProfile->address);
[profile addObject:currentProfile];
}
if([elementName isEqualToString:#"profiles"])
{
[self->profile addObject:currentProfile];
currentProfile = nil;
currentNodeContent = nil;
setText:currentProfile->lastName;
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
xmlParser = [[ViewController alloc] loadXMLByURL:#"http://dierenpensionlindehof.nl/profiles.xml"];
}
Thanks in advance!
for just count of element you can have an instance variable like of int type numberOfProfilesCount and you can increment this in
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
numberOfProfilesCount++;
}
and in
- (void)parserDidEndDocument:(NSXMLParser *)parser {
numberOfProfiles.Text = [NSString stringWithFormate:#"%d", numberOfProfilesCount];
}
to show your element count
Assuming profile is a global variable, use [profile count] to get the number of profiles.
The try: [numberOfProfiles setText:[[profile count] stringValue]
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 am using NSXMLParser to parse my XML with the following structure:
<characters>
<character>
<literal>本</literal>
<codepoint>
<cp_value cp_type="ucs">672c</cp_value>
<cp_value cp_type="jis208">43-60</cp_value>
</codepoint>
</character>
</characters>
I want to use the cp_value element's attribute_value as a key and the element value (e.g. 672c) as the value and place this key-value pair in my NSMutableDictionary *_codepoint. After parsing, I want the result (in the console) to look like this:
_codepoint: {
"ucs"=672c;
"jis208"=43-60;
}
As I have implemented the parser (code follows), I am getting this back in the console:
2013-01-22 22:12:46.199 MyApp[13391:c07] _codepoint: {
ucs = "\n \n ";
}
2013-01-22 22:12:46.201 MyApp[13391:c07] _codepoint: {
jis208 = "\n \n 672c\n ";
}
First - the values and keys are out-of-sync and second, the value for the jis208 element is not getting read-in. Second, I'm not sure what these \n and whitespaces are. Can anybody please give some advice?
The code I have written is:
- (void)parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict
{
if([elementName isEqualToString:#"characters"]) {
appDelegate.characters = [[NSMutableArray alloc] init];
} else if ([elementName isEqualToString:#"character"]) {
aCharacter = [[Character alloc] init];
} else if ([elementName isEqualToString:#"cp_value"]) {
if (!_codepoint) _codepoint = [[NSMutableDictionary alloc] init];
[_codepoint setValue:currentElementValue forKey:[attributeDict valueForKey:[[attributeDict allKeys] lastObject]]];
NSLog(#"_codepoint: %#", _codepoint);
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if (!currentElementValue) {
currentElementValue = [[NSMutableString alloc] initWithString:string];
} else {
[currentElementValue appendString:string];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:#"characters"]
// cp_values will be copied from a local NSMutableDictionary *_codepoint
|| [elementName isEqualToString:#"codepoint"]
) return;
if ([elementName isEqualToString:#"character"]) {
[appDelegate.characters addObject:aCharacter];
[aCharacter release];
} else if ([elementName isEqualToString:#"cp_value"]){
[aCharacter.codepoint addObject:_codepoint];
}
}
Thank you very much for looking.
problem is that you are adding currentElementValue to _codepoint before reading actual value into currentElementValue i.e you are adding it in when cp_value is started. you should add currentElementValue to _codepoint in didEndElement: delegate method.Then you'll get expected result.Modify your code like this:
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if([elementName isEqualToString:#"characters"]) {
appDelegate.characters = [[NSMutableArray alloc] init];
} else if ([elementName isEqualToString:#"character"]) {
aCharacter = [[Character alloc] init];
} else if ([elementName isEqualToString:#"cp_value"]) {
if (!_codepoint) _codepoint = [[NSMutableDictionary alloc] init];
currentAttributeKey = [[NSMutableString alloc]initWithString:[attributeDict valueForKey:[[attributeDict allKeys] lastObject]]];
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if (!currentElementValue) {
currentElementValue = [[NSMutableString alloc] initWithString:string];
} else {
[currentElementValue appendString:string];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:#"characters"] || [elementName isEqualToString:#"codepoint"])
return;
if ([elementName isEqualToString:#"character"]) {
[appDelegate.characters addObject:aCharacter];
[aCharacter release];
} else if ([elementName isEqualToString:#"cp_value"]){
[_codepoint setValue:[[currentElementValue componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] componentsJoinedByString:#""] forKey:currentAttributeKey];
currentElementValue = [[NSMutableString alloc]init];
NSLog(#"_codepoint: %#", _codepoint);
[aCharacter.codepoint addObject:_codepoint];
}
}
where currentAttributeKey is NSMutableString that will store the attributes.In your case ucs and jis208
I have parsed the xml file.
The console is showing the parsed elements correctly but the array is showing null.
- (ParserClass *) initXMLParser
{
//[super init];
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:#"note"]) {
//Initialize the array.
appDelegate.testArray = [[NSMutableArray alloc] init];
}
else if([elementName isEqualToString:#"to"]) {
aTest = [[Test 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:#"note"]) {
[appDelegate.testArray addObject:aTest];
//[aBook release];
aTest = nil;
}
else
[aTest setValue:currentElementValue forKey:elementName];
//[currentElementValue release];
currentElementValue = nil;
}
#end
Try to change your initialization to:
- (ParserClass *) initXMLParser {
self=[super init];
if(self !=nil){
appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
// init array of user objects here
appDelegate.testArray = [[NSMutableArray alloc] init];
}
return self;
}
And,if your xml is:
<books>
<note>
<something>cccc</something>
</note>
<note>
<something>cccc</something>
</note>
</books>
So you need change:
-(void)parser: (NSXMLParser *)parser didStartElement:(NSString *) elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict {
if([elementName isEqualToString:#"note"]) {
aTest = [[Test alloc] init];
//if you have attributes, you can extract them here:
// user.att = [[attributeDict objectForKey:#"<att name>"] ...];
}
NSLog(#"Processing Element: %#", elementName);
}
And to get your array you must do something like this:
//Data store your xml
NSXMLParser *nsXmlParser = [[NSXMLParser alloc] initWithData:Data];
ParserClass *parser = [[ParserClass alloc] initXMLParser];
//delegate your parser
[nsXmlParser setDelegate:parser];
//it's doing parsing
BOOL success = [nsXmlParser parse];
if (success)
{
NSMutableArray *someArray = [parser appDelegate.testArray ];
NSLog(#"%#",someArray );
} else
{
NSLog(#"Error parsing document!");
}
try it , it working for me...