MonthFebruary 2013

In Defense of XML

Over the last few years XML has become a very unfashionable standard and especially in the Haxe world has drawn a lot of fire for being too verbose and containing too much redundancy.
I still use XML when I feel it’s appropriate, and I wanted to explain why.

When is XML the wrong choice?

In the past, XML has been used as a way of serialising data as input for a known web application (either from the back-end or from a file). I see this as a misuse of the technology. If it is not a public service, it has no reason to be be easily human readable and deserialising XML at runtime is wasteful. Ironically, this is what happens every time your browser loads a page and no-one seems too concerned about that.

Syntax problems with XML

I will also happily admit that the closing tag in XML is absolutely useless. Some might argue that it adds checkable redundancy to the file and avoids misspelling an opening tag, but that begs the question; Why not make all XML structures have redundancy? (Anyone think closing an attribute by retyping it’s name sound good?)

This could also be argued of the CDATA tag, which seems to be avoided simply because of it’s utter ugliness.

YAML?

YAML is like Brittany Murphy (was), it’s pretty, but it has some problems. Firstly, it doesn’t scale well, because it uses indentation as syntax, the deeper your heirarchies become the heavier each individual item is (so that a simple piece of information can use 10x the necessary characters, if deep enough). Sometimes removing indentations can make code more readable, and XML allows this (as does JSON), or it can be removed all-together when needed. In XML and JSON, you may choose to put several bits of information on the same line for brevity (normally as attributes), but YAML does not allow this behaviour.

This is not to say YAML does not have it’s uses. I believe it will find it’s place representing small pieces of structured data in broadly editable systems (like Wikipedia or something).

JSON?

In my opinion JSON is a strong contender to topple XML, and should be used in many public web-services instead of XML/SOAP. It’s human-readable and light on it’s feet. I have had many more issues resolving JSON serialisation incompatibilities than XML, but this is probably a result of it’s more organic evolution into a standard.

Where I see XML rise above JSON is when it comes to namespaces. Lots of developers will go their whole careers without needing to understand XML namespaces, but once you do, you’ll realise that XML is a little more than serialisation format. It allows different nodes to be scoped differently and to avoid any naming collisions. This might sound trivial but it means that XML data-sources can be annotated with tags from multiple different systems each of which can process the file without disturbing the other nodes, all without any need for delimiting anything (as in some template languages).

I’ll give you an example, you could use XSLT(an XML based language) to transform Android layout files (another XML based language) into XHTML. Neither of these standards were build to be aware of the other. And the output XHTML tags within your XSLT files can live as first class citizens alongside your transformation tags only because of namespaces. In this scenario, the resulting format does not even have to use namespaces to benefit from having them. So by using XML as an input for your application, you will have made it many times more flexible than otherwise.

When is XML appropriate?

When interpreted at compile-time, XML performance issues all but disappear, and the opportunities in pre-processing the XML add a huge degree of flexibility to a system.
I would argue that this is where XML belongs and will hopefully thrive as it’s misuse recedes.

Guise: Unified UI for Haxe

Haxe is a great platform for future-proofing your work, and with NME it provides a solid tool-chain for cross-platform native development.

Unfortunately, it lacks a real solution for the issue of user interfaces.
That’s why I’ve been building Guise, a UI library for native and non-native user interfaces.

Ideally, Haxe should have a UI system that does the following:

  • Should be able to be dropped in quickly and easily, with little setup code.
  • Allows the use of native controls where desired.
  • Allows the developer to switch to non-native (i.e. drawn) controls when the design requires.
  • Future display libraries should be able to be implemented quickly so that non-native controls are portable.

Guise attempts to solve each of these issues.
Note: Guise is just a working title, if anyone has a better name, comment at the bottom.

Guise is not Haxe 3 ready yet, only 2.10 (although there is a branch being worked on)

Check out the repository here.

Current usage types

Before getting into the details, I’ll show a few examples of Guise using different platforms/styles.
You’ll notice that I’ve only implemented a handful of controls so far, this has been done to keep the codebase flexible while the core architecture is still being finalised.

