Ipphones

  • Subscribe to our RSS feed.
  • Twitter
  • StumbleUpon
  • Reddit
  • Facebook
  • Digg

Thursday, 17 April 2008

Simplifying libxml

Posted on 10:09 by Unknown
As I mentioned in my previous post, XML handling on the iPhone is through the open source libxml library, which is a procedural C-based API. We can also use libxml in Cocoa, and if you have an eye toward re-using your code on the iPhone, it's probably not a bad idea to use libxml instead of NSXML. It also means I can show you how to use libxml without using the iPhone SDK and violating the NDA. 

To use libxml in your Cocoa projects, you just need to do one thing in your Xcode project settings, which is to add /usr/include/libxml2/** to your Header Search Paths build settings:
This will tell your project where to find the header files for libxml.

Now, to use libxml to parse XML data contained in an instance of NSString, say we had:
NSString *xml; // string containing XML
We need to make sure we import the necessary header file:
#import <libxml/xmlmemory.h>
Next, we have to tell the library to parse this data. Being a procedural C library, libxml knows nothing about NSString, which is an objective-C class class cluster, so we have to convert our NSString into a c string, like this:
xmlDocPtr doc = xmlParseMemory([xml UTF8String], [xml lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
If this was successful doc will not be NULL. Now, how do we get values from this? Well, we can get the root node like this:
xmlNodePtr root = xmlDocGetRootElement(doc);
xmlNodes are implemented as doubly linked lists, a construct that we don't use much in Objective-C, although it's likely used under the hood in the implementation of some of the collection classes. This abstraction is different from how we commonly work in Objective-C. Ordinarily, we have an object that represents the collection and we call methods on that collection object to get to the objects that it contains. In an old-school linked list like this, the xmlNode object pointed at by an xmlNodePtr represents both the node itself and the collection. Now, there is only going to be one root node in most situations but let's look at how we would get to the children of the root node.

It's actually pretty easy. We declare another node pointer and point it at the nodes's children like so:
xmlNodePtr node = root->children;
Now, the children pointer gives us a single node, but that node is also our access to all of the node's siblings and children. To iterate through all the nodes at this level, we can loop like this:
xmlNodePtr cur_node;
for (cur_node = node; cur_node; cur_node = cur_node->next)
{
 // Do something
}
This loop keeps going until it gets to the last item in the linked list. The last item has NULL as its pointer to next, so the loop stops. Similarly, we can loop through a node's children like this:
xmlNodePtr children;
for (children = node->children; children; children = children->next)
{
 // Do something
}
To get a node's name, we just look at the name member of the xmlNode struct, which is a c string. So, if we want to find a node with a specific name among a node's children, we would do it like this:
NSString *nameToSearchFor = @"Id";
xmlNode *child = NULL;
for (child = node->children; child; child = child->next)
{
if (strcmp((char *)child->name, [aName cStringUsingEncoding:NSUTF8StringEncoding])==0)
{
// Do something with the node
}
}
To determine the value of a node - the value between the begin and end tab in your XML like this: 
<node>value</node>
It's a little more complicated, but not much. To obtain its value as a string:
xmlChar *ret = xmlNodeListGetString(doc, node->children, 1);
Notice that we pass not the node, but the node's children pointer. This is because the text between the begin and end tags counts as a child.

At this point, I think you can see how mixing a procedural C API with Objective-C code looks a little ugly. On the other hand, I believe that Apple must have had good reason to not port NSXML to the iPhone, probably having to do with performance, but that is just conjecture on my part. So, how can we make our code look nicer without imposing significant additional overhead? 

Well, we can create a very low-overhead Objective-C wrapper. In the internals of the class, we use libxml for performance, but then convert to and from Objective-C objects in our accessors and mutators. This gives us a nice compromise between performance and readability, so our code can look like this without adding significant processing overhead:
 NKDLibXMLDocument *doc = [NKDLibXMLDocument documentWithRawXML:result];
NKDLibXMLNode *root = [doc rootNode];
NKDLibXMLNode *user = [root childNamed:@"User"];
NSLog(@"Id: %@", [user valueForChildNamed:@"Id"]);
NSLog(@"FirstName: %@", [user valueForChildNamed:@"FirstName"]);
NSLog(@"LastName: %@", [user valueForChildNamed:@"LastName"]);
Doesn't that look nicer? Isn't it easy to tell what's going on in that code? We hide all the nastiness away in a couple of classes and then never have to deal with it again. Yeah, that's the ticket.

I've still got some work to do on on the wrapper class, but I'll post it in the next day or two.
Email ThisBlogThis!Share to XShare to Facebook
Posted in iPHone, iPhone SDK, libxml, Objective-C | No comments
Newer Post Older Post Home

0 comments:

Post a Comment

Subscribe to: Post Comments (Atom)

Popular Posts

  • Making OpenGL ES Screenshot
    The Bit-101 Blog has an entry that shows how to take a screenshot when using OpenGL ES . I tested this in my much-delayed particle-generato...
  • Adding CLANG to Your Build Process
    Frasier Spiers has a nifty piece this morning on using Git pre-commit hooks to automatically run the CLANG Static Analyzer. I'm not a G...
  • CLANG Static Analyzer
    If you aren't using the LLVM/Clang Static Analyzer , you really should be. The Clang Project is an attempt to write a front end for the...
  • A Little Help
    I'm having a problem with OpenGL ES, and it's keeping me from finishing my particle engine post. I was hoping someone here could see...
  • WWDC Accommodations
    Staying downtown in San Francisco is very expensive in the summertime. Bu, if you're going to WWDC, you really want to stay downtown. Yo...
  • Xcode File Templates and a Mystery
    One of the things that confuses many newcomers to Xcode is how to set it up so that your company name gets automatically filled in when you ...
  • Brain Surgery?
    Craig Hockenberry has an interesting post on his blog today about the iPhone background processing issue. Craig speaks from personal experi...
  • Book's Almost Done
    I just finished Chapter 16. I'll give it another read-over in the morning then it will go off to my writing partner for his review, then...
  • iPhone Alley
    Looks like Dave and I are going to make an appearance on the iPhone Alley Podcast next week. We're recording on Sunday night, so I woul...
  • Shuffling Arrays
    Ever want to randomize an array of items? It's a task that, for some reason, I've had to do a lot in recent programs. So, I wrote a ...

Categories

  • 3D Models
  • Ad Hoc Distribution
  • ADC
  • Address Book
  • Amazon
  • Anaglyphs
  • App Store
  • Apple
  • Apple DTS
  • Apple Store
  • Application Store
  • articles
  • Award
  • Background Processing
  • Barcodes
  • Beta
  • Blog
  • Blogger
  • Blogging
  • Blogs
  • Blogspot
  • Book project
  • Bug Reporting
  • Captain Obvious
  • Categories
  • Censorship
  • CFFoundation
  • CGAffineTransform
  • Clang Static Analyzer
  • Cocoa
  • Cocoa Touch
  • Code Reuse
  • Code Signing
  • Computer
  • conferences
  • Controller Classes
  • Core Animation
  • Daring Fireball
  • Database
  • Debugging
  • Defect
  • Delegates
  • Design Awards
  • Developer Certifications
  • Discussion Forums
  • Edit Mode
  • employment opportunities
  • Encryption
  • Enterprise
  • Errata
  • free code
  • Free software
  • Full Screen
  • Game Programming
  • Gestures
  • Getting Started
  • goof
  • Google Code
  • Google Maps
  • Gotcha
  • Help
  • HIG
  • HTTP PUT
  • Idiots
  • Idle Timer
  • Images
  • Instruments
  • Interface Builder
  • iPHone
  • iPhone Applications
  • iPhone Dev Center
  • iPhone Developers
  • iPhone OS 3.0
  • iPhone SDK
  • iPhone SDK PNG
  • iPhone Simulator
  • iPhoneSDK
  • iPod
  • Job Opportunities.
  • k
  • Key Value Observing
  • Keynote
  • KVO
  • Landscape Mode
  • Learn Cocoa
  • Learn Cocoa on the Mac
  • libxml
  • Licensing
  • Mac Developers
  • Mac OS X
  • Macworld Expo
  • Microsoft
  • NDA
  • NeHe
  • New Category
  • New Release
  • NSFileHandle
  • NSMutableArray
  • NSMutableURLRequest
  • NSXML
  • Object-Oriented Design
  • Objective-C
  • Open Source
  • OpenGL ES
  • Optimizations
  • Other blogs
  • Paired Arrays
  • Parsing
  • Particle Engine
  • Party
  • PeopleSoft
  • Performance
  • Persistence
  • Pink Screen of Death
  • Piracy
  • Pixar
  • Podcasts
  • Press Release WTF
  • Press Releases WTF
  • private APIs Google
  • Project Template
  • Properties
  • Random Numbers
  • Rant
  • Rejected
  • Resources
  • Responder Chain
  • REST
  • Reverse Engineering
  • Rumors
  • Runtime
  • Sample Code
  • Screencast
  • screenshot
  • Scroll Views
  • snippet
  • Snow Leopard.
  • SOAP
  • Sockets
  • Source
  • Splash Screen
  • SQLite
  • SQLitePersistentObjects
  • Steve Jobs
  • Steve-Note
  • Strings
  • Stupidity
  • Subversion
  • Table Views
  • Taps
  • Template
  • Tip
  • Tips
  • Tririga
  • tutorials
  • Twitter
  • UIAlertView
  • UIColor
  • UIImage
  • UIPickerView
  • UIScrollView
  • UITextField
  • UIView
  • UIWebView
  • Update
  • Utilities
  • UUID
  • Vacation
  • Version Control
  • Web Services
  • Writing
  • WTF
  • WWDC
  • Xcode
  • XML

Blog Archive

  • ►  2009 (141)
    • ►  May (14)
    • ►  April (30)
    • ►  March (48)
    • ►  February (26)
    • ►  January (23)
  • ▼  2008 (163)
    • ►  December (46)
    • ►  November (25)
    • ►  October (44)
    • ►  September (2)
    • ►  August (5)
    • ►  July (2)
    • ►  June (9)
    • ►  May (2)
    • ▼  April (11)
      • The Dangers of Beta
      • Web Services Fun
      • Simplifying libxml
      • Web Services Fun
      • Golden Ticket
      • WWDC
      • Idiocy Can Come with Many Letters After Its Name
      • The Root of All Evil: Introduction to Optimizing O...
      • SDK Beta 3 is Out
      • You're Doing it Wrong! A Brief Discussion of Categ...
      • Pink Screen of Death
    • ►  March (17)
Powered by Blogger.

About Me

Unknown
View my complete profile