Smart Layer Export manual install

Some people have trouble installing the Smart Layer Export plugin.
I don’t really recommend manually installing, as it means you won’t automatic updates.
Until Adobe fixes the plugin installer though, it’s some people’s only choice.

Here’s how to install the plugin manually.

On Mac OSX

1. Change the file extension of the plugin from zxp to zip
2. Unzip the package (the built-in unzip program doesn’t seem to work well, use Stuffit Expander instead)
3. Copy Smart Layer Export.jsx file into your Scripts folder (Applications/Adobe Illustrator CC 2014/Presets/en_US/Scripts)
3. Copy SmartLayerExport folder into your locale folder (Applications/Adobe Illustrator CC 2014/Presets/en_US)

On Windows

1. Change the file extension of the plugin from zxp to zip
2. Unzip the package
3. Copy Smart Layer Export.jsx file into your Scripts folder (C:\Program Files\Adobe\Adobe Illustrator CC 2014\Presets\en_US\Scripts)
3. Copy SmartLayerExport folder into your locale folder (C:\Program Files\Adobe\Adobe Illustrator CC 2014\Presets\en_US)

If you are using a different language, the “en_US” and “Scripts” part of those paths will be different, but it should be fairly clear which is which.

After copying the files into the correct location you will need to restart Illustrator.

Managing Presets in Smart Layer Export

A user of my Smart Layer Export plugin asked me how to manage presets so I thought I’d just post some tips for everyone.

At the top left of the panel you’ll see the presets area.

Presets

1. Presets Dropdown

First is the Presets Dropdown, which loads a preset and applies it over your current settings.
A note about presets; they don’t have to include all settings, and if they omit particular settings then your current settings will remain after selecting a preset.
This allows for a preset to only affect one part of the panel (for example, only the destination folder) and leave other settings untouched.

2. Add Preset Button

The Add Preset button allows you to create a new Preset.
It will bring up the following dialog box.
AddPreset
Which allows you to name your preset, as well as select which options should be included in it (see above note about partial presets).

3. Import Preset Button

The Import Preset button brings up a file search dialog box which allows you to add exported presets to your list.

4. Export Preset Button

The Export Preset button allows you to save a preset (or the current settings) to a preset file which can then be distributed and imported on other computers.

Accessing internal Preset files

The controls provided are fairly simple and don’t allow for editing/deleting presets.
If you need to edit/delete a plugin, you currently need to access the folder where they are stored on the hard drive.

On Windows, it is here:
C:\Users\\AppData\Roaming\org.tbyrne.smartLayerExport\presets

On Mac OSX, it is here:
/Users//Library/Application Support/org.tbyrne.smartLayerExport/presets

Here you can delete presets as well as edit them in a text editer (if you know XML).

Manually installing Flash2Svg

If you’re having trouble installing Flash2Svg in Flash, here are some instructions to manually install the plugin.
This works in all versions (CS5 – CC 2015, as of writing) but will only give you the older, flash-based UI, not the new HTML5-based UI.
This means some of the functionality won’t be there (e.g. embedding assets) but all of the most recent bug fixes will be available.

  • Download the latest ZXP
  • Change the file name of the extension from ZXP to ZIP
  • Extract the contents of the zip archive
  • Copy the SVG.swf and svg-help.xml files from the FLASH folder into this folder:
    C:\Users\{username}\AppData\Local\Adobe\Flash CS5\en_US\Configuration\WindowSWF
  • Copy the Extensible folder (also from the FLASH folder) and copy the whole folder into this folder:
    C:\Users\{username}\AppData\Local\Adobe\Flash CS5\en_US\Configuration\Javascript

Obviously change the version of flash in those paths to the correct one (e.g. ‘Flash CC 2015’).

Mac is very similar, something like:
/Users/{username}/Library/Application Support/Local/Adobe/Flash CS5/…

On both systems you’ll probably have to show hidden folders to get there.

Haxe > Python > Remote debug on Raspberry Pi

Just got the Python remote step-through debugger working on RPi.
You can compile Haxe to Python your laptop, automatically deploy it to the RPi and then start a remote Python debug session on the device with one button.

Check out this article for the python debugger part of things:
http://www.codeproject.com/Tips/987276/Remote-Programming-of-RaspberryPi-using-PyCharm

Add an hxml file to your project called compile.hxml, in the project root:

1
2
3
-cp src
-python bin/Main.py
-main my.pack.Main

Change the details in there to match your project.

