I want to parse data from a xml file. This is working so far, but I don't find the correct way to get data from the dictionary.
My parser looks as follows
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict{
currentElement = [elementName copy];
if ([elementName isEqualToString:#"Placemark"]) {
placemarkData = [[NSMutableDictionary alloc] init];
currentTitle = [[NSMutableString alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
if ([currentElement isEqualToString:#"name"] || [currentElement isEqualToString:#"address"] || [currentElement isEqualToString:#"coordinates"])
[currentTitle appendString:string];
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName{
if ([elementName isEqualToString:#"Placemark"]) {
[placemarkData setObject:currentTitle forKey:currentElement];
[Placemarks addObject:[placemarkData copy]];
NSLog(#"adding story: %#", currentElement);
}
As you can see. The data is stored in a dictionary, and this dictionary is store in an array. Only problem is... the key for dictionary is always coordinates. This look kinda logical to me... but I don't find the logic to implement it the right way. Can somebody have a look?
Thnx in advance!
When you fill a dictionary, you set objects for keys. To get an object from a dictionay, you need to have the key. And I think that is your problem.
To list the keys in your dictionary, you can use a keyEnumerator:
NSEnumerator *enumerator = [myDictionary keyEnumerator];
id key;
while ((key = [enumerator nextObject])) {
/* code that uses the returned key */
NSString *theElement = key;
NSLog(#"Element: %#", theElement);
}
With this code, you will list all the keys. To find the object with the key, you use [myDictionary objectForKey:key];. If you know the elements in your XML you can access them with this line.
I think the problem you are facing is because of the logic you used in
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict{
currentElement = [elementName copy];
if ([elementName isEqualToString:#"Placemark"]) {
placemarkData = [[NSMutableDictionary alloc] init];
currentTitle = [[NSMutableString alloc] init];
}
}
method, i.e. allocating the placemarkData that will work fine if element Placemark is encountered first time but for the next iteration there will be problem, follow this idea and see the response on to the console, I am sure that you will find the solution.
come back if any doubt or query in that.
Related
I am parsing data using NSXMLParser.
I am able to get the parsed data. But when I add it to the NSMutableArray using addObject, the array is empty.
I am using the latest Xcode version.
Can someone please help me out.
The array I am working on is identificationTypes1
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
if ([elementName isEqualToString:#"Books"]) {
}
if ([elementName isEqualToString:#"Book"]) {
if ([elementName isEqualToString:#"title"]) {
self.identificationTypes1 =[[NSMutableArray alloc]init];
}
}
}
-(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:#"Books"]) {
NSLog(#"Count is %#",[identificationTypes1 count]);
return;
}
if ([elementName isEqualToString:#"Book"]) {
}
if ([elementName isEqualToString:#"title"]) {
NSLog(#"Curre value is %#",currentElementValue);
[self.identificationTypes1 addObject:currentElementValue];
}
currentElementValue = nil;
}
NSMutabeArray *myArray = [[NSMUtableArray alloc]init];
[myArray addObject:<XML Data>];
You cannot nest elements as you have in didStartElement. Parsers do not allow that.
Take out the title out on its own and retest. You need to make new variables that are accessed conditionally.
i'm new to iPhone development. i have two xml tags has a same name. how to differentiate this two tags. i mean how to identify when first tag will be closed
<data>
<level>0</level>
<type>video</type>
<file>file_CTcE96nTfP3sXIQ8.wmv</file>
<position>0,0,640,360</position>
<duration>121</duration>
</data>
<data>
<level>0</level>
<type>image</type>
<file>file_CTNJ1da7ntcTGmxd.jpg</file>
<position>640,0,1024,360</position>
<duration>121</duration>
</data>
<data>
<level>0</level>
<type>image</type>
<file>file_CTAo1yLWaZqXkpic.png</file>
<position>0,360,337,480</position>
<duration>121</duration>
</data>
i have implement these methods.
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
if ([elementName isEqualToString:#"data"]) {
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
???
}
here is there three data tags there. i want to put all each data tags in three array. how can i achieve that.i mean like this
data1(file,type,position,duration)
data2(file,type,position,duration)
data3(file,type,position,duration)
In didStartElement
if ([elementName isEqualToString:#"data"]) {
data = [[NSMutableDictionary alloc] init];
level = [NSMutableString alloc] init];
type = [NSMutableString alloc] init];
position = [NSMutableString alloc] init];
duration = [NSMutableString alloc] init];
}
Then in didEndElement
if ([elementName isEqualToString:#"data"]) {
[data setObject:type forKey:#"type"];
[data setObject:position forKey:#"position"];
[data setObject:duration forKey:#"duration"];
[dataList addObject:data];
}
U need to add foundCharacters delegate method and assign values to strings here
if ([currentElement isEqualToString:#"type"]) {
[type appendString:string];
}
if ([currentElement isEqualToString:#"position"]) {
[position appendString:string];
}
if ([currentElement isEqualToString:#"duration"]) {
[duration appendString:string];
}
level, position and duration are to be parsed as normal tags..
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:#"data"])
{
}
}
So I know how to parse some XML structures but I am currently trying to parse this specific xml structure thats a bit different to what I am used to.
normally I would parse something like
<xml>
<data>
<name>Forrest</name>
<age>25</name>
<username>forrestgrant</username>
</data>
</xml>
But now I'm working with some xml like so..
<xml>
<data name="Forrest" age="25" username="forrestgrant" />
<other value="6" />
</xml>
how do I access those variables when they are structured like this?
This is how I would normally approach this task, which is baised of searching for the title tags and getting the data from each one.. however I am now trying to figure out how to parse this other style of xml.
- (void)startTheParsingProcess:(NSData *)parserData
{
[myDataArray release]; // clears array for next time it is used.
myDataArray = [[NSMutableArray alloc] init]; //initalizes the array
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:parserData]; //incoming parserDatapassed to NSXMLParser delegate which starts parsing process
[parser setDelegate:self];
[parser parse]; //Starts the event-driven parsing operation.
[parser release];
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqual:#"item"]) {
// NSLog(#"Found title!");
itemString = [[NSMutableString alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
[itemString appendString:string];
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ([elementName isEqual:#"item"]) {
//NSLog(#"ended title: %#", itemString);
[myDataArray addObject:itemString]; //this is where i pass the values over to my array.
[itemString release];
itemString = nil;
}
}
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
// Passes myDataArray to the method that will sort and display the array into a uitableview.
[self startSortingTheArray:myDataArray];
}
any help would be greatly appreciated..
The xml data above provides the data as attributes on the xml element.
This callback method gives you access to the attributes as a dictionary of key values (attributeDict).
(void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict
NSLog the dictionary out in that method to see the values:
NSLog(#"attributes: %#", attributeDict);
In your didStartItem: method, the attributes dictionary will contain values for all the XML attributes.
hii every one
i am doing a iphone project in that i need to take a int value from xml so
how can i store a integer value which is stored in a xml, into a int variable using NSXMLParser (by parsing the xml)
can any one give me some examples,,, thanx in advance
Here is one way (assuming you already know how to use NSXMLParser)
xml:
<intVariable>10</intVariable>
code:
- (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 *)qualifiedName
attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqualToString:#"intVariable"])
intVariable = [currentElementValue intValue];
[currentElementValue release];
currentElementValue = nil;
}
(currentElementValue and intVariable are mutable string and int members respectively).
At the moment i've got the following code to get data from an xml file. This works so far
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict{
currentElement = [elementName copy];
if ([elementName isEqualToString:#"Placemark"]) {
placemarkData = [[NSMutableDictionary alloc] init];
currentTitle = [[NSMutableString alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
if ([currentElement isEqualToString:#"name"])
[placemarkData addObject:string forKey:currentElement];
if ([currentElement isEqualToString:#"address"])
[placemarkData addObject:string forKey:currentElement];
if ([currentElement isEqualToString:#"coordinates"])
[placemarkData addObject:string forKey:currentElement];
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName{
if ([elementName isEqualToString:#"Placemark"]) {
[Placemarks addObject:[placemarkData copy]];
NSString *batsen = [placemarkData objectForKey:#"name"];
NSLog(#"adding story: %#", batsen);
}
}
This dictionary will be loaded into a array. Problem is that where this array got loaded in need to find the right entry in the array. I do it like this
TabbedCalculationAppDelegate *appDelegate = (TabbedCalculationAppDelegate *)[[UIApplication sharedApplication] delegate];
NSArray *jean = appDelegate.Placemarks;
NSDictionary *boekje = [jean objectAtIndex:1];
NSString *coordinaten = [boekje objectForKey:#"coordinates"];
NSString *naam = [boekje objectForKey:#"name"];
NSLog(#"poep: %#" , naam);
NSLog(#"wwhoppa: %#", coordinaten);
titel.text = coordinaten;
But since arrays works with index I can't find a way to get the right entry. To clarify, a user clicks in a mapview on an annotation. This annotation then gets the corresponding detailview. The detailview can check which annotation is clicked by the view.annotation.title;
So I actually need a dictionary in a dictionary with name as key in the root dictionary. Is this possible? and on what way I can implement this?
Is this a little bit clear? Else just ask!
Thnx guys
Yes, this is a good idea. Just pass the 'inner' dictionary as the object parameter to setObject:forKey: on the 'outer' dictionary. It'll just work. For example:
NSMutableDictionary *outer=[[NSMutableDictionary alloc] init];
NSDictionary *inner=[NSDictionary dictionaryWithObject:#"hello" forKey:#"world"];
[outer setObject:inner forKey:#"greetings"];