Fast XML parsing in iOS / Objective-C with TBXMLEx

Have you ever wondered which is the best way to parse a XML file in Objective-C / iOS? There are certainly a lot of options available to those who know where to lot at, but many of them are just awful to use: hard to configure, cryptic API, inexistent documentation and so forth.

Ray Wenderlich once wrote a post called “How To Choose The Best XML Parser for Your iPhone Project“, which greatly covers many XML parsers available to iOS, and was there that I discovered TBXML, which is by far one of the best parsers available to iOS. While TBXML is great, it’s “non-OO” API and some intolerance to bad formed XML had me wonder if there were anything I could do to make it better.

With that motivation, I created an extension to TBXML called “TBXMLEx” (TBXML with Extensions) which adds some syntax sugar on top of the original library and better handle bad XML files, all of that with a more OO-friendly interface.

The design goals for TBXMLEx are (taken for the original TBXML goals):

  • XML files conforming to the W3C XML spec 1.0 should be passable
  • XML parsing should incur the fewest possible resources
  • XML parsing should be achieved in the shortest possible time
  • It shall be easy to write programs that utilise TBXML
How to use it
Below is a quick example of how to use TBXMLEx:
#include "TBXMLEx.h"

NSString *xml = @"<files> \
    <file timestamp='1234567890' size='123' createdAt='01/01/20011'>file1.jpg</file> \
    <file timestamp='1234567890' size='8934'> \
        <name>file2.jpg</name> \
        <attributes> \
            <createdAt>01/01/2011 13:45:56</createdAt> \
            <owner>john</owner> \
        </attributes> \
    </file> \
</files>";

TBXMLEx *xml = [TBXMLEx parserWithXML:xml];

// "files" is the rootElement
if (xml.rootElement) {
    TBXMLElementEx *fileNode = 1;

    while ([fileNode next]) {
      // You can access the attributes through a dictionary
        NSDictionary *allAttributes = fileNode.attributes;
        NSLog(@"Timestamp: %@", [allAttributes objectForKey:@"timestamp"]);

        // Or you can have direct access to any specific attribute
        NSLog(@"Size: %d", [fileNode intAttribute:@"size"]);

        NSObject *createdAt = [fileNode attribute:@"createdAt"];
        NSString *filename = fileNode.value; // or fileNode.text

        if (!createdAt || !filename) {
            // Look for the properties someplace else
            TBXMLElementEx *nameNode = [fileNode child:@"name"];

            if (nameNode) {
                filename = nameNode.value;
            }

            TBXMLElementEx *attributesNode = [fileNode child:@"attributes"];

            // If an attribute does not exist it will simply return "nil", but nevertheless it's
            // always good check if it exists if you really need it
            if (attributesNode) {
                NSLog(@"Created at: %@", [attributesNode child:@"createdAt"].value); // Will not crash if attribute is nil
                NSLog(@"Owner: %@", [attributesNode child:@"owner"].value);
            }
        }

        NSLog(@"Filename: %@", filename);
    }
}

You can find more information about the project, as well the source code, at https://github.com/rafaelsteil/tbxmlex

2 thoughts on “Fast XML parsing in iOS / Objective-C with TBXMLEx

  1. Congratulations Steil. This is a very interesting XML parsing approach, but I really would like to know how do you think this solution can be used in a more dynamic way, I mean, without to hard coding the sought attributes?

  2. Hey Ricardo,

    do you have a more concrete example? In your comment you said about not hard coding the attributes names, is that right? Or what you really want to achieve is to parse the entire XML without knowing beforehand the *element* names?

    As of the attributes, you can use “NSDictionary *allAttributes = fileNode.attributes” and iterate over the keys. However, if what you really want is to parse the file without knowing the element names, I’ll have to expose such API. TBXML itself has this option, but my extension is hiding it yet. I can add that feature, if needed.

Leave a Reply

Your email address will not be published. Required fields are marked *

*


4 * = twenty eight

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>