Then add a pre-launch tool to compile the Haxe code:

  • Run > Edit Configurations
  • Select your run configuration on left
  • Add a ‘Before launch’ task > “Run External Tool”
  • Add a new Tool
  • Locate the Haxe compiler in the Program field
  • Add these parameters (inc. -debug to include hx source back-references):
    1
    compile.hxml -debug
  • Set working directory to ‘$ProjectFileDir$’

Note, this Tool configuration can be reused across projects, as long as they have the compile.hxml file.

Sticking points:

  • JetBrains Haxe plugin doesn’t work well with PyCharm (ended up using FD for coding).
  • Would be awesome to get the hx source back-references integrated into the debugger so that you’re debugging Haxe not Python code.

Viber Animated SVGs

For over a year now, Viber have been funding the development of my Flash2Svg panel for Flash Professional (also available from Adobe Add-ons site).

The animations they’ve been producing with it have been really incredible, and I’ve been really keen to showcase some of their incredible work.
The resulting animations are so smooth and the vectors are so crisp that it’s really worth being able to see them at desktop size (preferably on a HiDPI/Retina screen).

So thanks to Viber for their continued support and for allowing me to some of their animations publicly.
Hopefully it’ll bring a little more attention and support to the SVG/SMIL specifications they’re built upon.

Click the images to play the animation





Flash2Svg v3.13

Recently there has been tons of activity on the Animated SVG exporter for Flash Pro.
Continue reading

Flash2Svg v3.7

There’s a new version of the Flash2Svg plugin available.

Some new features include color tweens (check the pupils in the example, from v3.7) and custom eases (1 or 2 points only, from v3.6).

Continue reading

In the last six months I’ve launched two export tools for Adobe Illustrator.

Smart Layer Export

This tool followed on from a free export panel I released some time ago. It enables a quick way to export artboards and layers into a variety of formats. I’ve added a ton of features and usability to the tool, and it’s been getting a great response.

Check it out here

Smart Symbol Export

After getting a handful of requests for this functionality, I’ve added the ability to export the symbols used in a document with all of the features of the other plugin.

Check it out here

ScreenPPI Cordova Plugin

I’ve recently released a very simple plugin for PhoneGap.
It allows access to the screen’s PPI (also called DPI).

Grab it here:
http://plugins.cordova.io/#/package/org.tbyrne.cordova.plugins.screenppi

Promises in Haxe Composure

After learning recently that Lubos Lenco was using my Composure library as the foundation of his impressive ZBlend game framework, I decided to add a few more really helpful features.

Promises

Sometimes when using @inject to inject multiple properties, it’s helpful to know when all of the properties have been injected. This can be done by adding the @promise metadata to a method with a list of the properties that should be watched for. The method will be called immediately after all properties get set.

Notice that it is possible to use non-injected variables in your promises (‘active’ in the below example). At compile-time these variables will be wrapped in getter/setters to facilitate the watching process (or the setter will be amended if it already has one).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    class MainPlayer extends AbstractTrait{

        public var active:Bool;

        @inject({asc:true})
        private var gamepad:IInputDevice;

        @inject
        private var controller:CharacterMotionControl;

        public function new(){
            super();
        }

        @promise("active", "gamepad", "controller")
        public function onPromiseMet(met:Bool):Void{
            if(met){
                trace("Both traits have been added and are ready to bind together");
                controller.setInput(gamepad);
            }else{
                trace("One of the traits is about to be removed, unbind them now");
                controller.setInput(null);
            }
        }
    }

How promises behave

  • The first call to your bound method will be called as soon as all applicable variables have been injected, the met parameter will always be true on the first call.
  • If any of the properties get set to another value, then the method will be called twice, once before the property is committed with met=false, then again after the value has been set with met=true. This will really only happen when promises are pointing to non-injected properties (which are set outside of the composure framework).
  • If any of the applicable traits are removed (i.e. the property is set to null) then the method will be called again with met=false

Future features

There are a few other ideas floating around for more features and improvements, which I’ll have a look at when I get a chance:

  • Compile-time binding for certain pre-established objects. This will make things much faster and lighter when generating lots of the same type of game objects (a bunch of enemies, for example).
  • A light and simple event system for communicating events between the traits of a ComposeItem. This would also come with metadata support.
  • A simpler, lighter version of the @inject metadata that trades some flexibility for performance.

SVG Animation Exporter v3.0

