XML.com: XML From the Inside Out
oreilly.comSafari Bookshelf.Conferences.

advertisement

Introducing o:XML

July 21, 2004

Most of us tend to think of XML as a useful, general-purpose data format. New vocabularies are springing up all the time, as do tools for XML processing. Still we haven't yet realized the potential of XML as a facilitator in the software development process itself.

o:XML is one project that promises to deliver the same benefits for programming that XML already offers for data representation. Furthermore, it may just make it easier than ever to code XML applications.

So what is o:XML? Well, it's a dynamically typed, general-purpose object-oriented programming language. It's got threads, exception handling, regular expressions, namespaces, and all the other things you would expect from a modern language. And it's expressed entirely in XML. Maybe o:XML is a bit like Python crossed with XML. To give you more of an idea, here's a version of Hello World, complete with type and function declarations:

Example 1: Hello World

<?xml version="1.0"?>
<o:program>
  <o:type name="HelloWorld">
    <o:function name="hello">
      <o:do>
        <o:return select="'Hello World'"/>
      </o:do>
    </o:function>
  </o:type>
  <o:set instance="HelloWorld()"/>
  <o:eval select="$instance.hello()"/>
</o:program>

XML being XML, the result is a verbose language that many will find difficult to read and hard work to write. It doesn't look like a "real" programming language like C or Java. And let's face it, there are already too many programming languages in the world. So why o:XML? Before addressing that question I will offer a short overview of the language itself.

Language Overview

Running an o:XML program produces XML output -- XML contained within the program is simply copied to the output. With this knowledge we can rewrite Hello World as follows:

Example 2: Hello Again

<?xml version="1.0"?>
<o:do>Hello World!</o:do>

Since o:XML is object-oriented, everything is an object and every object has a type. The basic types are String, Element, Document, etc., representing types of XML nodes. There are also collection types and an evolving set of core libraries. Users can, of course, create their own types and functions.

o:XML has an expression language very similar to XPath. The main difference is that o:Path allows functions to be invoked on nodes and node sets, just like with objects in Java or C++. Since in o:XML nodes are objects, o:Path can be used not only to find and select nodes, but also to modify and change their state.

Example 3: o:Path Expression

//a[@href.contains('cnn.com')].remove()

Removes all a elements with href attributes containing the text cnn.com.

In this example the function contains() is invoked on the href attribute of all a elements in the document. The function remove() is invoked on all a elements that match the predicate.

Any valid XML document is a valid o:XML program. Furthermore, o:XML can be embedded anywhere in an XML document. Embedded use of o:XML means that dynamic content can be included in a document without breaking XML validity. o:XML exists in its own namespace, and respects document integrity.

Say, for example, that you store your holiday pictures in a directory. You would like to produce an RSS feed with names and links to the pictures. We construct a simple program based on the structure of plain RSS, and use the o:Lib io module to access the file system.

Example 4: RSS Feed

<rss version="2.0">
  <channel>
    <title>Pleasant Pictures</title>
    <link>http://www.o-xml.org/</link>
    <description>An o:XML example.</description>
    <o:import href="lib/io.oml"/>                           1
    <o:set dir="io:File('.')"/>                             2
    <o:for-each name="file" select="$dir.list('*.jpg')">    3
      <item>
        <title><o:eval select="$file.name()"/></title>      4
        <link>file://<o:eval select="$file.path()"/></link>
      </item>
    </o:for-each>
  </channel>
</rss>
  1. Load the io module.
  2. Set the variable dir by creating a File that represents '.', the current directory.
  3. Iterate over all jpgs in the directory, assigning each one to the variable file.
  4. Get the file name and insert the value into the title element.

The above example represents a complete o:XML program. If you run it from the command line, it will produce an RSS output with one item element for each file in the current directory. As with all o:XML programs, it can also run as part of a web application or from a build script.

The example could easily be extended. You might want to sort the pictures by date (using o:sort), or prettify the filename by removing the suffix, and replace underscores with spaces (using the regexp substitute() function). Alternatively, an exsting XML data source such as the iPhoto AlbumData could be used to generate names and descriptions.

What is nice about simple o:XML scripts like these is that there is no "impedance mismatch" between the programming language and the data format. Coding in o:XML means that you can work quickly and elegantly, never departing from the Web's native tongue.

The next example further illustrates how o:XML integrates with XML. The program produces an SVG bar chart that shows the number of words in a DocBook document, broken down by section. It takes one parameter, the document filename.

Example 5: DocBook Word Count

<o:program>
  <o:param name="file"/>                                    1
  <o:import href="lib/io/File.oml"/>                        2
  <svg:svg>
    <o:for-each select="io:File($file).parse()//section">   3
      <o:set x="count(preceding::section) * 30 + 20"/>      4
      <o:set words="count(.//text().match('\w+')) * 2"/>    5
      <svg:rect width="10" x="{$x}" y="{250 - $words}">     6
        <o:attribute name="height" select="$words"/>
      </svg:rect>
      <svg:g transform="rotate(45, {$x}, 260)">
        <svg:text x="{$x}" y="260">                         7
          <o:eval select="title/text()"/>
        </svg:text>
      </svg:g>
    </o:for-each>
  </svg:svg>
</o:program>
  1. file parameter declaration.
  2. Load the io:File library type.
  3. Iterate over all section elements in the parsed file.
  4. Calculate the horizontal position of the next bar.
  5. Count the number of words in this section.
  6. Produce an SVG rectangle.
  7. Create an SVG text tag with the title of this section, rotated 45 degrees.

Here is the output produced by the program when run against this article:

I ran the program from the command line with this command:

java -jar objectbox.jar -Dfile=introducing.xml svg-example.oml

When an o:XML program is deployed in a servlet engine, it will take its parameters from an HTTP request. This means that simple command-line scripts work without modification as web applications and web services. Our example could be invoked like this:

http://milt.local/examples/svg-example.oml?file=introducing.xml

o:XML programs can equally well be invoked by Ant build scripts, with Ant providing the parameter values dynamically. This can also be very useful, for example, to automate XML publishing tasks.

Pages: 1, 2

Next Pagearrow