Tutorial

Hello World!

Let's start with a very simple example. The following template prints 'Hello [Person's first name]', where person is passed as one of the template's parameters.

<btl:template xmlns:btl="http://btl.sourceforge.net/">
	<btl:main>
		<btl:param name="person"/>
		
		<h1>Hi ${person.firstName}!</h1>
		
		<p>Welcome to <img src="./btl.gif"/> & have fun!</p>
		
		<p>Your homepage is <a href="${person.homepage}">here</a>.</p>
	</btl:main>
	
</btl:template>

Please notice here:

  1. "http://btl.sourceforge.net/" is the BTL's namespace. All BTL's directives and instructions are in this namespace
  2. "btl:main" is a template's entry point, similar to the Java's main method.
  3. "${person.firstName}" is used to output "firstName" property of the "person" bean. Notice that the same construct can be used in an attribute value.
  4. Whenever "${...}" is used, we don't care if the result contains special characters (such as ampersand or angle brackets) or not, they're automatically handled by the BTL.
  5. BTL template is an XML, thus it follows XML rules for defining special characters, in this case "&amp;".
  6. "img" tag is closed, although HTML doesn't require this. It has to be closed in BTL, b/c valid XML is required at all times. However, HTML renderer will output this tag according to the HTML standard.
  7. The only template parameter in this example "person" is passed to the main-macro. Just like in the XSLT, all parameters must be defined somewhere in the template.

Usual Suspects: If, For-Each, etc

BTL has a comprehensive set of directives and instructions, including branches, cycles, macro calls and others. If you're familiar with XSLT, you'll find most of the XSLT instructions here in some form.
<btl:template xmlns:btl="http://btl.sourceforge.net/">
	
	<btl:main>
		<btl:param name="person"/>
		
		<btl:if expr="person">
			<h1>Hi ${person.firstName}!</h1>
		</btl:if>
		
		<p>Siblings: 
			<btl:for-each var="sibling" expr="person.siblings" status="s">
				<btl:if expr="s.hasPrev">, </btl:if>
				<btl:text>${sibling.fullName}</btl:text>
			</btl:for-each>
		</p>
		
	</btl:main>
	
</btl:template>
  1. BTL uses boolean conversion rules (see if-statement above) similar to XSLT. For example, a string is evaluated to true if it's not empty, object is evaluated to true if it's not null, collection is evaluated to true if it's not empty, etc.
  2. "Foreach" above uses status variable, which provides cycle information, such as index, "hasPrev" and "hasNext" flags.
  3. Similar to XSLT, you can define variables and intialize them with scalar values, objects or output buffer. Unline XSLT, BTL allows re-assigning variable values.

Macros

Just like almost in any other language BTL has macros (analogous to XSLT's templates). Macro is defined using "btl:macro" directive.
<btl:template xmlns:btl="http://btl.sourceforge.net/"
	xmlns:bte="http://btl.sourceforge.net/exec"
	xmlns:my="http://example.com/my">
	
	<btl:macro name="hello">
		<btl:param name="person"/>
		
		<btl:text>Hi ${person.firstName}!</btl:text>
	</btl:macro>
	
	<btl:macro name="my:hello">
		<btl:param name="person"/>
		
		<btl:text>Hi again ${person.firstName}!</btl:text>
	</btl:macro>
	
	<btl:main>
		<btl:param name="person"/>
		
		<h1>
			<btl:call name="hello">
				<btl:param name="person" expr="person"/>
			</btl:call>
		</h1>

		<h1>
			<btl:call name="my:hello">
				<btl:param name="person" expr="person"/>
			</btl:call>
		</h1>
		
		<!-- OR -->
		
		<h1><bte:hello person="person"/></h1>

		<h1><my:hello person="person"/></h1>
	</btl:main>
	
</btl:template>
  1. Macro's name can be in the default (empty) or user-defined namespace.
  2. There're two ways to call a macro: explicit (using "btl:call" instruction) and implicit (using tag with macro's qualified name). To distinguish implicit macro-call form from the output tags, "http://btl.sourceforge.net/exec" namespace should be used for macros in the default namespace.
  3. Macro's execution can be parameterized using "btl:param".

Match-Macros

Overall, match-macro is very similar to macro with an exception that it has two additional attributes: "target" and "match". Attribute "target" specify the name by which the target object will be referred in both macro and match attribute. Attribute "match" specifies expression that should evaluate to true for macro to be selected from all possible macros. Optional attribute "priority" can be used to resolve potential matching conflicts.
<btl:template xmlns:btl="http://btl.sourceforge.net/"
	xmlns:bte="http://btl.sourceforge.net/exec">
	
	<btl:match-macro name="renderPerson" target="p">
		<btl:text>${p.fullName}</btl:text>
	</btl:match-macro>

	<btl:match-macro name="renderPerson" target="p" match="p.age lt 18">
		<btl:text>${p.firstName}</btl:text>
	</btl:match-macro>

	<btl:match-macro name="renderPerson" target="p" match="p.age gte 18 and p.gender == 'male'">
		<btl:text>Mr. ${p.lastName}</btl:text>
	</btl:match-macro>

	<btl:match-macro name="renderPerson" target="p" match="p.age gte 18 and p.gender == 'female'">
		<btl:text>Mrs. ${p.lastName}</btl:text>
	</btl:match-macro>
	
	<btl:main>
		<btl:param name="person"/>
		
		<h1>Hi 
			<btl:apply name="renderPerson" target="person"/>
		</h1>
		
		<!-- OR -->
		
		<h1>Hi <bte:renderPerson btl:target="person"/></h1>
	</btl:main>
	
</btl:template>
				
  1. Just as in the case of btl:macro, there're two forms of invoking match-macro: explicit (using btl:apply) and implicit (using macro's name with namespace or default "http://btl.sourceforge.net/exec" namespace).

More samples coming...

  • Macros and nested content (btl:nested)
  • Variables: scope, assign/reassign
  • Buffer variables (embedded XML support)
  • Functions
  • Importing templates and macro precedence
  • Special macro library for HTML
  • BtlDoc
  • And much more...