SVG is a great graphic format, it scales perfectly for different screen pixel densities, so that it looks crystal clear on all devices.
Being a vector format it’s also typically smaller than raster based formats (i.e. JPEG, GIF, etc)
It’s only drawback is that it consumes resources to be rendered, but this has been almost entirely mitigated in recent years by all browser vendors optimising their rendering software.
It also has the power to include animations within a single file, through the underutilised SMIL standard. These animations are also very clean and light.
Unfortunately there is little in the way of generating these animations, this is why I have been working on this export panel for flash for some time now.

Continue reading

HaxeBridges – Inter-platform coding library

HaxeBridges is a library which allows a single project to be compiled into separate parts, and for separate platforms.
This is useful for many situations, including when multi-threading, client/server, etc.

The idea is that your main application should be able to naturally use objects which will be published via a different platform/compile.

The example included in the repository now is a simple example of creating a worker thread (flash only for the moment).

In the main class:

1
2
3
4
 var obj = new ObjectInsideWorker();
 obj.nonStaticMethod(function(result){
    trace("Worker result: "+result);
 });

And the class which gets compiled into the worker:

1
2
3
4
5
6
7
8
9
10
package;
class ObjectInsideWorker{
 
 public function new(){
 }

 public function nonStaticMethod():String{
    return "nonStaticMethod: "+Std.string(Math.round(Math.random() * 1000));
 }
}

Then all that’s required is a compiler argument to get things working:

1
--macro Bridge.add('ObjectInsideWorker', 'Worker')

(first argument is a comma separated list of classes to be included in the worker)

More examples and bridge-types to come.
Check out the repository here.

RD32II Action Camera AVI file issues

I recently used a small video camera for an overseas journey and realised on return that the video files generated are formatted in such a way that prevents them from being read by most professional video editing/converting software. To get around this took a little research, so for those who are having similar issues I thought I’d post how I fixed the files. These instructions are for Windows, if anyone converts for use on OSX please post in the comments.

  • First, download ffmpeg, look for the link with “Static” in the title under the correct OS type heading (32-bit or 64-bit).
  • Open this compressed file (might need to install 7zip if you can’t immediately open the archive).
  • Extract the bin/ffmpeg.exe file from the archive and copy it into the folder with your video files.
  • Create a new text file in the same folder and add this text into it:
1
2
for %%a in ("*.*") do ffmpeg -i "%%a" -c:v libx264 -preset slow -crf 20 -c:a libvo_aacenc -b:a 128k "newfiles\%%~na.mp4"
pause
  • Rename this file “Convert.bat”.
  • Double-click this file

It will create new video files (in H264 format), after which you can delete the original AVI files.
Now you should be able to move these two files into any folder with the broken video files, run the “Convert.bat” file and it fix your videos.

If, like me, you had your camera mounted upside-down for practical purpose, then use this script instead, which will also rotate the video 180 degrees.

1
2
for %%a in ("*.*") do ffmpeg -i "%%a" -c:v libx264 -vf "vflip,hflip" -preset slow -crf 20 -c:a libvo_aacenc -b:a 128k "newfiles\%%~na.mp4"
pause

SMIL test page

Export Flash to Animated SVG

While working on a project which required rich vector animations in the browser, I came across Dave Belias’ library for exporting still SVG frames from flash. I wondered if I could re-purpose it to export Animated SVGs, a relatively unknown standard for containing fully animated imagery within a single SVG file.
Continue reading

Export Illustrator Layers to SVG files

I’m currently working on an Adobe Edge job, it’s almost totally vector based, and it turned out there were few quick options for breaking Illustrator files down into multiple SVG files.

After looking around, I decided to add features to Matthew Ericson’s awesome exporter script. Adding the SVG export format was easy enough, unfortunately I ran into another problem.

The original tool was built for raster outputs, and whilst it did support EPS, each EPS file that was generated actually had all layers included (all invisible except one).
So after some reworking I got it to generate small vector SVG/EPS files, each containing only what was needed.

I also made it easier/cleaner to add new formats and added a few usability tweaks (options which don’t apply to the current output format are disabled).

Installation & Usage

Just drop this javascript file in your Illustrator scripts folder (CS6 is something like: C:\Program Files\Adobe\Adobe Illustrator CS6\Presets\en_GB\Scripts).

In Illustrator, use the File > Scripts > MultiExporter option to bring up the dialogue box, it’s all fairly self explanatory.

MultiExporterScreen

Notes