Graphics API in NME

Graphics API Style

This style uses a flash-type graphics API to draw UI elements to screen.
Skins are written in XML which is interpreted at compile-time (no loading/parsing XML needed).
Transitions between skin states are generated automatically based on the skin (although would probably be customisable in future).

Currently it is using NME, although it can support any number of drawing APIs (and did support CreateJS at one point).

Note: The skin used here is based on Allan Knutson’s Chutzpah style.

Bitmap API in Starling

Bitmap API Style

This style uses a texture-based bitmap API to draw styles on the GPU.
Currently it’s using Starling as it’s underlying display platform, but we anticipate dropping Starling support in favour of Nicolas’ H2D library (when it is a little more mature and supports a few more platforms).

There is also no reason that NME couldn’t support this type of skin, so expect to see that in the future (this would allow use alongside the graphics-type API above).

Note: The skin used here is based on Mani’s UI style.

HTML5 in Chrome

HTML5 Wrapper

We see this wrapper coming in handy when a native app needs to be pushed to the web.
Obviously you’d want to get some CSS in there as well.

I’ve just included here as an image for those on old browsers (sliders are very weird in IE9 btw).

Waxe on Windows

Waxe Wrapper

Waxe is a Haxe wrapper for wxWidgets, a native UI binding library for Windows, OSX and Linux. Unfortunately the project seems to have stalled (Hugh?), but I still believe it’s a good starting point for native UIs (especially for OSX).

The wrapper classes made for Waxe would hopefully provide the base for wrapping a similar solution for mobile, wrapping a library like Basis or MoSync NativeUI (with a set of externs), which would then open up support for iOS, Android and WP7 native controls.

Disclaimer

Whilst I haven’t pushed anything to haxelib yet, I’ll include the information below for anyone who wants to poke around the repository and test it out.

Setup

To use Guise with a native UI wrapper, you’d do something like this (file paths will have to be relative to calling class):

1
2
3
var root = new ComposeRoot();
root.addTraits([WindowTag, StageTag]);
XmlToCode.path("guise/Platforms/Waxe.xml").install(root);

And if you were using Guise with non-native controls, you’d set up like this:

1
2
3
4
var root = new ComposeRoot();
root.addTraits([WindowTag, StageTag]);
XmlToCode.path("guise/Platforms/NME.xml").install(root);
XmlToCode.path("guise/Styles/Chutzpah.xml").install(root);

All of these XML files get turned into classes at compile-time by the XmlToCode macro I built recently.

Adding controls

You can add a Text Button like this:

1
2
3
4
var item:ComposeItem = new ComposeItem();
item.addTraits([new TextButtonTag("Text Button"),
                new BoxPos(0,0,100,30)]);
root.addChild(item);

And a text input:

1
2
3
4
var item:ComposeItem = new ComposeItem();
item.addTraits([new TextInputTag("Type here"),
                new BoxPos(0,0,100,30)]);
root.addChild(item);

The code is exactly the same regardless of the intended platform, just the initial install call changes.

Skinning

The skinning system is very flexible and doesn’t push an anticipated structure on the developer. For example, a TextInput control can be skinned to have no text field, or ten of them, or an icon, or whatever your designer desires.
Each control has states, these are like MouseOver, Inactive or Focused; multiple states can be active at once. Each control also has layers and these layers can take on a different appearance based on which states are active. Each layer can also change it’s size and position based on which states are active (and transitions between these positions will be generated).

Future?

As mentioned above, we’re waiting for a few other haxe libraries to stabalize before integrating them, but once they have been integrated we’ll have all popular platforms covered in one way or another.

Native Layouts

Currently Guise has a few Haxe-based layouts and I intend to expand on this, but sometimes there is no substitute for native layouts. Supporting these would be a matter of providing some sort of NativeLayout class which would read a platform-specific layout file (XIB for iOS/OSX, Layout XML for Android, XAML for windows). The generation of all of these layout files from a common source file is the subject of another research project I’m working on (slowly).

