Friday, March 19, 2010

XSL: xsl:element and short tags

I have had problems with XSL and short tags before when using identity transforms, but it can also be an issue doing simple element creation. Obviously as far as a parser is concerned, it makes no difference whatsoever whether you have short tags (e.g. <fish/>) or the complete form (<fish></fish>) for you empty elements, but it makes it much fatter and far less human readable - especially as the .NET System.Xml.Xsl.XslCompiledTransform at least puts closing tags on a new line for empty elements as well as ones with children.

So, if you generate a completely empty element with <xsl:element>, then the short form is used:

<xsl:template match="fish">
 <xsl:element name="{@type}"/>
</xsl:template>

However, if you add any attributes, then the complete form will be used, even though there are still no child elements:

<xsl:template match="fish">
 <xsl:element name="{@type}">
  <xsl:attribute name="type">Fish</xsl:attribute>
 </xsl:element>
</xsl:template>

The trick is to generate your element into an <xsl:variable> and then use <xsl:copy-of> to output it, which results in the short form being maintained:

<xsl:template match="fish">
 <xsl:variable name="el">
  <xsl:element name="{@type}">
   <xsl:attribute name="type">Fish</xsl:attribute>
  </xsl:element>
 </xsl:variable>
 <xsl:copy-of select="$el"/>
</xsl:template>

Easy when you know how. I couldn't find this anywhere on Google, so it's either an obvious thing that everyone but me already knows, my searching sucks, or I'm the first person to have this problem.

Following a comment by Martin Honnen on my original MSDN query about this, it seems that it is a bit more complicated; the basic problem is that XSLT does not define an output format for these situations, so it is entirely up to the processor / serialization combination.

The processor I was using to run these tests was on v2.0 of the framework, and was the deprecated System.Xml.Xsl.XslTransform object, which requires the workaround. The newer System.Xml.Xsl.XslCompiledTransform uses the short form for empty tags and so does not need the workaround.

Annoyingly, the target application uses XslCompiledTransform and therefore would have worked fine, it is only the scratchpad I use for knocking up stylesheets that uses the legacy code that caused the issue! And a quick change of typename for one object and removal of one parameter that was null anyway, and it's bloody working there too. Hurrah for wasted time.

Ah well, if someone is still using the deprecated code then maybe this will help.

Wednesday, March 3, 2010

J2ME: EXIF and lightmetering Part 1

I am a bit of a camera obsessive. I got into photography with a digital P&S, progressed to a DSLR, and then got into film. Since then, my camera collection has taken over several surfaces in the flat. I don't have that many, but then I don't have that many surfaces.

Most of the collection consists of old cameras; my theory is that if you want to take crisp "perfect" images, a DSLR is the way to go. This is a theory based mainly on laziness, but it works for me.

In general, the film cameras have been chosen for looks at least as much as quality. The Rolleiflex has both in spades, of course.

Most of the old cameras do not have a light meter, and many with the old selenium cell meters simply do not work any more.

I do own a couple of lightmeters, but I find they are a pain to use, and new ones are basically extremely expensive flash looking versions with exactly the same functionality.

What I have been doing it using the dSLR to take a preview shot, then transferring the settings over to whatever camera I am currently playing with. However, this becomes a bit tedious after a while, and also having, say, the Rolleiflex and the dSLR round my neck results in severe neck strain.

So, ideally, I want a very small camera than can take a preview shot with the ability to tell it the ISO and, usually, the aperture I want. I can then check the preview looks okay, and transfer the settings over with any modifications required. However, P&S cameras with these manual settings are not cheap and often have big limitations on the ISO and f/stop they allow you to set, so an alternative solution is to take the preview with whatever settings the camera wants, then allow me to easily convert them into ones I can use.

This is where my mobile comes in. It is extremely small, I always have it on me, and it has a camera with a full auto mode that takes JPEGs stuffed full with the EXIF data for the exposure. Perfect. Except that, on the phone, there is no way of actually viewing the EXIF.

However, the phone, a Sony Ericsson C903, has mobile Java, and I've seen some Java before, so I decided to give writing an app for it a shot.

It was an interesting exercise, and along the way I discovered several fun things. For example, mobile Java is one of the most frustratingly NON-device independent environments it's been my misfortune to use, the certification requirements are beyond absurd, and my phone has one of the most annoying bugs ever to have existed - when your app works perfectly and is extremely useful, having the phone randomly lose and/or corrupt the memory card it's sitting on is rather irritating.

The first bit of the code, which we have finally come to, is something that will read EXIF data out of JPEGs. I had a fish round for some libraries and found lots of great code that was either extremely big, extremely non J2ME compatible, or both.

Then I discovered this Javascript library, which I have to say, is brilliant. It's a use for client side Javascript and AJAX that simply would never have occurred to me in a million years. It is perfect for my uses because being entirely client side Javascript it uses very basic language features and is very small, ideal for conversion to Java by someone who hasn't used Java for about 8 years :o)

The code was written in the J2ME 3.0 SDK editor, which seems to have mangled the indentation for any other editor, but source code formatters are not exactly hard to find. The basic EXIF when compiled has not J2ME specific imports, so can be linked into any Java project; this is very handy for testing, obviously.

I made a couple of changes; I added X_FNumberAsString as a new data item for laziness, and created a Fraction class to help with maintaining the normal form of shutter speeds when manipulating them (a later post).

The ByteArrayWrapper class duplicates the required functionality from binaryajax.js.

EXIFReader contains the main functionality, and EXIFTags the tag names / descriptions and offsets, and also the list constants for various tags.

The classes live in the package rext.simpleexif.

It is pretty easy to use; you simply load in an image file into a byte[], then create the reader:

EXIFReader reader = new EXIFReader();
  
boolean ok = false;

try
{
 ok = reader.readEXIFFromByteArry(data);
}
catch(Exception e)
{
}

The reader object has three Hashtables for the various tags, EXIF, TIFF and GPS, and a Vector for debug messages called LOG.

Print out all EXIF tags to the console:

Enumeration exifk = reader.EXIF.keys();

while(exifk.hasMoreElements())
{
 String s = (String)exifk.nextElement();
 System.out.println(s + ": " + String.valueOf(reader.EXIF.get(s)));
}

You can get the code from the link below, including a small test console app that will print off the debug info then the EXIF data for a JPEG file.