I made minimal changes to Matt’s functionality, here are his original notes with my modifications.

  • Supported formats are: PNG8, PNG24, PDF, EPS & SVG
  • You can choose whether you want to export all the artboards in the document with the currently visible layers showing, or if you want to export files for each of the layers in a document on the currently active artboard, or if you want to export a combination of all the artboards multiplied by all the layers.
  • Files are named based on their layer name. It only exports layers where their name has been changed from the default “Layer 1″, “Layer 2″ or “Artboard 1″, “Artboard 2″, etc. I removed this feature, but might add it back as a configurable option.
  • If you put a minus sign (-) in front of a layer name or artboard name, it will skip that layer or artboard. (Useful for when you no longer decide you like a particular mockup, but don’t want to delete it from the master Illustrator document.)
  • For layers only: If you put a plus sign (+) in front of a layer name, that layer will always be visible. Useful for if you want to have a layer that always appears in the background of each exported image.
  • It stores its settings in a nonvisible, nonprinting layer named “nyt_exporter_info”

  • It has an option for transparency.
  • It has an option for embedding linked imagery (EPS & SVG only).
  • It has an option for embedding fonts (EPS only).

Check out the Gist

If the panel is unusably small

This is most likely the result of an Illustrator bug affecting Dual monitor setups.
Open the script in a text editor and replace the following line:

this.dlg = new Window('dialog', 'Multi Exporter');

with the line:

this.dlg = new Window('dialog', 'Multi Exporter', undefined, {resizeable:true});

This will make the panel resizable.
(Thanks to Alexey Tcherniak for looking into this)

Edits 11/04/2013 – 8/05/2013

There were some issues with the alignment of objects when multiple artboards existed, which I’ve fixed.
Also, it now avoids outputting imagery when nothing would be included, this makes the “Artboard + Layers” output much more useful (as you’d rarely have one layer which spans across multiple artboards).
I have added the functionality to trim the exported files to their visible size (as opposed to the artboard’s size), this will allow mouse interactions to pass around the visible area to regions behind the SVG.
Fixed an issue where layers containing only invisible items (e.g. Guides) were causing an exception.
Fixed an alignment issue which appeared if the artboard had been resized after creation.
Fixed cropping issue with large layers (and Trim option)

Edit 17/05/2013

Separated the artboard and layer selection, which now allows for more fine-grain set ups.
Now allows for ‘Trimmed Edges’ functionality for all output formats.

Edit 17/07/2013 – 28/08/2013

Now you can export Illustrator layers to FXG files (versions 1.0 & 2.0)
Added an option to ignore warnings.
Fixed ‘Save & Close’ button.
Empty child layer bug fix.

Edit 6/12/2013

Added a mode to avoid visual clipping of round backgrounds.
Thanks to John Ford for the input.

Edit 7/8/2014

I’ve changed the file naming system to be much more flexible, using a token pattern instead of the prefix/suffix fields. Try it out here.

NEW VERSION

There’s a brand new version of the tool, rewritten from the ground up, it’s way more powerful and allows for multiple image formats to be generated from a single execution.
Also, it avoids the group issue that was the cause of that annoying message box.
I’ll still be offering this version, but if you get a lot of use out of it, buying the power version would be much appreciated.

Check it out at Adobe Exchange.

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

E4X Macro for Haxe

I recently needed to navigate some XML in Haxe and noticed that there were few options for doing this quickly and easily in Haxe.

I did notice Oleg’s Walker class which brings some of the E4X functionality of AS3 to Haxe.
While the resulting code was more elegant than hand-writing loops and tests, it still felt too verbose, and I decided to add some macro sugar to it to cut down the syntax (and bring it closer in line with the E4X spec).

The result is the E4X class, which reduces the amount of code by 2-3 times (in comparison to a fully runtime, function-based solution). Due to haxe language restrictions, the resulting syntax is not quite as compact as the AS3 equivalent, but it’s close.

Usage

E4X expressions must be wrapped in the macro call, and they return an iterator of values (the type of which is based on the last part of the expression).

To get all children:

1
var nodes:Iterator<Xml> = E4X.x(xml.child());

Here are some different ways to get a list of all the child nodes with the name “node”:

1
2
3
4
5
6
7
8
9
10
11
var xml:Xml;
var nodes:Iterator<Xml> = E4X.x(xml.node);

// or (for example)
var nodes:Iterator<Xml> = E4X.x(xml.child("node"));

// or (using an expression which will be wrapped in a function call)
var nodes:Iterator<Xml> = E4X.x(xml.child(nodeName=="node"));

