IOS NSXMLParser Not getting all the text from the element? [duplicate] - ios

i have the following XMLParser but when i try to run it, it doesn't work properly.
- (void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementname namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if ([elementname isEqualToString:#"results"])
{
currentJob = [SearchResult alloc];
}
}
- (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementname namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ([elementname isEqualToString:#"jobTitle"])
{
currentJob.jobTitle = currentNodeContent;
}
if ([elementname isEqualToString:#"location"])
{
currentJob.shortAddress = currentNodeContent;
}
if ([elementname isEqualToString:#"companyName"])
{
currentJob.employer = currentNodeContent;
}
if ([elementname isEqualToString:#"results"])
{
[self.jobs addObject:currentJob];
currentJob = nil;
currentNodeContent = nil;
}
}
AND here is my foundCharakter Method:
- (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
currentNodeContent = (NSMutableString *) [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}
The output doesn't start from the beginning, it starts from the middle of the String...
I just can not understand, why some results look nice where some others don't.
What am i doing wrong ? How can i parse an xml properly ?
Any help will be appreciated.
Thx in advance

I used the following code and works now:
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
if(!elementContentString)
elementContentString = [[NSMutableString alloc] initWithString:string];
else
[elementContentString appendString:string];
}

I don't think there any problem in your code, it is working fine at my end. I am using the twitter api for getting xml and it is giving me proper output.

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;
}

Objective-C - how can separately parse attributes of my XML?

I'm working on an application where I use XML parsing in UITableView. I can not figure out how I'm separately parses attributes rok1 and rok2. If I use [_element isEqualToString: # "jmeno"] application works well, but it displayed to me in UITableView together rok1 and rok2 and do not want it. Thx for your help.
There is my parser code:
- (void)parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict {
self.element = elementName;
if ([_element isEqualToString:#"rok1"])
{
_item = [[NSMutableDictionary alloc] init];
self.nazev = [[NSMutableString alloc] init];
self.definice = [[NSMutableString alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if ([self.element isEqualToString:#"nazev"])
{
[self.nazev appendString:string];
}
else if ([self.element isEqualToString:#"def"])
{
[self.definice appendString:string];
}
}
- (void)parser:(NSXMLParser *)parser
didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName {
if ([elementName isEqualToString:#"rok1"])
{
Slova *thisSvatek = [[Slova alloc] initWithName:self.nazev
definice:self.definice];
[self.svatkyArray addObject:thisSvatek];
}
self.element = nil;
}
And example of my XML:
<?xml version="1.0" encoding="UTF-8" ?>
<menu>
<rok1>
<jmeno>
<nazev>Prvni</nazev>
<def>blblbla</def>
<jmeno>
<nazev>Druhy</nazev>
<def>blbablabal</def>
</jmeno>
</rok1>
<rok2>
<jmeno>
<nazev>Prvni</nazev>
<def>blblbla</def>
</jmeno>
</rok2>
</menu>
You need to keep track of your "state" as you are parsing the XML document. One simple approach is simply to add a boolean property that indicates that you are processing 'inside' the target element.
- (void)parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict {
self.element = elementName;
if ([elementName isEqualToString:#"rok1"])
{
self.foundTarget=YES;
self.nazev = [[NSMutableString alloc] init];
self.definice = [[NSMutableString alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if (self.foundTarget) {
if ([self.element isEqualToString:#"nazev"])
{
[self.nazev appendString:string];
}
else if ([self.element isEqualToString:#"def"])
{
[self.definice appendString:string];
}
}
}
- (void)parser:(NSXMLParser *)parser
didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName {
if ([elementName isEqualToString:#"rok1"])
{
Slova *thisSvatek = [[Slova alloc] initWithName:self.nazev
definice:self.definice];
[self.svatkyArray addObject:thisSvatek];
self.foundTarget=NO;
}
self.element = nil;
}
A more sophisticated approach is to build some sort of data structure, such as a dictionary, that represents your XML
- (void)parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict {
self.element = elementName;
if ([elementName isEqualToString:#"rok1"] || [elementName.isEqualToString:#"rok2"])
{
self.nazev = [[NSMutableString alloc] init];
self.definice = [[NSMutableString alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if ([self.element isEqualToString:#"nazev"])
{
[self.nazev appendString:string];
}
else if ([self.element isEqualToString:#"def"])
{
[self.definice appendString:string];
}
}
- (void)parser:(NSXMLParser *)parser
didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName {
if ([elementName isEqualToString:#"rok1"] || [elementName.isEqualToString:#"rok2"])
Slova *thisSvatek = [[Slova alloc] initWithName:self.nazev
definice:self.definice];
self.rokDictionary[elementName]=thisSvatek; // self.rokDictionary is an NSMutableDictionary
}
self.element = nil;
}
To separate out the various 'jmeno' tags, you need to handle them in didStartElement & didEndElement -
- (void)parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict {
self.element = elementName;
if ([elementName isEqualToString:#"rok1"] || [elementName.isEqualToString:#"rok2"])
{
self.jmenoArray=[NSMutableArray new];
}
else if ([elementName isEqualToString:#"jmeno"]) {
self.nazev = [[NSMutableString alloc] init];
self.definice = [[NSMutableString alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if ([self.element isEqualToString:#"nazev"])
{
[self.nazev appendString:string];
}
else if ([self.element isEqualToString:#"def"])
{
[self.definice appendString:string];
}
}
- (void)parser:(NSXMLParser *)parser
didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName {
if ([elementName isEqualToString:#"jmeno"]) {
Slova *thisSvatek = [[Slova alloc] initWithName:self.nazev
definice:self.definice];
[self.jemnoArray addObject:thisSvatek];
}
else if ([elementName isEqualToString:#"rok1"] || [elementName.isEqualToString:#"rok2"])
self.rokDictionary[elementName]=self.jmenoArray; // self.rokDictionary is an NSMutableDictionary
self.jmenoArray=nil;
}
self.element = nil;
}

How Can I parse an xml with empty tags using NSXMLParser?

How to parse the xml tags with empty values to get null values using NSXMLParser. I'm using the following code :
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqualToString:#"Video"])
{
isStatus = YES;
}
if ([elementName isEqualToString:#"ArrayOfVideo"])
{
isStatus = NO;
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
currentNodeContent = (NSMutableString *)[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if (isStatus)
{
if ([elementName isEqualToString:#"MediaOriginalFileName"])
{
[originalFileAry addObject:currentNodeContent];
}
if ([elementName isEqualToString:#"MediaType"])
{
[typeArray addObject:currentNodeContent];
}
if ([elementName isEqualToString:#"VideoMediaSource"])
{
[tableda addObject:currentNodeContent];
}
if ([elementName isEqualToString:#"VideoThumbnail"])
{
[tableImg addObject:currentNodeContent];
}
if ([elementName isEqualToString:#"VideoTitle"])
{
[tableData addObject:currentNodeContent];
}
}
}
here I'm not getting the empty values for the tag "VideoThumbnail".. Please help me to solve this...
this is what i tried ,and i found empty string, as expected from your example.
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
NSLog(#"the tag is %#",elementName);
if([elementName isEqualToString:#"VideoThumbnail"])
{
NSLog(#"video thumbnail tag arrived");
datastringThumbnail =[[NSMutableString alloc]init];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if(datastringThumbnail)
{
datastringThumbnail = [NSMutableString stringWithFormat:#"%#",string];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
{
if([elementName isEqualToString:#"VideoThumbnail"])
NSLog(#"the string is : %#",datastringThumbnail);
// [tableImg addObject:currentNodeContent];
// currentNodeContent is datastringThumbnail in my case
}
}
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
NSLog(#"the string we get is %#",datastringThumbnail);
}
FYI, datastringThumbnail is mutable string that will store you data of thumbnail tag(if any). As in your case there was no data in that tag, this string was empty. Use it wherever you want.
Actually, thing is that your method
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
}
is not being called since there are no data inside that particular data. So in following method ,you can do as follow :
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if (isStatus)
{
if ([elementName isEqualToString:#"VideoThumbnail"])
{
if([currentContent Length]>0)
{
[tableImg addObject:currentNodeContent];
}
else
{
[tableImg addObject:#" "];
}
}
}
}
forgive my indentation... Also TBXML parsing is much faster and easier way to work with xml parsing. you can directly give names of tags and their child nodes.
You try in
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
May be you get the getting the empty values for the tag "VideoThumbnail".
Following link useful for you.
https://developer.apple.com/library/ios/samplecode/SeismicXML/Listings/SeismicXML_APLParseOperation_m.html#//apple_ref/doc/uid/DTS40007323-SeismicXML_APLParseOperation_m-DontLinkElementID_11

XML Parsing within TAG in ios

I have a XML file:
<trkseg>
<trkpt lat="11.004661" lon="76.97364"></trkpt>
<trkpt lat="11.005497" lon="76.97496"></trkpt>
</trkseg>
Here is my code:
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqualToString:#"trkseg"])
{
self.tag = [[MRTRouteMapTag alloc]init];
NSLog(#"SRC: %#",[attributeDict objectForKey:#"lat"]);
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
[self.workingPropertyString appendString:string];
}
//event_logo, event_name, event_venue, event_date_time, race_details, event_descriptions;
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
{
if (self.tag)
{
NSString *trimmedString = [self.workingPropertyString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
// clear the string for next time
[self.workingPropertyString setString:#""];
if ([elementName isEqualToString:#"trkseg"])
{
[self.array addObject:self.tag];
self.tag = nil;
NSLog(#"Array Count ==>>>>>> %d", [self.array count]);
}
// Get Registered User Details
// ------ ------- ------------
else if ([elementName isEqualToString:#"trkpt"])
{
NSDictionary *attributeDict;
NSString *imageURLString = [attributeDict objectForKey:#"lat"];
self.tag.latitude = trimmedString;
NSLog(#"race_id ==>> %#", imageURLString);
}
}
}
Here I need to parse data from trkpt TAG of lat and lon value. Could any one guide me to achieve this.. Thanks in Advance.
lat and lon are not values, but attributes of node trkpt
They should be available to you at didStartElement like so:
[attributeDict objectForKey:#"lat"];
or
[attributeDict objectForKey:#"lon"];
This is not related to NSXMLPArser, but the XML structure itself.
The values that you are looking for are stored in the attributeDict dictionary in
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict
At finally i find the solution to archive it..
Here i added my sample code..
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqualToString:#"trkpt"])
{
self.tag = [[MRTRouteMapTag alloc]init];
lat = [attributeDict objectForKey:#"lat"];
lon = [attributeDict objectForKey:#"lon"];
tag.latitude = lat;
tag.longitude = lon;
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
[self.workingPropertyString appendString:string];
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if (self.tag)
{
if ([elementName isEqualToString:#"trkpt"])
{
[self.array addObject:self.tag];
self.tag = nil;
}
}
}

How to parse data from a website using NSXMLParser

I want to get the updates from a website based on the titles and links which is in xml format.
I have tried with the code below but it's not working. In console it is showing the message:
2011-11-03 14:45:05.987 tabbar[673:e903] * Terminating app due to
uncaught exception 'NSInvalidArgumentException', reason: '-[NSCFString
isEqualtostring:]: unrecognized selector sent to instance 0x5746830'
If I run again, the table view is loading but there is no data in the table cells.
It is showing this message at the line if ([elementName isEqualtostring:#"item"]):
program received signal SIGABRT
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
classelement = elementName;
if ([elementName isEqualtostring:#"item"])
{
itemselected = YES;
multitle = [[NSMutableString alloc]init];
mullink = [[NSMutableString alloc]init];
}
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedname:(NSString *)qName
{
if ([elementName isEqualToString:#"item"])
{
itemselected = NO;
[titlearray addObject:multitle];
[linkarray addObject:mullink];
[multitle release];
[mullink release];
[self.tbl reloadData];
}
}
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if (itemselected)
{
if ([classelement isEqualToString:#"title"])
{
NSLog(#"%#",string);
[multitle appendString:multitle];
}
else if([classelement isEqualToString:#"link"])
{
[multitle appendString:string];
}
}
}
If you are reading directly from a website more than likely you are getting "invalid" characters. As soon as the parser see's these invalid characters it will crash. I would suggest looking at using "HPPLE Parser". It works much better and wont crash if invalid characters come in.
Hpple information here: http://blog.objectgraph.com/index.php/2010/02/24/parsing-html-iphone-development/
Finally I got it. What I did is I have taken two NSMutableArrays and two NSMutableStrings and I appended the items to the strings, and later those strings I appended to the two arrays.
(void)viewDidLoad
{
titlearray = [[NSMutableArray alloc]init];
linkarray = [[NSMutableArray alloc]init];
NSString *rssaddress =#"http://www.greenday.com/rss";
NSURL *url = [NSURL URLWithString:rssaddress];
xmlparser = [[NSXMLParser alloc]initWithContentsOfURL:url];
[xmlparser setDelegate:self];
[xmlparser parse];
[super viewDidLoad];
}
(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
classelement = elementName;
if([elementName isEqualToString:#"item" ])
{
itemselected = YES;
titlestrng = [[NSMutableString alloc]init];
linkstrng = [[NSMutableString alloc]init];
}
}
(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if([elementName isEqualToString:#"item" ])
{
itemselected = NO;
[titlearray addObject:titlestrng];
[linkarray addObject:linkstrng];
[titlestrng release];
[linkstrng release];
[self.tb reloadData];
}
}
(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if(itemselected)
{
if([classelement isEqualToString:#"title"])
{
[titlestrng appendString: string];
NSLog(#"%#",titlestrng);
}
else if ([classelement isEqualToString:#"link"])
{
[linkstrng appendString:string];
NSLog(#"%#",linkstrng);
}
}
}

Resources