I am using the hpple plugin to parse and display html elements in my iphone app.
The problem i'm having is say there is a table on the webpage I am trying to parse, with several rows, (that may change from time to time). How do I go about getting the number of rows in this table, and iterating through each row and getting the different text content on each row. Is this possible with the hpple plugin?
Thanks in advance.
If all that want to do is count the rows in a table with class "tableClass" then you might try something like this
// Count the number of rows in a particular table
NSString *searchString = [NSString stringWithFormat:#"//table[#class='tableClass']/tr;
NSArray *tableRows = [xpathParser search:searchString];
NSInteger rows = [tableRows count];
NSLog(#"There are %d table Rows", rows);
// For loop to step through the rows
for(int j = 1; j <= rows; j++) {
searchString = [NSString stringWithFormat:#"//table[#class='tableClass']/tr[%d]/td", j];
NSArray *tableCells = [xpathParser search:searchString];
}
This should step through the table row by row and each time scrape the individual data cells (I didn't test it so there are no guarantees.) The problem with this is that it will be very slow if your table has more than a few rows.
You are better off just calling the table and scraping all the td cells at once from the table and then deciding how they make up the rows. This way is easy if the number of cells in a row stays constant.
Related
After finally figuring out how to pull data from google spreadsheets, I can't understand how to add new entries to the end of file.
Here's what I want to achieve:
My app should send some survey results to a google spreadsheet, here's how the file is supposed to look:
Let's assume that I need to send the next survey results to that spreadsheet. How do I send them and make sure that they appear just under the last survey results?
Thanks
UPDATE
I've found an answer long ago, so decided to update the question for lone rangers like me that couldn't find any info on this topic :)
For this answer I assume that you already know how to get to the spreadsheet's cells feed.
Here's what you need to do after you get the cells feed:
First of all we need to find out the last row number so we can later on write to the row under it.
NSArray * entries = [cellsFeed entries]; // we pull out all the entries from the feed
GDataEntrySpreadsheetCell * lastCell = [entries lastObject]; // then we take just the last one
NSString * title = [[lastCell title] stringValue]; // then we need it's title. The cells title is a combination of the column letter and row number (ex: A20 or B5)
NSString * lastRow = [[title componentsSeparatedByCharactersInSet:
[[NSCharacterSet decimalDigitCharacterSet] invertedSet]]
componentsJoinedByString:#""]; // then we remove the letters and we're left only with the row number
We can now send some data to the row under the last row like this:
// create a cell object and give it the row number (in our case it's the row under lastRow, so we add + 1), column number (yes, here you should provide a number and not a letter) and the string that you want to appear in the cell
GDataSpreadsheetCell * cell = [GDataSpreadsheetCell cellWithRow:[lastRow intValue] + 1 column:1 inputString:#"some value" numericValue:nil resultString:nil];
// create a cellEntry object that will contain the cell
GDataEntrySpreadsheetCell * cellEntry = [GDataEntrySpreadsheetCell spreadsheetCellEntryWithCell:cell];
// upload the cellEntry to your spreadsheet
[_srv fetchEntryByInsertingEntry:cellEntry
forFeedURL: [[workSheet cellsLink] URL] // make sure that you save the workSheet feed in an instance variable so that you'll be able to reach it in another method. If you pulled data from the spreadsheet that you must already know how to get the worksheet feed
delegate:self
didFinishSelector:nil];
That's it! The data should upload to your spreadsheet.
Let me know if you have any questions, I know the documentation is kinda scarce for this.
I have the following code in my search method that updates the tableview.
for (int x = 0; x < [array count]; x++) {
//network stuff here
self.searchedReservations = [aSearchObjectType objectsFromServerDictionaries:aResultsArray];
[self.aTableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade];
}
Each object in the array represent a section in my table, for most cases the count will be 4, so 4 sections.
Right now, the code is loading the same data for all sections in the table's cells. Instead of the unique data for each section of the table.
Here is the code that loads the cells. I'm missing some logic that maps the data to the right section of the table.
MyClass *object = [self.searchedReservations objectAtIndex:iIndexPath.row];
cell.textLabel.text = object.customerFullName;
I assume you have the code below in your 'cellForRowAtIndexPath' method:
MyClass *object = [self.searchedReservations objectAtIndex:iIndexPath.row];
cell.textLabel.text = object.customerFullName;
Tables are organised into sections, then within each section there are rows. The rows start at zero again for each section.
If you are on section 0, loading cell 0 this code above is not taking the section number into account, only the row number - so it is loading:
[self.searchedReservations objectAtIndex:0]
to populate the cell.
When you are on section 1, loading cell 0 in section one, you are retrieving exactly the same value because you are just using the row number. ie. you're still loading
[self.searchedReservations objectAtIndex:0]
You may think that you are changing the value of the 'searchedReservations' object between the loading of each section (this is what it looks like you're trying to do in the loop above) but I'm not sure that this is working (as the code the populate searchedReservation doesn't seem to do anything different in each loop counter). Also the first time the table loads it will run through all of the rows in all of the sections anyway.
I think you need to either use the indexPath.section field as well as the indexPath.row field at the time you are populating the cell to ensure you are setting the appropriate row in the appropriate section.
Also use the debugger to see whats going on in your cellForRowAtIndexPath method and in your loop and make sure that you are getting/using a different 'searchedReservations' object for each incrementation of the loop and that this matches the 'searchedReservations' object in the cellForRowAtIndexPath method.
hii every one in my iphone app i have a search screen & i have some entries in the search bar like sudha, tharanga and womens era (some magazines ) suppose if we search cricket special, it has to show the respective magazine
so i planned to have the table view data like follows
sudha (cricket special, anna hazare special)
tharanga (footbal special,x special)
womens era (some y special)
and while loading data to the table view by trimming the all data which is present between the brackets ( ) and should i display remaining in the table view
so how can i trim the string in such a way that it should remove the data with in brackets and bracket symbols
so that my table view data should become like this
sudha
tharanga
womens era
, thanx in advance
Regarding trimming the string as per your requirement, I guess the simplest way to go about it is to use the - (NSArray *)componentsSeparatedByString:(NSString *)separator method as follows;
NSArray *anArray = [theFullString componentsSeparatedByString:#"("];
Assuming theFullString = #"womens era (some y special)", the resulting arrays first element would be as #"womens era ". I assume this works fine.
Use this nnstring method to get the desired result,
- (NSString *)substringWithRange:(NSRange)range;
OR you can do that, first find bracket location,
int pointPos = -1;
for(int i=0; i<= [myString length]-1; i++){
if ([myString characterAtIndex:i] == '(') {
pointPos = i;
break;
}
}
NSString *finalString = [myString substringToIndex:pointPos];
I am working on a small isometric engine for my next iPhone game. To store the map cells or tiles I need a 2 dimensionel array. Right now I am faking it with a 1-dimensionel, and it is not good enough anymore.
So from what I have found out looking around the net is that in objective-c I need to make an array of arrays.
So here is my question: How do I dynamicly create arrays at runtime based on how many map-rows I need?
The first array is easy enough:
NSMutableArray *OuterArray = [NSMutableArray arrayWithCapacity:mapSize];
now I have the first array that should contain an array for each row needed.
Problem is, it can be 10 but it can also be 200 or even more. So I dont want to manually create each array and then add it. I am thinking there must be a way to create all these arrays at runtime based on input, such as the chosen mapsize.
Hope you can help me
Thanks in advance
Peter
I think this previous question should help.
2d arrays in objective c
Nothing to do with me. I have never owned an iphone or tried to write code for one.
The whole point of NSMutableArray is that you don't care. Initialize both dimensions with an approximate size and then add to them. If your array grows beyond your initial estimate the backing storage will be increased to accomodate it. This counts for both your columns (first order array), and rows (second order array).
EDIT
Not sure what you meant in your comment. But this is one way to dynamically create a 2-dimensional mutable array in Objective-C.
NSUInteger columns = 25 ; // or some random, runtime number
NSUInteger rows = 50; // once again, some random, runtime number
NSMutableArray * outer = [NSMutableArray arrayWithCapacity: rows];
for(NSUInteger i; i < rows; i++) {
NSMutableArray * inner = [NSMutableArray arrayWithCapacity: columns];
[outer addObject: inner];
}
// Do something with outer array here
NSMutableArray can hold as many elements as you want to add to it. (Based on available heap though).
All you have to do is when you want to add an element(Array) to this mutable array you can add it using the addObject method.
So you create a MutableArray as follows:
NSMutabaleArray *outerArray = [NSMutableArray array]; // initially contains 0 elements.
[outerArray addobject:<anotherArray>];
From your rejection of the other answers I think you don't know how to add them in a loop, or am I wrong?
Try:
for (i = 0; i < mapSize; i++)
[outerArray addObject: [[NSMutableArray alloc] init]];
or, if you know or can estimate the size of the second dimension:
for (i = 0; i < mapSize; i++)
[outerArray addObject: [[NSMutableArray alloc]
initWithCapacity: your_2nd_d_size]];
Now, how you fill the arrays, i.e. where you get the contents depends on you. In one or more loops, you do:
[(NSMutableArray *)[outerArray objectAtIndex: i]
addObject: your_current_object];
I have a array (resultArray) which has 21 items of data in it. I want to display it in a 8 sectioned table with different row counts.
How to assign the value properly in all row? Both indexpath.row and section.row gives wrong values. How to assign a single array value to grouped table with more section?
It's up to you to map your data model to the table view, and you can do it any way that you want. If you have a flat array of items and want to map them into different sections of the table view, you'll have to know which offsets of the result data go into which sections of the table, but no one can do that for you automatically, because only you know the semantics of the data. You need some code that takes the section and row index and figures out which index into the results array needs to be returned.
If it's always 21 items and always the same mapping, then hardcoding the mapping in a table or a big bunch of if statements is probably fine. If it's dynamic then you'd need some other lookaside mapping table, depending on how you wanted to map.
Finally, as #iPortable suggests, you could also find a way to structure your results data appropriately, which makes the controller logic simple, depending on your data.
I would create a multi layer array for this. The first level would be the section count and the second level the row. The array would look something like this:
resultArray{
1 = {
1 = first row in first section,
2 = second row in first section
},
2 = {
1 = first row in second section,
2 = second row in second section
}
}
then you get the value from the array in your cellForRowAtIndexPath: as follows:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSArray *sectionArray = [returnArray objectAtIndex:indexPath.section];
cell = [sectionArray objectAtIndex:indexPath.row];
}