macdevcenter.com
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Keynote's XML Connections
Pages: 1, 2

The Problem

So now that I've gone ahead and stated how easy it is to create a Keynote presentation purely through code, I'll walk through the process of doing so. As a bit of a music buff, I like to keep tabs on what kinds of music I'm listening to at a glance. But doing so through the iTunes interface requires too much effort. Instead I want to automatically generate the information so I can spend my time in other ways. Luckily most of the work is already done: using MyTunes, I've already placed my music library into a MySQL database. Now I'll supply the information to Keynote, and let the application do the heavy lifting to produce the result.

The Boring Part

As usual, the first thing we have to do is make sure we have the tools required for the job. For this tutorial, I'll use Java and the Apache Software Foundation's Xerces XML parser, which is freely available here, in addition to MySQL's JDBC driver, available here. You'll also need your iTunes music library information to be stored in a MySQL database (which can be done with MyTunes, available here). Refer to my previous article "Using Java to Expand iTunes Functionality" to get it up and running. The final step is to download the template presentation file and the Java class that will fill in the blanks for us, both of which are available here.

The Solution

Expand the archive, and open up the presentation.apxl in a text editor, and scroll down to the part of the file that appears as follows:

The template that we'll use for our own presentation
The template that we'll use for our own presentation

The highlighted tag is the needle that we'll look for in the haystack, while the tags that are commented-out illustrate how we'll have to format our data so that it will be presented in the graph. To make this easy, we'll parse the information using SAX. Whereas DOM makes the information in the document available in a hierarchical tree structure, SAX provides it on an as it becomes available basis, as the parser works through the document from beginning to end. So when we're parsing the document and come across the <mytunesChart /> tag, we'll replace it with the information for the columns in our graph. For all other tags, we'll simply echo them to the stream to be printed. The following snippet of code does exactly what we want:

// invoked when the parser encounters an
// opening tag; we're looking for the tag
// whose name local name is "mytunesChart"
public void startElement(String uri, String loc,
  String q, Attributes atts)
  throws SAXException {

  buffer = new StringBuffer();

  // if this tag is NOT what we're looking for...
  if (! localName.equals("mytunesChart")) {

    // open the tag
    buffer.append("<").append(qName);

    // add all the attributes of the tag
    for (int i = 0; i < atts.getLength(); i++) {
      buffer.append(" ");
      buffer.append(atts.getQName(i));
      buffer.append("=").append("\"");
      buffer.append(atts.getValue(i));
      buffer.append("\"");
    } 

    // add the namespace info, if any exists
    if (! ns.toString().equals("")) {
      buffer.append(ns.toString());
    } 

    // close the tag, and print to the stream
    buffer.append(">");
    this.writer.print(buffer.toString());

  // this is the key that we're looking for,
  // so we'll spit out our column info
  } else {

    // change the items in [] to match your
    // database connection parameters
    Connection con = DriverManager.getConnection(
      "jdbc:mysql://" + [host] + "/" + [db name]
      + "?user=" + [username] + "&password=" +
      [password]);

    Statement stmt = con.createStatement();
    ResultSet rs = stmt.executeQuery(
      "select DISTINCT(trackGenre), COUNT(*) " +
      "as trackCount FROM Tracks " +
      "GROUP BY " + trackGenre");

    // while there's another genre...
    while (rs.next()) {

      String genre = rs.getString("trackGenre");
      int count = rs.getInt("trackCount");

      // make sure the genre has been specified
      // note: you will have to encode an "&"
      // to "&amp;" if any of your genres
      // contain an ampersand
      if (genre != null) {
        buffer.append("<array>\n");
        buffer.append("<string>");
        buffer.append(genre);
        buffer.append("</string>\n");
        buffer.append("<number>");
        buffer.append(count);
        buffer.append("</number>\n");
        buffer.append("</array>\n");
      }
    }

    this.writer.println(buffer.toString());
  }
}

Run the class with the command

javac MyTunesChart; java MyTunesChart template.key

Upon the class' completion, there should be a new Keynote document in the directory named mytunes.key. Open it in Keynote, and you should see something similar to the following:

The result of our work
The result of our work

It's important to note that the template file itself can't be opened in Keynote. While this seems a bit odd, remember that by inserting the key in the APXL file, the document no longer validates against the schema. However, once our Java class processes the template, this tag will be replaced with data that will make the output file validate.

Closing Tag

One of the major attractions in using applications on the Mac is in creating an automated workflow, in which one or more applications are glued together to pass information and commands between themselves. We've now seen how it is possible to accomplish the feat with XML in the absence of AppleScript. And since XML bindings are available for most programming languages, you are free to use any language that you are comfortable with, whether it's Java, Objective-C, C/C++, Ruby, Perl, PHP, or another.

Apple is actively promoting Keynote to developers as a tool to serve as the presentation medium for applications. If you are interested in finding out more information, there are several resources on the ADC site to assist developers who are considering integrating Keynote with their applications:

  • technical notes regarding the APXL format, available here and here,
  • a mailing list for developers who are creating Keynote tools,
  • and a sample program that creates a presentation from scratch.

While there currently aren't any standard applications that incorporate Keynote presentation capabilities, it should be interesting to see what happens in the near future now that the application has established its audience.

David Miller is combining his passions of photography and working on the web at iStockphoto; when not hacking away with a text editor and a few web browsers in hand, he can be seen huddled over his laptop tweaking levels and curves for his freelance photography. Keep track of David's latest projects over at his home on the web.


Return to the Mac DevCenter