Parsing XML in Cocoa
Asked Answered
I

1

20

Today I am looking into how to make a simple XML parser in Cocoa (for the desktop). I am thinking of using NSXMLParser to parse the data, but am not quite sure where to start. The XML file on the web doesn't have the much data in it, just a simple listing with a few things that I need to save into a variable. Does anyone have any suggestions on how to do this, as the online documentation about this isn't making too much sense.

Thanks for any help!

EDIT The reason why I am wanting to create an XML parser is to get information from a MYSQL database on a server to the client application. If there is some better way to do this besides a XML parser, please let me know!

Ison answered 6/7, 2009 at 23:53 Comment(3)
what doesn't make sense in the online documentation?Earthaearthborn
I'm not just sure what I should override in order to make it work.Ison
There's nothing to override. You make a separate object and appoint it the parser's delegate. In that object, you respond to certain messages (some required, some optional) that tell you what the parser has found.Cott
E
51

Here's how it works:

There's a class called NSXMLParser. It's used to parse XML files. However, NSXMLParser is stupid. All it knows how to do is parse XML, but it doesn't know what it's supposed to do with the information it finds.

Enter a delegate. A delegate is like a nanny. Since the XMLParser doesn't have a clue what to do with the information it finds, it goes and asks its delegate about each and every thing: "Hey! I started parsing a document! Am I supposed to do anything?" "Hey! I found some CDATA! What am I supposed to do with it!" "Hey! I found another tag!" "Hey! I found a closing tag!", and so on. All of these "Hey!" statements are delegate methods, or in other words, they are optional methods that a delegate object may choose to implement. Usually (but not always), the object that creates the NSXMLParser is also the delegate, but that doesn't have to be the case.

So you might have something like this:

NSXMLParser * parser = [[NSXMLParser alloc] initWithContentsOfURL:someURLToAnXMLFile];
[parser setDelegate:self];
[parser parse];
[parser release];

Then in that same object (self), you might have some of these methods:

- (void)parserDidStartDocument:(NSXMLParser *)parser {
  //the parser started this document. what are you going to do?
}

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict {
  //the parser found an XML tag and is giving you some information about it
  //what are you going to do?
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
  //the parser found some characters inbetween an opening and closing tag
  //what are you going to do?
}

- (void)parserDidEndDocument:(NSXMLParser *)parser {
  //the parser finished. what are you going to do?
}

There are a whole bunch of these methods listed in the documentation. Simply go to the NSXMLParser class reference, and they're all listed under the "Delegate Methods" section. Once you get the hang of it, NSXMLParser is pretty easy to use. It is a SAX Parser, which means it's event-driven parser. It finds stuff, and it tells you about it.

Ellyellyn answered 7/7, 2009 at 3:1 Comment(12)
Thanks Dave: Really helpful! And, for the future, would you recommend using XML or MYSQL for database/client communications?Ison
I'd probably use both. If I needed a client-server connection, and I controlled both ends, I'd probably keep the data in a MySQL database, then access it with some PHP scripts that spit out the appropriate data that's formatted as XML (Plist XML specifically, so I could do things like NSArray * myArray = [NSArray arrayWithContentsOfURL:urlToMyPHPScript];)Ellyellyn
@Dave How would I format XML as a PLIST, and would that mean that I could just make a NSDictionary and sort through like that? I have also been trying some stuff with NSXMLParser, and am wondering how you would suggest using the commands that you posted above to associate the element and the found characters. For instance, you know that "Some description" is in the element "Description". Thanks for all your help.Ison
@PF1 to get the idea of the plist format, open up a .plist file in ~/Library/Preferences. Then just have a PHP script that pulls stuff out of your DB and echos text that looks like a plist. If you want a specific example, you can contact me directly. =)Ellyellyn
@Dave Just looked at some PLIST files - Doesn't seem to have too much of a difference to regular XML. And as far the PHP part, seems pretty simple (I knew PHP before I learned Cocoa). :) If I have any other questions/want examples, I'll either post here or drop you an email.Ison
@Dave I was just playing around with NSXMLParser. But unfortunately, I still can't figure out how to associate the element and the found string with the contents of the elements. For instance, you know that "Some description" is in the element "Description". Thanks again for all your help!Ison
@PF1 got your email, am really busy today & tomorrow. I'll respond soon, I promise!Ellyellyn
@Dave Totally fine, no pressure. I just also wanted to post here in case some spam filter blocked my email. Believe me, it happens.Ison
Also Dave, if it isn't possible to do what I was saying, is there some way to change the names of the methods (ex. parserDidEndDocument1 and parserDidEndDocument2) and call these depending on what XML document you are calling?Ison
Great description of delegates. I was wondering why you [parser autorelease] instead of [parser release]?Chetnik
@nevan - i was under the impression that NSXMLParser would spawn a thread for parsing, but a quick test shows that to be incorrect.Ellyellyn
NSXMLParser is fine for shallow xml documents, like the example. When you have xml nested several levels deep, it becomes a nightmare -- I'm talking from experience here. NSXMLParser smashes the xml puzzle to pieces, then hands them to you one by one. Here's an element 'w="3"', now what is this referring to again? A width of 3? Or a training that starts in week three? So, you have to keep track of the current node, its parents and any groups it may belong to. That may be doable at 3 or 4 levels deep, but beyond that the administrative overhead overwhelms any advantages NSXMLParser offers.Ensure

© 2022 - 2024 — McMap. All rights reserved.