// all of which are shortcuts for this filter expression
var nodes:Iterator<Xml> = E4X.x(xml.child(function(xml:Xml, _i:Int):Bool{return xml.nodeName=="node";}));

To get the text of a node use the text() method:

1
var nodes:Iterator<String> = E4X.x(xml.text());

To access descendants, use the “desc()” method, or the underscore shortcut:

1
2
3
4
5
var nodes:Iterator<Xml> = E4X.x(xml.desc());
// or
var nodes:Iterator<Xml> = E4X.x(xml._());
// or just
var nodes:Iterator<Xml> = E4X.x(xml._);

Here are some different ways to get a list of all the descendant nodes with the name “node”:

1
2
3
4
5
6
7
8
9
10
11
var xml:Xml;
var nodes:Iterator<Xml> = E4X.x(xml._("node"));

// or (for example)
var nodes:Iterator<Xml> = E4X.x(xml.desc("node"));

// or (using an expression which will be wrapped in a function call)
var nodes:Iterator<Xml> = E4X.x(xml.desc(nodeName=="node"));

// all of which are shortcuts for this filter expression
var nodes:Iterator<Xml> = E4X.x(xml.desc(function(xml:Xml):Bool{return xml.nodeName=="node";}));

Getting a list of descendants that have an “id” attribute would be done like this (the a(“id”) call acts like a filter):

1
2
3
4
5
6
7
var nodes:Iterator<Xml> = E4X.x(xml._(a("id")));

// which could also be written as
var nodes:Iterator<Xml> = E4X.x(xml._(a(attName=="id")));

// both of which will be expanded to
var nodes:Iterator<Xml> = E4X.x(xml._(a(function(attName:String, attValue:String, xml:Xml):Bool{return attName=="id";})));

Whereas, if you wanted to get the “id” attributes themselves, you could do this:

1
var nodes:Iterator<Hash<String>> = E4X.x(xml._.a("id"));

To get all of the ancestors of any nodes with an “id” attribute equal to “test”, you could do this:

1
2
3
var nodes:Iterator<Xml> = E4X.x(xml._(a("id")=="test").ances());
// or (a little less legible, but will perform slightly better)
var nodes:Iterator<Xml> = E4X.x(xml._(a(attName=="id" &amp;&amp; attValue=="test")).ances());

 

Comparison with AS3 E4X

Getting children with a specific node name (i.e. “node”)
AS3 E4X xmlRoot.node
Haxe E4X xmlRoot.node
Getting descendants with a specific node name (i.e. “node”)
AS3 E4X xmlRoot..node
Haxe E4X xmlRoot._(“node”)
Getting an attribute
AS3 E4X xmlRoot.@id
Haxe E4X xmlRoot.a(“id”)
Getting all descendants with a “id” attribute
AS3 E4X xmlRoot..(@id.length())
Haxe E4X xmlRoot._.(a(“id”))

Note that all of these examples should be wrapped in the E4X.x() call, as in the code snippets above.

 

Performance

I also ran some performance tests for several targets (and the equivalent tests in AS3 E4X), the results of which are below.
This helped me make some performance improvements to Oleg’s original code, and I managed to squeeze an extra 25-30% increase in performance out of it.

Surprisinigly, the JS target seems to perform best overall (although this is probably more as a result of Chrome’s JS engine).
Even after my improvements, the AS3 target was woefully slow in comparison to it’s native counterpart, although all of the other targets seemed to hold their own, with more complex expressions becoming faster than the AS3 E4X equivalent (if anyone knows why this performs so poorly, let me know).

AS3 E4X Hx > Flash Hx > JS Hx > C++ Hx > Neko
Get Children 0.00 0.21 0.03 0.22 0.03
Get Children With Attrib 0.08 1.02 0.24 0.10 0.31
Get Descendants 0.92 7.20 0.52 0.57 0.94
Get Descendant Text 1.48 19.40 1.97 1.83 3.22
Get Descendants by Name 2.33 11.05 0.24 0.51 1.42
Get Descendants with matched Attrib. 2.70 30.10 1.20 2.23 7.51
Measurements are in seconds per 1000 calls
JS tests done in Chrome 24 Win64

If anyone has any idea how to use the @ symbol in method names in haxe (without the compiler complaining), let me know and I’ll make attribute accessors match the spec.

I will be releasing this code as part of an upcoming haxe library called “xml-tools”, but until then, feel free to download the E4X class here.

Shout out if have any issues.

© 2016 Thomas Byrne

Theme by Anders NorenUp ↑