views:

137

answers:

2

In my application i parse a xml from which I get a list of items (hotels and restaurants) that i put into array "listElements"; I need to get from this array, another array that will contain only the particular elements (hotels only) and then I need to get from this array, three array that will contain hotels according to stars(array5starhotel, array4starhotel,array3starhotel). How can do this? This is the code I used for parsing(I used TBXML):

- (void)loadCategories {
    // instantiate an array to hold categories objects
    listCategories = [[NSMutableArray alloc] initWithCapacity:100];

    tbxml = [[TBXML tbxmlWithXMLFile:@"Molise.xml"] retain];

    // Obtain root element
    TBXMLElement * root = tbxml.rootXMLElement;

    // if an author element was found
    if (root) {
      //search for the first category element within the root element's children
      TBXMLElement * category = [TBXML childElementNamed:@"category" parentElement:root];

      // if a category element was found
      while (category != nil) {

        // instantiate a category object
        Category * aCategory = [[Category alloc] init];

        // get the name attribute from the category element
        aCategory.name = [TBXML valueOfAttributeNamed:@"name" forElement:category];

        // search the category's child elements for a "element" element
        TBXMLElement * element = [TBXML childElementNamed:@"element" parentElement:category];

        // if a "element" element was found     
        while (element != nil) {                              

          // instantiate a "element" object
          Element * aElement = [[Element alloc] init];

          // extract the attributes from the "element" element
          aElement.title = [TBXML valueOfAttributeNamed:@"title" forElement:element];
          aElement.address = [TBXML valueOfAttributeNamed:@"address" forElement:element];          
          aElement.stars =[TBXML valueOfAttributeNamed:@"stars" forElement:element];

          // add the "element" object to the category's listElements array and release the resource       
          [aCategory.listElements addObject:aElement];
          [aElement release];

          // find the next sibling element named "element"
          element = [TBXML nextSiblingNamed:@"element" searchFromElement:element];
        }

        // add our category object to the listCategories array and release the resource  
        [listaCategories addObject:aCategory];
        [aCategory release];

        // find the next sibling element named "category"
        category = [TBXML nextSiblingNamed:@"category" searchFromElement:category];
      }                      

      [tbxml release];
    }
A: 

OK, so your code snippet doesn't do what the question says it does.

You make an array of categories (listCategories) containing lots of Category objects. Each of these contains a listElements array.

Assuming that you want the items from the 'hotels' category . . .

// Get the hotels category
Category *hotelsCategory = nil;
for (Category *temp in listCategories.each) {
  if ([temp.name isEqualToString:@"hotel"]) {
    hotelsCategory = temp;
    break;
  }
}
if (nil == hotelsCategory)
  return NSLog(@"No hotels category found");

// Get the hotels from this category with a 3 or above star rating
NSMutableArray *array5starhotel = [NSMutableArray array];
NSMutableArray *array4starhotel = [NSMutableArray array];
NSMutableArray *array3starhotel = [NSMutableArray array];
for (Element *element in hotelsCategory.listElements) {
  if ([element.stars isEqualToString:@"5"])
    [array5starhotel addObject:element];
  if ([element.stars isEqualToString:@"4"])
    [array4starhotel addObject:element];
  if ([element.stars isEqualToString:@"5"])
    [array3starhotel addObject:element];
}

Hope that helps - I've had to guess at some stuff because I don't know what's in a Category or Element object!

deanWombourne
I'll explain better in the class Category are instantiated a string "name" (category.name) and an array listElement (category.listElement); in the class Element are instantiated three strings: title, description, stars (element.title, element.stars element.description.) The reason why I asked how to make the three arrays is that when I click on the hotel category I need to display the hotels according to stars in three different section of a tableView
Claudio
OK, the second part of my code will go through a single Category object and get the three arrays that you want.
deanWombourne
dean i have a problem with your code, in three array is loaded always the same hotel (the first of XML tree),in fact in the three sections of the table view I get the same hotel when they should appear three different
Claudio
after many problems, finally it works
Claudio
A: 

NSArrays [filteredArrayUsingPredicate:][1] is the tool for the job.

As noted, your listCategories array will contain an array of Category objects with each category containing an array of Element objects.

// Retrieve "hotel" Elements 

NSPredicate *hotelPredicate = [NSPredicate predicateWithFormat:@"name == hotel"];
Category *hotelCategory = [[[listCategories filteredArrayUsingPredicate:hotelPredicate] objectAtIndex: 0] retain];

NSArray *hotels = [[hotelCategory listElements] retain];

// Split the array of Elements based on star value
NSPredicate *elementRatingTemplate = [NSPredicate predicateWithFormat:@"stars == $STARS"];

NSPredicate *threeStarPredicate = [elementRatingTemplate predicateWithSubstitutionVariables: [NSDictionary dictionaryWithObject:@"3" forKey:@"STARS"];

NSArray *threeStarHotels = [[hotels filteredArrayUsingPredicate: threeStarPredicate] retain]; 

NSPredicate *fourStarPredicate = [elementRatingTemplate predicateWithSubstitutionVariables: [NSDictionary dictionaryWithObject:@"4" forKey:@"STARS"];

NSArray *fourStarHotels = [[hotels filteredArrayUsingPredicate: fourStarPredicate] retain]; 

NSPredicate *fiveStarPredicate = [elementRatingTemplate predicateWithSubstitutionVariables: [NSDictionary dictionaryWithObject:@"5" forKey:@"STARS"];

NSArray *fiveStarHotels = [[hotels filteredArrayUsingPredicate: fiveStarPredicate] retain]; 

// Do something with the filtered arrays
// Clean up retained objects.
falconcreek
falcon, the compiler gives me various errors with this code
Claudio
can you post them? SO isn't a great compiler.....
falconcreek
NSPredicateTemplate doesn't exist, NSArray may not respond to listElements, error: expected ':' before 'token' and confused by earlier errors, bailing out after NSArray *threeStarHotels
Claudio
updated. fixed the type errors
falconcreek
thanks now I try if it worksI was going to put this code at the end of parsing before [tbxml release];then i recover the hotels from the array, in view controller
Claudio
The first predicate was incorrect. I have updated to @"name == hotel"
falconcreek
i found another solution, but thank you very much for your help!!
Claudio