Given this XML structure from (http://localhost:3000/route.xml):
<objects type="array">
<object>
<trip0>
<departure>20:01</departure>
<start>Place a</start>
<end>Place b </end>
<arrival>20:16</arrival>
<how>Walking</how>
</trip0>
</object>
<object>
<trip1>
<departure>20:16</departure>
<start>Place b</start>
<end>Place c </end>
<arrival>20:32</arrival>
<how>By car</how>
</trip1>
</object>
</objects>
Using the following Objective-C code:
implementation of view
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// URL localhost for testing purposes
NSURL *url = [[NSURL alloc] initWithString:@"http://localhost:3000/route.xml"];
// Init parser
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
[xmlParser setDelegate:self];
//Start parsing the XML file.
BOOL success = [xmlParser parse];
if(success)
NSLog(@"No Errors");
else
NSLog(@"Errors !!!!!!!!E!!!");
}
#pragma mark XMLParser delegate
- (void)parserDidStartDocument:(NSXMLParser *)parser
{
NSLog(@"Document started", nil);
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict {
if([elementName isEqualToString:@"trip0"]) {
//Initialize the array.
NSLog(@"Found trip0 !");
}
NSLog(@"Processing Element: %@", elementName);
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
NSLog(@"Processing Value: %@", string);
}
I’m able to get this as output :
2011-11-16 19:34:06.006 SandboxTabBar[11754:11603] Processing Element: objects
2011-11-16 19:34:06.008 SandboxTabBar[11754:11603] Processing Value:
2011-11-16 19:34:06.009 SandboxTabBar[11754:11603] Processing Element: object
2011-11-16 19:34:06.009 SandboxTabBar[11754:11603] Processing Value:
2011-11-16 19:34:06.010 SandboxTabBar[11754:11603] Found trip0 !!
2011-11-16 19:34:06.010 SandboxTabBar[11754:11603] Processing Element: trip0
2011-11-16 19:34:06.011 SandboxTabBar[11754:11603] Processing Value:
2011-11-16 19:34:06.011 SandboxTabBar[11754:11603] Processing Element: departure
2011-11-16 19:34:06.012 SandboxTabBar[11754:11603] Processing Value: 20:01
2011-11-16 19:34:06.012 SandboxTabBar[11754:11603] Processing Value:
2011-11-16 19:34:06.013 SandboxTabBar[11754:11603] Processing Element: start
2011-11-16 19:34:06.013 SandboxTabBar[11754:11603] Processing Value: Place a
2011-11-16 19:34:06.014 SandboxTabBar[11754:11603] Processing Value:
2011-11-16 19:34:06.015 SandboxTabBar[11754:11603] Processing Element: end
2011-11-16 19:34:06.015 SandboxTabBar[11754:11603] Processing Value: Place b
2011-11-16 19:34:06.207 SandboxTabBar[11754:11603] Processing Value:
2011-11-16 19:34:06.208 SandboxTabBar[11754:11603] Processing Element: arrival
2011-11-16 19:34:06.209 SandboxTabBar[11754:11603] Processing Value: 20:16
2011-11-16 19:34:06.210 SandboxTabBar[11754:11603] Processing Value:
2011-11-16 19:34:06.211 SandboxTabBar[11754:11603] Processing Element: how
2011-11-16 19:34:06.212 SandboxTabBar[11754:11603] Processing Value: walking
2011-11-16 19:34:06.213 SandboxTabBar[11754:11603] Processing Value: 15 min
2011-11-16 19:34:06.214 SandboxTabBar[11754:11603] Processing Value:
2011-11-16 19:34:06.215 SandboxTabBar[11754:11603] Processing Value:
2011-11-16 19:34:06.216 SandboxTabBar[11754:11603] Processing Value:
2011-11-16 19:34:06.217 SandboxTabBar[11754:11603] Processing Element: object
2011-11-16 19:34:06.218 SandboxTabBar[11754:11603] Processing Value:
2011-11-16 19:34:06.219 SandboxTabBar[11754:11603] Processing Element: trip1
2011-11-16 19:34:06.220 SandboxTabBar[11754:11603] Processing Value:
2011-11-16 19:34:06.221 SandboxTabBar[11754:11603] Processing Element: departure
2011-11-16 19:34:06.222 SandboxTabBar[11754:11603] Processing Value: 20:32
2011-11-16 19:34:06.223 SandboxTabBar[11754:11603] Processing Value:
2011-11-16 19:34:06.221 SandboxTabBar[11754:11603] Processing Element: start
2011-11-16 19:34:06.222 SandboxTabBar[11754:11603] Processing Value: Place b
2011-11-16 19:34:06.223 SandboxTabBar[11754:11603] Processing Value:
And so on …
I want to populate UITableviews with content like this:
“Trip 0’s depature is at 20:01 from Place A to Place b and arrived on 20:16 by walking.”
and
“Trip 1’s departure is at 20:16 from Place b to Place c and arrived on 20:32 by car”
There must be an easier way to select and combine the nodes that I need from the XML file.
How to achieve such a result with the given XML file?
A DOM parser makes things much easier for things like this, but it does mean (a) choosing a library that supports DOM on iOS, figuring out how it works, its idiosyncrasies, etc and (b) having the whole XML document in memory before you parse it out and populate your table model. Neither of those is a big deal for many cases, but sometimes memory concerns may force you away from DOM.
If you want to avoid these potential problems for your app, it isn’t that hard to implement what you want using NSXMLParser. To start, define a class that represents a “Trip” and give that class the properties you want for each trip (start, end, arrival, etc). Then in your parser delegate class define a few ivars for holding a mutable array of Trip objects, a “currentTrip” object that you can populate as you go, and a mutable character buffer you can use to capture characters scanned by the parser.
With those in place you can implement something like the following in your parser delegate logic:
This is just the basic code structure you want, not necessarily optimized. In particular, I haven’t included any releases to avoid memory leaks, which you would need if you aren’t using ARC. Also, I’ve created a new characterBuffer object at the beginning of each element that could include text you care about: This might be done more intelligently with a little more care and thinking. You get the idea though.
Taken as a whole, this approach can be a little tedious but it also is not hard and it can perform quite a bit better than DOM parsing in some cases, if that’s something that is a factor for you app.