iHarder.net

XMLTree

Support This Project

Wrapping Apple's Own XML Parser

Download now! (51KB)

Follow the file release RSS feed...

Introduction

XML Tree provides an Objective-C wrapper for Apple's own C-language XML parser provided in Mac OS X. I much prefer working with Objective-C, so I was bothered to learn Apple didn't provide an Objective-C API (and if they do I'll be happy to label XMLTree obsolete).

It's a work in progress meaning there are a lot of functions that Apple provides at the C-language level that I have not yet wrapped in a useful Objective-C way, but you can at least access basic element and attribute information for now.

I've released this code into the Public Domain, so you don't have to worry about licensing or whatnot if you use it in your programs. Heck, I didn't even write the hard stuff: Apple did that! If you make any useful changes, I'd sure appreciate it if you'd send them back to me so I can add them to a new release for everyone.

Example

Let's work with a sample XML document. Let's say this XML document is available at some URL, maybe by a SOAP call or maybe it's just a document on the web. I've applied some formatting to (hopefully) make it easier to read.

<?xml standalone="yes" version="1.0" ?>
<Book ISBN="1234567890">
 <Title>How to Get People to Send you $20 for a Book</Title>
 <Author>John Doe</Author>
 <Chapters>
  <Chapter sequence="1">It was a dark and stormy night...</Chapter>
  <Chapter sequence="2">The Dilbert Principle maintains...</Chapter>
 </Chapters>
</Book>

Here's how I would get this document, assuming the document is at the given URL:

NSURL *theURL = [NSURL URLWithString:@"http://www.example.com/books?ISBN=1234567890"];
XMLTree *tree = [[[XMLTree alloc] initWithURL:theURL] retain];

Don't forget that you can access files as URL's too like so:

NSURL *theURL = [NSURL fileURLWithPath:@"/Users/foo/TheBook.xml"];
XMLTree *tree = [[[XMLTree alloc] initWithURL:theURL] retain];

I now have an XMLTree that represents the entire XML document. If I called [tree type] it would return a value of 1 which corresponds to kCFXMLNodeTypeDocument. What is that? It's one of the predefined values that is available to you (and you didn't even know it!). The actual Apple-defined structure is this:

enum CFXMLNodeTypeCode {
    kCFXMLNodeTypeDocument = 1,
    kCFXMLNodeTypeElement = 2,
    kCFXMLNodeTypeAttribute = 3,
    kCFXMLNodeTypeProcessingInstruction = 4,
    kCFXMLNodeTypeComment = 5,
    kCFXMLNodeTypeText = 6,
    kCFXMLNodeTypeCDATASection = 7,
    kCFXMLNodeTypeDocumentFragment = 8,
    kCFXMLNodeTypeEntity = 9,
    kCFXMLNodeTypeEntityReference = 10,
    kCFXMLNodeTypeDocumentType = 11,
    kCFXMLNodeTypeWhitespace = 12,
    kCFXMLNodeTypeNotation = 13,
    kCFXMLNodeTypeElementTypeDeclaration = 14,
    kCFXMLNodeTypeAttributeListDeclaration = 15
};

This tree that we just read in has two children: The <?xml ...?> processing instruction and the tree starting with the <Book...> element.

You could get the processing instruction alone as its own XMLTree and the rest of the document as its own XMLTree like this:

XMLTree *piTree   = [tree childAtIndex:0];
XMLTree *bookTree = [tree childAtIndex:1];

Now we could get the book's ISBN number (of course we already knew it, right?) like so:

NString *isbn = [bookTree attributeNamed:@"ISBN"];

There's an easier way to get to basic components of your XML document though. It's the descendentNamed: method. Skipping the piTree and bookTree steps, we could get the ISBN this way:

NSString *isbn = [[tree  descendentNamed:@"Book"] attributeNamed:@"ISBN"];

Similarly we could jump straight to the author this way:

NSString *author = [tree  descendentNamed:@"Author"];

Note that descendentNamed: (and childNamed:) returns the first match, and descendentNamed: performs a depth-first search, so a search for "Chapter" would return the dark and stormy night chapter:

NSString *firstChapter = [tree  descendentNamed:@"Chapter"];

Known Shortcomings

This is just my second release of XMLTree, so there are a lot of functions that Apple's C-language XML parser supports that XMLTree does not yet support. Basically XMLTree only provides basic access to elements and attributes. As I go along, I'll be adding support for other things like Processing Instructions and whatnot. If you make any useful changes, I'd appreciate it if you would share them with the rest of us and send your changes to me, but it's Public Domain so do whatever you want with it.

Change Log

v0.2.1
Thanks to Tom Butterworth for finding some (many) leaks and fixing them.
v0.2
I forget what's been added since the first release. I think we added some more child-access methods and we've begun work on an xpath-access method, but that's not complete. There are also some more ways to create XMLTrees.
v0.1
First Release.

Apple's Parser

For more information on Apple's C-language XML parser, try this link:

http://developer.apple.com/techpubs/macosx/CoreFoundation/XMLServices/XML_Services/index.html

A Note About Public Domain

I have released this software into the Public Domain. That means you can do whatever you want with it. Really. You don't have to match it up with any other open source license &em; just use it. You can rename the files, do whatever you want. If your lawyers say you have to have a license, contact me, and I'll make a special release to you under whatever reasonable license you desire: MIT, BSD, GPL, whatever.