XML Parser organizing the elements in the keys - objective-c

I'm reading the existing elements within my xml file and organizing within a NSMutableDictionary with keys and objects, the structure of my xml file is as follows:
<?xml version="1.0"?>
<root>
<elements>
<element1>something 0</element1>
<element2>somethingelse 0</element2>
<element3>anotherthing 0</element3>
</elements>
<elements>
<element1>something 1</element1>
<element2>somethingelse 1</element2>
<element3>anotherthing 1</element3>
</elements>
<elements>
<element1>something 2</element1>
<element2>somethingelse 2</element2>
<element3>anotherthing 2</element3>
</elements>
</root>
My code is bellow:
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
NSString *trim = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if(!currentString){
currentString = [[NSMutableString alloc] init];
}
[currentString appendString:trim];
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if([elementName isEqualToString:#"root"]){
currentString = nil;
return;
}
if([elementName isEqualToString:#"elements"]){
key++;
currentString = nil;
}else{
NSString *keyp = [NSString stringWithFormat:#"%d",key];
NSMutableArray *listForelements = elementsArray[keyp];
if (keyp != nil) {
listForelements = [NSMutableArray array];
[elementsArray setValue:currentString forKey:keyp];
}
[listForelements addObject:currentString];
currentString = nil;
return;
}
currentString = nil;
The array elementsArray is returning me the following values:
0 = "anotherthing 0";
1 = "anotherthing 1";
2 = "anotherthing 2";
Instead of:
0 =
"something 0"
"somethingelse 0"
"anotherthing 0"
1 =
"something 1"
"somethingelse 1"
"anotherthing 1"
...
How I can solve this Problem?

After working with a significant amount of XML recently, I'd say your best bet is to look at a library like Ono. Parsing your XML is possible using the built in NSXMLParser and delegate methods but there is an unnecessary amount of things to keep track of compared to the following solution with Ono.
This solution makes use of a single class method that accepts the XML as NSData and returns an NSDictionary. This method has been created in a dedicated parsing class for whatever it's worth.
#import "Ono.h"
+ (NSDictionary *)parseData:(NSData *)data
{
NSError *docError;
ONOXMLDocument *document = [ONOXMLDocument XMLDocumentWithData:data error:&docError];
if (docError) {
// handle document creation error
NSLog(#"%#", docError.localizedDescription);
}
NSMutableDictionary *parsedData = [NSMutableDictionary dictionary];
[document enumerateElementsWithXPath:#"//elements" usingBlock:^(ONOXMLElement *element, NSUInteger idx, BOOL *stop) {
NSString *key = [NSString stringWithFormat:#"%d", idx];
NSMutableArray *items = [NSMutableArray array];
[element.children enumerateObjectsUsingBlock:^(ONOXMLElement *obj, NSUInteger idx, BOOL *stop) {
NSString *trimmedString = [obj.stringValue stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
[items addObject:trimmedString];
}];
[parsedData setObject:[items copy] forKey:key];
// [parsedData setObject:[items copy] forKey:#(idx)]; if you wanted to use an NSNumber as the key
[items removeAllObjects];
}];
return parsedData;
}
We first create an ONOXMLDocument using the +XMLDocumentWithData:error: method. Next we want to check that the document was created correctly and handle an error appropriately.
The NSMutableDictionary is created to store the parsed data and is returned by the method.
With regards to parsing, we first enumerate all of the ONOXMLElement instances that have the XPath elements. Using the XML provided, this gives us 3 items. We then create a key for the contained arrays to be stored by using the index provided by the enumeration block. We could also use an NSNumber as commented in the code.
Next, we create an NSMutableArray that will hold the content strings we intend to parse. We need to enumerate the children (element1, element2, element3) of each elements node. For convenience, we use ONOXMElement as the type of the argument obj so we can use the stringValue property which returns the content of the node.
As above, it's trimmed according to the desired character set, and then we add it to our items array. After enumerating the children of an element, we add a copy of the items array to the dictionary (since it's immutable the contents would change on the next iteration) and then remove all the objects so it is empty for our next iteration.
Once all iterations are complete, we return the dictionary of parsed XML.

Related

NSMutableArray loses data

There is lots of help regarding this issue already here but none of the implementations have worked. i.e.: creating (nonatomic, retain) + using self.myArray, Using a dictionary instead of arrays.
What I am doing is parsing information from an xml document, filter out unwanted entries, and try to dynamically store the information for that entry.
When I try to store the info into 2 mutableArrays the information of ONE of them gets lost when trying to access the info outside of my 'parser' method.
Some background code. Not full code. (this also has the dictionary as well)
.h
#interface WikiView : UIViewController {
//scrollview
UIScrollView *ScrollView;
//init
int isIpad;
int orientation;
int parseCount;
//parse data constructs
NSString *subplant;
NSString *element;
NSMutableString *text;
NSString *oldElement;
NSMutableDictionary *dataHolder;
NSMutableArray *dataGroup;
NSMutableArray *dataText;
}
#end
.m
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
//inits
dataGroup = [[NSMutableArray alloc] init];
dataText = [[NSMutableArray alloc] init];
dataHolder = [[NSMutableDictionary alloc] initWithCapacity:1];
text = [[NSMutableString alloc] init];
//parse the info
[self loadDataFromXML:xmlpath];
//When I call the values for dataText here they are all null
//also when called the objects for dataHolder are null as well
//this outputs the correct array
for (int i = 0; i<[dataGroup count]; i++) {
NSLog(#"%#",dataGroup[i]);
}
//this outputs an array of null objects
for (int i = 0; i<[dataText count]; i++) {
NSLog(#"HI.....%#",dataText[i]);
}
}
//parse function
//method to retrieve data
- (void)loadDataFromXML:(NSString *)xmlpath {
//data is parsed
NSData* data = [NSData dataWithContentsOfFile: xmlpath];
NSXMLParser* parser = [[NSXMLParser alloc] initWithData: data];
[parser setDelegate:self];
[parser parse];
[parser release];
}
//on found characters
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if ([subplant isEqualToString:plantid]) {
NSString *s2 = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if (![oldElement isEqualToString:element]) {
if (oldElement != nil) {
if (parseCount >= 1) {
//Here I store the values into the proper places
NSLog(#"%#: %#",oldElement,text);
[dataGroup addObject:oldElement];
[dataText addObject:text];
[dataHolder setObject:text forKey:oldElement];
//The values are correct here
}
parseCount++;
}
//if (new tag) reset string
[text setString:s2];
}
else{
//if not new tag append string (takes care of &apos;)
[text appendString:s2];
}
oldElement = element;
}
}
//on did start element
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
//accessing tags of this element
if ([elementName isEqualToString:#"plant"]) {
subplant = [attributeDict valueForKey:#"plant"];
}
element = elementName;
}
-(void)dealloc{
[super dealloc];
[text release]; [dataGroup release]; [dataText release]; [dataHolder release];
}
I create dataGroup and dataText the exact same way but only dataText loses its value.
Any help is appreciated, and if any part of my code is unclear please let me know.
EDIT:
Found the source of the problem.
When I write to the dataText array I rewrite every entry to be the last entry to be entered. In my test case the last entry was the string #"null" creating an array of nulls.
Will be back with solution when found.
EDIT2:
#RuslanSoldatenko Noticed I did not create a new instance of my text string after I set the object in the array. Look at the comments for help.

nsmutablearray elements to nsstring

I want to retrieve elements that are parsed in a NSMutableArray and store them into a NSString variable and then store them in NSMutableArray as NSString (because I want to display the content in a NSComboBox). I tried this but it dosen't work. Can you fix the problem, I can't fix it:
//--this is the parsing code :
- (void)parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict {
if ([elementName isEqualToString:#"user"]) {
NSLog(#"user element found – create a new instance of User class...");
if(currentElementValue == nil)
currentElementValue = [NSMutableString string];
else
[currentElementValue setString:#""];
}
else {
currentElementValue = nil;
}
user = [[User alloc] init];
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if (!currentElementValue) {
// init the ad hoc string with the value
currentElementValue = [[NSMutableString alloc] initWithString:string];
} else {
// append value to the ad hoc string
[currentElementValue appendString:string];
if (currentElementValue)
{
currentElementValue = nil;
}
}
NSLog(#"Processing value for : %#", string);
}
- (void)parser:(NSXMLParser *)parser
didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName {
if ([elementName isEqualToString:#"users"]) {
// We reached the end of the XML document
return;
NSLog(#"QUIT");
}
if ([elementName isEqualToString:#"userName"]) {
[[self user] setUserName:currentElementValue];
NSLog(#"final step for value: %#", user.userName);
NSLog(#"currentElementName content : %#", currentElementValue);
[currentElementValue release];
NSLog(#"release : %#", currentElementValue);
currentElementValue = nil;
NSLog(#"release : %#", currentElementValue);
}
if ([elementName isEqualToString:#"firstName"]) {
[[self user] setFirstName:currentElementValue];
[currentElementValue release];
currentElementValue = nil;
}
if ([elementName isEqualToString:#"lastName"]) {
[[self user] setLastName:currentElementValue];
[currentElementValue release];
currentElementValue = nil;
}
if ([elementName isEqualToString:#"user"]) {
NSLog(#"\n user=%# \n",user);
[users addObject:user];
NSLog(#"userName test : %#", users);
[user release];
user = nil;
}
}
-(BOOL)parseDocumentWithData:(NSData *)data {
if (data == nil)
return NO;
NSXMLParser *xmlparser = [[NSXMLParser alloc] initWithData:data];
[xmlparser setDelegate:self];
[xmlparser setShouldResolveExternalEntities:NO];
BOOL ok = [xmlparser parse];
if (ok == NO)
NSLog(#"error");
else
NSLog(#"OK");
[xmlparser release];
return ok;
}
// this is the xml file :
<users>
<user>
<userName>mspeller</userName>
<firstName>Mike</firstName>
<lastName>Speller</lastName>
</user>
<user>
<userName>mgdan</userName>
<firstName>Mila</firstName>
<lastName>Gdan</lastName>
</user>
</users>
//-------
NSMutableArray *tabletest= [[NSMutableArray alloc] init];
NSMutableString * result = [[NSMutableString alloc] init];
int i;
for(i=0; i < [users count]; i++){
[result appendString:[NSString stringWithFormat:#"%#",[[users objectAtIndex:i] valueForKey:#"userName"]] ];
NSLog(#"result==%#",result);
[tabletest addObject:result];
}
Based on your link in the comment section I think you're accessing the "userName" property the wrong way. You're trying to access it, as users contains NSDictionary objects. As far as I can see you're adding User objects to the NSMutableArray.
Try the following (I took the liberty to beautify the code a bit):
NSMutableArray *tabletest= [NSMutableArray array];
for (User* user in users)
{
NSString* result = [NSString stringWithFormat:#"%#", user.userName];
NSLog(#"result==%#",result);
[tabletest addObject:result];
}
Please correct me if I totally misunderstood your design.
I don't follow what your intention is, but what your code does at the moment is add the same string [user count] time to the array tabletest as follows:
The line:
[result appendString:[NSString stringWithFormat:#"%#",[[users objectAtIndex:i] valueForKey:#"userName"]] ];
accumulates into result the result of appending each [[users objectAtIndex:i] valueForKey:#"userName"] together - each iteration of the loop adds the next item to the end of result.
The line:
[tabletest addObject:result];
Adds the object referenced by result into the array. This is done once per iteration so the array ends up with [users count] references to the same object. Placing a reference to a mutable string into an array does not place a copy of its current value, just a reference to the string - mutate the string and the mutation is visible through the reference stored in the array.
So the final result of your code is an array of [users count] references to the same mutable string, and that string is the concatenation of all the [[users objectAtIndex:i] valueForKey:#"userName"] values.
What was your intent?
If you are trying to create an array of string representations of [[users objectAtIndex:i] valueForKey:#"userName"] then change the code to:
NSMutableArray *tabletest= [[NSMutableArray alloc] init];
for(int i = 0; i < [users count]; i++)
{
// create a string representation of userName
NSString *result = [NSString stringWithFormat:#"%#",[[users objectAtIndex:i] objectForKey:#"userName"]];
// add the string to the array
[tabletest addObject:result];
}
But maybe your intent is something else?

String Replacement operations in objective c

I got the result which is in the form of
<ZmaterialGroupList><Matkl>001</Matkl><Text>Metal processing</Text></ZmaterialGroupList>
I need to get the result as 001 Metal processing when i apply the string replacement function upon this it give an exception.Please help me.
Added code from comment:
for(int i=0; i<[soapArray.items count]; i++) {
NSString *str = [soapArray.items objectAtIndex:i];
str = [str stringByReplacingOccurrencesOfString:#"<Matkl>" withString:#""];
}
In this way I wrote but I got an exception like
Invalid argument pass at str
You might do better to use NSXMLParser rather than trying to replace pieces of the XML.
If you update your question to include a bit more explaining your code (specifically the code that deals with soapArray), I should be able explain a bit more as to why your code doesn't work as it is.
Using NSXMLParser
It's important to remember that NSXMLParser just reads the data you give it sequentially, it doesn't use a DOM structure.
Setup
Primarily you need to give your parser something to parse! In my example I get a resource from the bundle and convert it to NSData. There is also however another option to initWithContentsOfURL. Make sure you don't forget to set your delegate!
-(void) parse
{
NSString *file = #"myXMLFile.xml";
NSData *data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[file stringByDeletingPathExtension] ofType:[file pathExtension]]];
//If you already have a string:
//NSData* data=[xmlString dataUsingEncoding:NSUTF8StringEncoding];
if (data.length == 0)
{
//No data
return nil;
}
...
}
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
parser.delegate = self;
[parser parse];
Parsing
-(void) parserDidStartDocument:(NSXMLParser *)parser
{
//Here you set up any variables you might need while parsing
}
-(void) parserDidEndDocument:(NSXMLParser *)parser
{
//I usually don't have to do anything here but you might need to release some variables here for example.
}
-(void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
//Here is where the bulk of the parsing is done if you are using attributes. I prefer to use attributes as it looks cleaner both in the XML file and the parser.
if ([elementName isEqualToString:#"element1"])
{
//Just an example of what you might want to do
int index = [[attributeDict valueForKey:#"attribute1"] intValue];
NSString *name = [attributeDict valueForKey:#"n"];
[exampleDictionary setValue:name forKey:[NSString stringWithFormat:#"%d", index]];
}
if ([elementName isEqualToString:#"element2"])
{
//We need to know that the next piece of information (from foundCharacters) is for element 2
currentElement = ELEMENT_2;
}
}
//If you haven't used attributes you might find that you have a lot of parsing to do here instead.
-(void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
//Check what this info is for?
if(currentElement == ELEMENT_2)
{
element2Data = [NSString stringWithString:string];
}
}
-(void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:#"element2"])
{
myObject.somethingThatNeedsElement2 = element2;
}
}
Finishing
After finishing it's a good idea to check that nothing went wrong and free up the parser memory. So in your parse method, add this after the call to [parser parse].
if ([parser parserError] != nil)
{
[[[[UIAlertView alloc] initWithTitle:#"Error parsing XML" message:[[parser parserError] localizedDescription] delegate:nil cancelButtonTitle:#"Done" otherButtonTitles:nil] autorelease] show];
}
[parser release];
Consider using an XML parser or you can use NSScanner:
Example:
NSString *wanted;
NSString *fullMessage;
NSString *xml = #"<ZmaterialGroupList><Matkl>001</Matkl><Text>Metal processing</Text></ZmaterialGroupList>";
NSScanner *scanner = [NSScanner scannerWithString:xml];
[scanner scanUpToString:#"<Matkl>" intoString:nil];
[scanner scanString:#"<Matkl>" intoString:nil];
[scanner scanUpToString:#"</Matkl>" intoString:&wanted];
fullMessage = wanted;
[scanner scanUpToString:#"<Text>" intoString:nil];
[scanner scanString:#"<Text>" intoString:nil];
[scanner scanUpToString:#"</Text>" intoString:&wanted];
fullMessage = [fullMessage stringByAppendingFormat:#" %#", wanted];
NSLog(#"fullMessage: '%#'", fullMessage);
NSLog output:
fullMessage: '001 Metal processing'

Functionality for Updating Entities Using NSXMLParser and Core Data

I'm using NSXMLParser and Core Data to parse a feed and add/update entities using core data in my IPhone app.
The issue is that the feed contains new and update data, so once I parse the feed the following happens:
Create a new Entity
Populate the Entities Properties using NSXMLParser
In didEndElement, fetch entities already in the system with myEntityId equal to the Entity we parsed.
If there is more than 1 Entity, then delete the old ones as the feed passed us new data.
Save the Entity
My issue is that it seems like a lot of work to save update information, and the code also always creates a new record rather than just updating a current record.
Is there anyway that this process can be made simpler and avoid the need to create a new entity and delete the old one when doing an update?
My abbreviated code is as follows:
DidStartElement
- (void)parser:(NSXMLParser *)parser didStartElement...
{
if ([elementName isEqualToString:#"AnEntity"])
{
NSManagedObject *newEntity = [NSEntityDescription insertNewObjectForEntityForName:#"MyEntity" inManagedObjectContext:_context];
self.currentEntityObject = newEntity;
} else
{
if ([elementName isEqualToString:#"Title"] || [elementName isEqualToString:#"MyEntityId"])
{
self.currentProperty = [NSMutableString string];
}
}
}
DidEndElement
- (void)parser:(NSXMLParser *)parser didEndElement...
{
if (self.currentEntityObject)
{
if ([elementName isEqualToString:#"Title"])
{
[self.currentEntityObject setValue:self.currentProperty forKey:#"title"];
} else if ([elementName isEqualToString:#"MyEntityId"])
{
[self.currentEntityObject setValue:self.currentProperty forKey:#"myEntityId"];
} else if ([elementName isEqualToString:#"AnEntity"])
{
[self.currentEntityObject setValue:[NSDate date] forKey:#"lastUpdated"];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"MyEntity" inManagedObjectContext:_context];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(myEntityId = %#)", [self.currentEntityObject valueForKey:#"myEntityId"]];
[request setPredicate:predicate];
NSError *error = nil;
NSArray *array = [_context executeFetchRequest:request error:&error];
int countOfEntityId = array.count;
if (array != nil && countOfEntityId > 1)
{
// This is an update so remove old versions
for(int i=0; i < countOfEntityId; i++)
{
if(self.currentEntityObject != [array objectAtIndex:i])
{
[_context deleteObject:[array objectAtIndex:i]];
}
}
}
error = nil;
[_context save:&error];
self.currentEntityObject = nil;
}
}
}
FoundCharacters
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if (self.currentProperty)
{
[currentProperty appendString:string];
}
}
My issue is that it seems like a lot of work to save update information, and it also always creates a new record rather than just updating a current record.
Is there anyway that this process can be made simpler and avoid the need to create a new entity and delete the old one when doing an update?
Any advice would be great.
Thanks
Rich
I realize this is an old post but I'll answer anyways.
You should definitely check out Saul Mora's MagicRecord. He made it dead easy to use in any project, works with ARC/non-ARC automatically, and the setup of CoreData is a one liner.
First off I'll show you how I parse and update.
- (void)setUpBeforeParsing
{
self.currentAttributes = [NSMutableDictionary dictionary];
self.currentParsedCharacterData = [NSMutableString string];
self.currentParsedBatch = [NSMutableArray array];
self.attributesDictionary = myManagedObjectObject.entity.attributesByName;
}
- (void)parser:(NSXMLParser *)parser didStartElement...
{
for (NSString *attribute in self.attributesDictionary)
{
if ([elementName isEqualToString:attribute])
{
accumulatingParsedCharacterData = YES;
[self.currentParsedCharacterData setString:#""];
}
}
}
- (void)parser:(NSXMLParser *)parser didEndElement...
{
if ([elementName isEqualToString:#"myIdentifierThatObjectIsDone"])
{
[self.currentParsedBatch addObject:[self.currentAttributes copy]];
[self.currentAttributes removeAllObjects];
accumulatingParsedCharacterData = NO;
}
for (NSString *attribute in self.attributesDictionary)
{
if ([elementName isEqualToString:attribute])
{
accumulatingParsedCharacterData = NO;
[self.currentAttributes setObject:[self.currentParsedCharacterData copy] forKey:attribute];
}
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if (self.accumulatingParsedCharacterData) [self.currentParsedCharacterData appendString:string];
}
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
[MyCoreDataClass MR_importFromArray:self.currentParsedBatch];
}
Really the main thing to take from this is that you can build an array of dictionaries that carry values that you want to transfer to your managed objects. A guy named Tom Harrington wrote a demo on cimgf.com about naming your object's properties the same as the xml or json returned and then you can simply iterate through your properties until it matches the xml element returned. The beauty here is say somewhere down the line you want to save more of the returned xml to your objects, simply add a property to your object and the parser will automatically sync it.
At the end of parsing you will notice a class method called, this is from the MagicalRecord framework. As long as you set a 'relatedByAttribute' in the user info part of your data model then it will automatically sync the dictionaries to your managed objects. So if your objects have a unique identifying property called "MyEntityId" then in the user info dictionary of your entity set 'relatedByAttribute' - 'MyEntityId' and MagicalRecord takes care of it.
Let me know if you need any clarification.

Parsing NSXMLNode Attributes in Cocoa

Given the following XML file:
<?xml version="1.0" encoding="UTF-8"?>
<application name="foo">
<movie name="tc" english="tce.swf" chinese="tcc.swf" a="1" b="10" c="20" />
<movie name="tl" english="tle.swf" chinese="tlc.swf" d="30" e="40" f="50" />
</application>
How can I access the attributes ("english", "chinese", "name", "a", "b", etc.) and their associated values of the MOVIE nodes? I currently have in Cocoa the ability to traverse these nodes, but I'm at a loss at how I can access the data in the MOVIE NSXMLNodes.
Is there a way I can dump all of the values from each NSXMLNode into a Hashtable and retrieve values that way?
Am using NSXMLDocument and NSXMLNodes.
YES! I answered my own question somehow.
When iterating through the XML document, instead of assigning each child node as an NSXMLNode, assign it as an NSXMLElement. You can then use the attributeForName function, which returns an NSXMLNode, to which you can use stringValue on to get the attribute's value.
Since I'm bad at explaining things, here's my commented code. It might make more sense.
//make sure that the XML doc is valid
if (xmlDoc != nil) {
//get all of the children from the root node into an array
NSArray *children = [[xmlDoc rootElement] children];
int i, count = [children count];
//loop through each child
for (i=0; i < count; i++) {
NSXMLElement *child = [children objectAtIndex:i];
//check to see if the child node is of 'movie' type
if ([child.name isEqual:#"movie"]) {
{
NSXMLNode *movieName = [child attributeForName:#"name"];
NSString *movieValue = [movieName stringValue];
//verify that the value of 'name' attribute of the node equals the value we're looking for, which is 'tc'
if ([movieValue isEqual:#"tc"]) {
//do stuff here if name's value for the movie tag is tc.
}
}
}
}
There are two options. If you continue to use NSXMLDocment and you have an NSXMLNode * for the a movie element, you can do this:
if ([movieNode kind] == NSXMLElementKind)
{
NSXMLElement *movieElement = (NSXMLElement *) movieNode;
NSArray *attributes = [movieElement attributes];
for (NSXMLNode *attribute in attributes)
{
NSLog (#"%# = %#", [attribute name], [attribute stringValue]);
}
}
Otherwise, you can switch to using an NSXMLParser instead. This is an event driven parser that informs a delegate when it has parsed elements (among other things). The method you're after is parser:didStartElement:namespaceURI:qualifiedName:attributes:
- (void) loadXMLFile
{
NSXMLParser *parser = [NSXMLParser parserWithContentsOfURL:#"file:///Users/jkem/test.xml"];
[parser setDelegate:self];
[parser parse];
}
// ... later ...
- (void) parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqualToString:#"movie"])
{
NSLog (#"%#", [attributeDict objectForKey:#"a"]);
NSLog (#"%d", [[attributeDict objectForKey:#"b"] intValue]);
}
}