Skin editor

As skinning is done in XML, I will at some point look at the viability of building a visual editing tool. This would use vector based drawing tools which could then be exported as either Graphics skins or Bitmap skins (with scale-9, bitmap fonts, etc).

XInclude for Haxe

When working with XML files, it’s often convenient to break the data structure down into smaller parts, each saved within a separate file.
There is a standard called XInclude which allows XML sources to reference other XML sources which can help reassemble your separate files into one structure.

As part of my XML Tools library, I’ve implemented an XInclude system which takes in a root XML file, loads in any referenced XML files and returns the complete XML structure.

Note: I’m well aware that XML has become the whipping boy of the web-dev world, but despite it’s verbosity we still have to deal with it.

Structuring your XML

To reference a file from within your root XML file (or any subsequent file), use the ‘include’ element like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// root.xml
<root>
    <include href="child.xml"/>
</root>

// child.xml
<child>
    <grandchild/>
</child>

// results in
<root>
    <child>
        <grandchild/>
    </child>
</root>

Or if you’re already using elements with the name ‘include’, you can use the XInclude namespace:

1
2
3
<root xmlns:xi="http://www.w3.org/2001/XInclude" >
    <xi:include href="child.xml"/>
</root>

As per the spec, if you want the referenced file to be added as a text node, you can specify using the ‘parse’ attribute:

1
<include href="child.xml" parse="text"/>

I’ve also added a feature which is not in the spec but I have found useful in the past. Using the ‘inParent’ attribute, you can have the root element of the referenced XML file ignored, with all of it’s attributes and chidl nodes being added directly to the parent node of the ‘include’ element. Here’s an example of the results:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// root.xml
<root>
    <include href="child.xml" inParent="true"/>
</root>

// child.xml
<child attribute="test">
    <grandchild/>
</child>

// results in
<root attribute="test">
    <grandchild/>
</root>

Installataion

As per usual, you have to install the xmlTools library from haxelib like this:

1
haxelib install xmlTools

And then include this library in your project settings.

Usage

Scroll to the bottom if you’re interested in using the tool from the Command line.
By default it uses the ‘mloader’ haxelib for all of it’s file-system access (you can use your own I/O system by implementing the org.tbyrne.io.IInputProvider interface).

1
2
3
var xmlIncluder = new XmlIncludeManager(new MLoader());
var task:IXmlIncludeTask = xmlIncluder.add("root.xml", "C:/xml/folder");
task.startInclude();

The first parameter here is the name of the root XML file, the second is the folder where all of the XML files are located.
The XML file-paths can include sub-directories of the root directory passed through.

You can then monitor the progress of the task like this:

1
2
3
4
5
6
7
8
9
xmlIncluder.progressChanged.add(onProgressChanged);
xmlIncluder.completeChanged.add(onCompleteChanged);

function onProgressChanged(from:XmlIncludeManager):Void{
    trace("progress: "+from.getProgress()+"/"+from.getTotal());
}
function onCompleteChanged(from:XmlIncludeManager):Void{
    trace("is complete: "+from.getComplete());
}

Command Line interface

I’ve also wrapped this code in an executable shell so that it can be used from the command line.

1
2
3
4
5
// as an executable
XmlIncluderShell root-file.xml -d C:/xml-directory/ -o C:/output-file.xml

// or as a neko executable
neko XmlIncluder.n root-file.xml -d C:/xml-directory/ -o C:/output-file.xml

The first argument is always the root XML file to operate on.
The second argument (-d) is the root directory that contains all of the XML files.
The third argument (-o) is the output file to write the result to.

Multiple executions can be done with one command using the ‘–‘ separator:

1
XmlIncluderShell root-file.xml -d C:/xml-directory/ -o C:/output-file.xml -- root-file2.xml -d C:/xml-directory2/ -o C:/output-file2.xml

Download executable here
Download Neko executable here

© 2017 Thomas Byrne

Theme by Anders NorenUp ↑