OmniGraffle XML to HTML

There are times when people will use a tool with a graphical user interface (GUI) such as OmniGraffle that provides an easy way to create an illustration of a complex structure such as a site map for a website. The output can be a file such as a PDF. It turns out that this PDF file does not contain text that can be selected, copied and pasted. For anyone wanting to reuse this data, this might mean having to recreate the structure by retyping it.

Thankfully, OmniGraffle includes the ability to export an XML file. The structure that is described by the diagram is exactly what one would want to recreate it in HTML.

OmniGraffle has an option to export as an OmniOutliner file. Control click the file and select Show Package Contents to grab the file called contents.xml. To be able to work with the data, I needed to take into account the XML namespace declaration to successfully run xsltproc on the command line.

The XML namespace declaration was preventing the XSLT processor from outputting successfully with the selectors that I was using. What I didn’t understand was that the XML namespace declaration on the outline element changes the XPath expressions needed to select these elements. Instead of:

              <xsl:template match="/">
  <xsl:apply-templates select="outline" />
</xsl:template>

            

I needed to use the XML namespace prefix on all selectors for the outline element and all child elements.

              <xsl:template match="/">
  <xsl:apply-templates select="outline:outline" />
</xsl:template>

            

Once I figured this out, xsltproc was able to output something other than a blank file or no file at all, since the result was empty.

The XSLT Template

Create a file called transform.xsl in the same directory as the contents.xml file. Add the following to the transform.xml file:

              <?xml version="1.0" encoding="ISO-8859-1"?>

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:outline="http://www.omnigroup.com/namespace/OmniOutliner/v3"
  extension-element-prefixes="outline">

<xsl:output method="xml"
    doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
    omit-xml-declaration="yes"
    encoding="UTF-8"
    indent="yes" />

<xsl:template match="/">
  <xsl:apply-templates select="outline:outline" />
</xsl:template>

<xsl:template match="outline:outline">
  <html>
    <head>
      <title>Site Map</title>
    </head>
    <body>
      <h1>Client Name</h1>
      <h2>Site Map</h2>
      <xsl:apply-templates select="outline:root" />
    </body>
  </html>
</xsl:template>

<xsl:template match="outline:root">
  <ul>
    <li>
      <a href="#"><xsl:value-of select="outline:item//outline:lit" /></a>
      <xsl:apply-templates select="outline:item" />
    </li>
  </ul>
</xsl:template>

<xsl:template match="outline:item">
  <ul>
    <xsl:apply-templates select="outline:children" />
  </ul>
</xsl:template>

<xsl:template match="outline:children">
  <li>
    <a href="#"><xsl:value-of select="outline:item//outline:lit" /></a>
    <xsl:apply-templates select="outline:item[outline:children]" />
  </li>
</xsl:template>

</xsl:stylesheet>

            

Updated the code to fix the problem of wrapping a ul element around every li.

XSLT Processor

On the commandline, you should be able to run xsltproc --version to display the version of your XSLT processor.

              Using libxml 20703, libxslt 10124 and libexslt 813
xsltproc was compiled against libxml 20703, libxslt 10124 and libexslt 813
libxslt 10124 was compiled against libxml 20703
libexslt 813 was compiled against libxml 20703

            

Then cd (change directory) into the directory containing the contents.xml and transform.xsl files and run the following command:

              xsltproc -v -o output.html transform.xsl contents.xml

            
  • The -v option enables verbose mode.
  • The -o option specifies the name of the output file that will be created, in this case output.html.
  • The next argument, transform.xsl, is the XSLT stylesheet.
  • The contents.xml file is the XML file extracted from the OmniOutliner export file.

By applying the XSL transformation to the XML file, the XSLT processor will output nested unordered lists to describe the site map structure. For example, the site map for this site might look like this:

              <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Site Map</title>
  </head>
  <body>
    <h1>The Lab</h1>
    <h2>Site Map</h2>
    <ul>
      <li>
        <a href="#">Home</a>
        <ul>
          <li>
            <a href="#">Archive</a>
            <ul>
              <li>
                <a href="#">Category</a>
                <ul>
                  <li>
                    <a href="#">Applications</a>
                  </li>
                  <li>
                    <a href="#">Design</a>
                  </li>
                  <li>
                    <a href="#">Development</a>
                  </li>
                  <li>
                    <a href="#">Projects</a>
                  </li>
                  <li>
                    <a href="#">Travel</a>
                  </li>
                  <li>
                    <a href="#">Workflow</a>
                  </li>
                </ul>
              </li>
              <li>
                <a href="#">Tag</a>
                <ul>
                  <li>
                    <a href="#">jQuery</a>
                  </li>
                  <li>
                    <a href="#">js</a>
                  </li>
                  <li>
                    <a href="#">Chome</a>
                  </li>
                  <li>
                    <a href="#">extensions</a>
                  </li>
                  <li>
                    <a href="#">responsive</a>
                  </li>
                  <li>
                    <a href="#">screen capture</a>
                  </li>
                  <li>
                    <a href="#">Symphony</a>
                  </li>
                  <li>
                    <a href="#">ensembles</a>
                  </li>
                </ul>
              </li>
            </ul>
          </li>
          <li>
            <a href="#">About</a>
          </li>
        </ul>
      </li>
    </ul>
  </body>
</html>

            

GUI Tools for XSLT Processing

If you would prefer to avoid the command line, there are other GUI tools for processing XSLT. My favourite tool has been the TextXSLT application developed by Marc Liyanage for Mac. However, because Lion no longer supports Rosetta, I can’t use it any longer.

Another option is XSLPalette. I did my testing for this script with a combination of XSLPalette, xsltproc and Symphony. I would have used a tool I created with Marco Sampellegrini, called xpathr, but we have some work to do on this tool to enable XSLT processing without having to save a gist to GitHub. It is definitely on my todo list, and you’ll see that I am reviving my GitHub account after a bit of a hiatus to work on the xpathr user interface.