us site
developer center
search

A Guide to Java MessageFormat (or, How I Learned to Stop Worrying and Love Macros)

December 10th, 2008 by Joel Barciauskas

While working on an application for a client, I encountered some issues with Java’s MessageFormat. In particular, I needed to pass MessageFormat a string that contained single-quotes and curly braces that would be treated literally. This is an issue, because single-quotes and curly braces are special characters in MessageFormat land.

MessageFormat is designed to allow you to dynamically create a string based on a static pattern and a set of inputs. For example, this is from the MessageFormat JavaDoc:

 Object[] testArgs = {new Long(3), "MyDisk"};

 MessageFormat form = new MessageFormat(
     "The disk \"{1}\" contains {0} file(s).");

 System.out.println(form.format(testArgs));

 // output, with different testArgs
 output: The disk "MyDisk" contains 0 file(s).
 output: The disk "MyDisk" contains 1 file(s).
 output: The disk "MyDisk" contains 1,273 file(s).


Seems pretty straight forward. However, say you wanted to format a string that contained curly braces, such as “{ Hello {0}! I’m inside curly braces }”. Of course, to support this, MessageFormat uses single-quotes to specify strings that should be treated literally. So, naively, one might think to format

{ Hello {0}! I'm inside curly braces }

with the following output where {0} = “Joel”

{ Hello Joel! I'm inside curly braces }

We would come up with something like

'{ Hello {0}! I'm inside curly braces '}

This would work, if single-quote were an escape character like many of us are accustomed to using, for instance in regular expressions, and in Java literal strings, backslash “\” is an escape character. Of course, if single-quote were like an escape character, the above example would work and I wouldn’t be writing this post. But the single-quote isn’t an escape character.

The rules for MessageFormat escaping are most easily understood like this:

  1. Strings inside single quotes are treated literally
  2. Two single-quotes next to each other will be interpreted as a single single-quote, rather than an empty literal string

The understanding of single-quote as an escape character comes from the second rule. In this case, it is similar to “\\” in Java, C, Perl, etc, where to get the literal character “\” rather than an escaped string to be interpreted specially (e.g., “\n” for new line, “\u2297″ for a special Unicode character), you type the escape character twice, i.e., “\\”. However, the two single-quotes in a row are a special case, and most of the time you will use a string inside a set of single-quotes to represent a set of characters that should be ignored by the MessageFormat parser as it searches for placeholders (e.g., {0}, {1}, …).

Following these rules, to format

{ Hello {0}! I'm inside curly braces }

where {0} = “Joel”, i.e.,

{ Hello Joel! I'm inside curly braces }

We really only need to tell the parser to ignore the start and end curly braces. To do this, we will use the following pattern:

'{' Hello {0}! I'm inside curly braces '}'

And that actually works!

Now, let’s look at the problem I was trying to solve, and see if these rules can help us out. The string I was trying to format looked like this:

<label text="{ bind('dataSource=joelDS; select=text; type=ONE_WAY') }" />

I was using this string in an XModify Macro, however, such as this:

<macro:macro xmlns:macro="http://openxal.org/core/macro"
	name="addTradingTab">
	<xm:modifications xmlns:xm="http://openxal.org/core/xmodify">
		<xm:append select="id('container')">
			<label text="{ bind('dataSource={0}; select=text; type=ONE_WAY') }" />
		</xm:append>
	</xm:modifications>
</macro:macro>

Notice that the string to be appended contains a {, a }, and two ‘, all of which need to be escaped, without smothering the {0} from the parser. First lets tell the parser to ignore the first { and last }:

<macro:macro xmlns:macro="http://openxal.org/core/macro"
	name="addTradingTab">
	<xm:modifications xmlns:xm="http://openxal.org/core/xmodify">
		<xm:append select="id('container')">
			<label text="'{' bind('dataSource={0}; select=text; type=ONE_WAY') '}'" />
		</xm:append>
	</xm:modifications>
</macro:macro>

Next, lets escape the single quotes inside the parens:

<macro:macro xmlns:macro="http://openxal.org/core/macro"
	name="addTradingTab">
	<xm:modifications xmlns:xm="http://openxal.org/core/xmodify">
		<xm:append select="id('container')">
			<label text="'{' bind(''dataSource={0}; select=text; type=ONE_WAY'') '}'" />
		</xm:append>
	</xm:modifications>
</macro:macro>

We can test the above string using the MessageFormat demo provided by Sun, which runs in an applet. Entering the

<label text="'{' bind(''dataSource={0}; select=text; type=ONE_WAY'') '}'" />

line in the Pattern field, and entering “joelDS” in the 0 argument, we get:

<label text="{ bind('dataSource=joelDS; select=text; type=ONE_WAY') }" />

Wahoo, it works!

To review:

  1. While MessageFormat single-quotes act like escape characters, it is much easier to think of them as a string-literal syntax
  2. When in doubt, test your Macro patterns using the MessageFormat demo provided by Sun.

Tags:

3 Responses to “A Guide to Java MessageFormat (or, How I Learned to Stop Worrying and Love Macros)”

  1. Вольтер (Мари Франсуа Аруэ) Says:

      …

    Труд часто является отцом удовольствия.

  2. MAX Says:


    MedicamentSpot.com. Canadian Health&Care.Special Internet Prices.No prescription online pharmacy.Best quality drugs. Low price pills. Order pills online

    Buy:Viagra Super Active+.Super Active ED Pack.VPXL.Cialis.Viagra Super Force.Maxaman.Viagra Professional.Viagra.Levitra.Propecia.Cialis Soft Tabs.Cialis Super Active+.Zithromax.Soma.Tramadol.Cialis Professional.Viagra Soft Tabs….

  3. in Says:

    Storage http://snew6crg8.BABYCLOTHESNUT.INFO/tag/Auctions+in+Storage/ : in…

    in…

Leave a Reply