NSXMLParser issue : don't get all my items and no data - ios

I have some difficulties to understand how to use NSXMLParser despite all the tutos I've watched...
I have the following XML file with for example :
<rss>
<channel>
<title>The Title</title>
<link>A URL</link>
<language>English</language>
<item>
<name>John</name>
<title>John4034</title>
<city>LA</city>
<country>USA</country>
</item>
....
<item>
<name>Marc</name>
<title>Marc2942</title>
<city>London</city>
<country>England</country>
</item>
</channel>
</rss>
I aim to stock all the items in a NSMutableArray of Item. My class Item has 4 NSString (name, title, city, country).
Here is my XMLParser.m file :
- (id) loadXMLbyURL : (NSString *) urlString
{
items = [[NSMutableArray alloc] init];
NSURL *url = [NSURL URLWithString:urlString];
NSData *data = [NSData dataWithContentsOfURL: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:#"item"]) currentItem = [Item alloc];
}
- (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if([elementName isEqualToString:#"name"]) [currentItem setName:currentNodeContent];
if([elementName isEqualToString:#"title"]) [currentItem setTitle:currentNodeContent];
if([elementName isEqualToString:#"city"]) [currentItem setCity:currentNodeContent];
if([elementName isEqualToString:#"country"]) [currentItem setCountry:currentNodeContent];
}
if([elementName isEqualToString:#"item"])
{
[self.items addObject:currentItem];
currentItem = nil;
currentNodeContent = nil;
}
}
But with all this, I have 2 issues :
My array of items only contains 108 indexes whereas my XML file got 299.
I've no data in my items properties... everything is (null) when I try to print it in the log.
Please help !

If anybody has the same problem, I finally found the solution.
The problem of non-checking all the XML file was because of a PCDATA error in the XML file.
The problem of getting nothing in the NSStrings has been solved in this thread : NSXMLParser issue : don't get all data?

Related

NSXMLParser - empty value

I am trying NSXMLParser for getting values from an XML for first time. But I have a problem.
Below my XML:
<Library>
<Book>
<ID>1</ID>
<TITLE>Test</TITLE>
</Book>
</Library>
and parser code:
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *) elementName namespaceURI:(NSString *)namespaceURI qualifiedNam(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if([elementName isEqualToString:#"Book"])
{
NSLog(#"%#", [attributeDict valueForKey:#"ID"]);
}
}
The result ID is null. Can you help me please?
Unfortunately, NSXMLParser doesn't work this way. It traverses over the elements in XML in document order, so by the time the "Book" element starts, it hasn't reached the "ID" element yet. Your code would work if the XML looked like
<Book Id="1">
...
</Book>
but I suppose you have no control over the XML. Then you need a more sophisticated solution. I believe the following would work:
Add these instance variables
NSString *currentElement, *bookID, *bookTitle;
NSMutableString *elementValue;
Implement the following methods:
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *) elementName namespaceURI:(NSString *)namespaceURI qualifiedNam(NSString *)qName attributes:(NSDictionary *)attributeDict {
currentElement = elementName;
elementValue = nil;
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
// Append characters to element value
if (!elementValue) elementValue = [NSMutableString stringWithCapacity:100];
[elementValue appendString:string];
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName {
if ([#"Id" isEqualToString:elementName]) {
bookID = [elementValue copy];
} else if ([#"Title" isEqualToString:elementName]) {
bookTitle = [elementValue copy];
} else if ([#"Book" isEqualToString:elementName]) {
// end of Book element, do something with bookID and bookTitle
}
}
Follow the below code.You will understand.
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 *arrayID;
In your .m part
//Step 3 - Allocate your all Arrays in your viewDidLoad method
arrayId = [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:#"ID"])
{
NSLog(#"The Result 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:#"ID"])
{
[arrayResult addObject:currentStringValue];
}
currentStringValue = nil;
}

EXC_BAD_ACCESS for NSXMLParser code

I have written the below code to parse RSS feeds. but i keep getting EXC_BAD_ACCESS in foundCharacter method when it tries to compare element with #"title".Any idea where am i going wrong?
NSMutableDictionary * item;
NSMutableString * title;
NSMutableString * link;
NSString *element;
NSMutableArray *feeds;
-(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];
}
}
-(void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if ([elementName isEqualToString:#"item"]) {
[item setObject:title forKey:#"title"];
[item setObject:link forKey:#"link"];
[feeds addObject:[item copy]];
NSLog(#"feeds :: %#",feeds);
}
}
-(void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
if ([element isEqualToString:#"title"]) {
[title appendString:string];`enter code here`
}else if ([element isEqualToString:#"link"]){
[link appendString:string];
}
}
I think the mistake is in this line:
element = elementName;
You have to init the variable element. So write this one:
element = [[NSString alloc] initWithString:elementName];
Then it should work.

Parsing data with NSXML in iOS

I'm trying to parse data from a Wordpress RSS feed using NSXMLR. My problem is exporting my parsed data. So far I have,
- (void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
currentElement = [elementName copy];
if ([elementName isEqualToString:#"item"]){
currentTitle = [[NSMutableString alloc] init];
item = [[NSMutableDictionary alloc] init];
}
}
this class
- (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if ([elementName isEqualToString:#"item"]){
[item setObject:currentTitle forKey:#"title"];
}
[stories addObject:item];
}
- (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
if ([currentElement isEqualToString:#"title"]){
[currentTitle appendString:string];
}
}
NSMutableArray *stories;
NSMutableDictionary *item;
So in ViewDidLoad implementation, I have
//declare the object of allocated variable
NSData *xmlData=[[NSData alloc]initWithContentsOfURL:[NSURL URLWithString:#"URL"]];// URL that given to parse.
//allocate memory for parser as well as
xmlParserObject =[[NSXMLParser alloc]initWithData:xmlData];
[xmlParserObject setDelegate:self];
//asking the xmlparser object to beggin with its parsing
[xmlParserObject parse];
NSLog(#"%#", [item objectForKey:#"title"]);
My problem is that I only print one object, I have multiples elements. How can I make it scan every single one of them and print them all.
Thanks in advance.
If I understand your code correctly, item holds the currently parsed item,
and the array stories holds all items.
So you have to allocate the stories array first:
stories = [[NSMutableArray alloc] init];
Then you do the parsing (but you should add an error check):
NSData *xmlData=[[NSData alloc]initWithContentsOfURL:[NSURL URLWithString:#"URL"]];
xmlParserObject =[[NSXMLParser alloc]initWithData:xmlData];
[xmlParserObject setDelegate:self];
if (![xmlParserObject parse]) {
// Parsing failed, report error...
}
And finally print the contents of the array:
for (NSDictionary *story in stories) {
NSLog(#"%#", [story objectForKey:#"title"]);
}
The didEndElement method probably should look like this:
- (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if ([elementName isEqualToString:#"item"]){
[item setObject:currentTitle forKey:#"title"];
[stories addObject:item]; // <-- MOVED INTO THE IF-BLOCK
}
}

How parsing image from XML page

I am have rss page from wether site.
<item>
<title>Запорожье: Вечер 03 Mar, Sun</title>
<link>http://www.gismeteo.ru/city/daily/5093/?462419</link>
<description>Облачно, температура 1..3 С, давление 753..755 мм рт.ст., ветер Юго-Западный, 6 м/с</description>
<category>Погода</category>
<enclosure url="http://img.gismeteo.ru/images/icons/new/d.sun.c2.png" length="2000" type="image/gif" />
<source url="http://informer.gismeteo.ru/rss/34601.xml">GISMETEO.RU: Погода в г. Запорожье</source>
<guid>418461</guid>
</item>
It is my code
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if([elementName isEqualToString:#"title"]){
xmlStringFileObject.titleString = nodecontent;
}
else if([elementName isEqualToString:#"description"]){
xmlStringFileObject.descriptionString = nodecontent;
}
else if([elementName isEqualToString:#"category"])
{
self.xmlStringFileObject.categoryString = nodecontent;
}
if([elementName isEqualToString:#"item"])
{
[outputData addObject:xmlStringFileObject];
}
nodecontent=[[NSMutableString alloc]init];
}
It works good but i cant parsing image and load him to UIImageView
I need a parsing image from this
<enclosure url="http://img.gismeteo.ru/images/icons/new/d.sun.c2.png" length="2000" type="image/gif" />. Help me please.
Look how i did it
NSString* imageURL = urlString; //http://img.gismeteo.ru/images/icons/new/d.sun.c2.png
NSData *imageData = [[NSData alloc]initWithContentsOfURL:[NSURL URLWithString:imageURL]];
UIImage *img = [[UIImage alloc] initWithData:imageData];Or you do not know how to get url string from xml?
UIImageView *imageView = [[UIImageView alloc] initWithImage:img];
Or you do not know how to get url string from xml?
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
if([elementName isEqualToString:#"source"])
NSString *urlString = [attributeDict objectForKey:#"url"];
}

xml parsing having multiple opening tags

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.

Resources