Simple Example
----------------
Assume that the following XML document is a target document we generate.

  <?xml version="1.0"?>
  <members>
    <member uid="&amp;001">
      <name>Foo</name>
      <age>22</age>
    </member>
    <member uid="&amp;002">
      <name>Bar</name>
    </member>
  </members>

We first prepare the following template 'text' and create a template object
'template'.

  text = <<EOF
  <?xml version="1.0"?>
  <members>
    <member id="members">
      <name id="name"></name>
      <age id="age"></age>
    </member>
  </members>
  EOF

  require 'xtemplate'
  template = XTemplate::XMLTemplate.new(text)

We then expand the template with the following data.

  data = {
    "members" => [
      {"@uid" => "&001", "name" => "Foo", "age" => 22},
      {"@uid" => "&002", "name" => "Bar"},
    ]
  }
  doc = template.expand(data)
  puts(doc.to_s)

Each '@uid' represents an attribute. All strings/objects in given data are
automatically sanitized. 'doc' is a result of expanding the template.
The following document is generated.

  <?xml  version="1.0"?>
  <members>
    <member uid="&amp;001">
      <name>Foo</name>
      <age>22</age>
    </member><member uid="&amp;002">
      <name>Bar</name>
    
    </member>
  </members>

If you would like to pass sanitized strings/objects to xtemplate, use
XTemplate::SanitizedString (See samples/sample1.rb).
We can successively output strings using Template#expand2 as follows:

  template2 = XTemplate::XMLTemplate.new(text2)
  template2.expand2($stdout,data)

The template object dumps generated strings using a method '<<'.
Also, a given data is modified by an expansion. If you don't want
to modify it, give options like this:

  template2.expand2($stdout,data, :keep_data => true)


Namespace of XTemplate
-----------------------
If you define a namespace with the URI "http://xtemplate.sourceforge.net/xtemplate",
the following tags are available.

  - <select id="..." [propagation="yes|no"]>, <value-of id="..." [propagation="yes|no"]>
  - <attribute name=".." [id="..."]>
  - <element name=".." [id="..."]>
  - <copy-of id="..." [with="..."]>
  - <import src="..">
  - <include src="..">
  - <template [name="..."]>
  - <expand id="..." [strip="yes|no"]>

When you would not like to eliminate "<age></age>" in <member>..</member>, use
the following template.

  text = <<EOF
  <?xml version="1.0"?>
  <members>
    <member id="members">
      <name id="name"></name>
      <age><xt:value-of id="age" xmlns:xt="#{XTemplate::BIND_URI}" /></age>
    </member>
  </members>
  EOF

'<xt:value-of ...>' is replaced with the indicated data. '<xt:select ...>' is
equivalent to '<xt:value-of ..>', where XTemplate::BIND_URI is
'http://xtemplate.sourceforge.net/xtemplate'.

Attribute Substitution
----------------------
Attribute values are replaced with specified data by using special form '@{...}'
such as <member id="members" uid="@{uid}">. Consider the following expansion data.

  data = {
    "members" => [
      {"uid" => "&001", "name" => "Foo", "age" => 22},
      {"uid" => "&002", "name" => "Bar"},
    ]
  }

If we give the following template, we can obtain the same result as the foregoing.

  text = <<EOF
  <?xml version="1.0"?>
  <members>
    <member id="members" uid="@{uid}">
      <name id="name"></name>
      <age id="age"></age>
    </member>
  </members>
  EOF


XTemplate's XPath
------------------
We can specify a path to data in each attribute 'id' as follows.

  text2 = <<EOF
  <?xml version="1.0"?>
  <members>
    <name id="/members/name"></name>
  </members>
  EOF
  template2 = XTemplate::XMLTemplate.new(text2)
  doc2 = template2.expand(data)
  print(doc2)

We get the following document as the result of the above.

  <?xml  version="1.0"?>
  <members>
    <name>Foo</name><name>Bar</name>
  </members>

The path format is very similar to W3C's XPath, however our XPath is not
exactly same as W3C's XPath (See samples/xpath.rb) and roughly implemented.

There is a special mechanism in XTemplate's XPath which is called 'action'.
For example, we prepare the following template.

<?xml version="1.0"?>
<members>
  <member id="/members[age>=20]{copy(uid,@uid);sort(age)}">
    <name id="name" />
    <age id="age" />
  </member>
</members>

We first choose only members who are older than 20 by [age>=20], which
syntax is similar to W3C XPath. '{'...'}' is an action in which we can reconstruct
collected data. 'copy(uid,@uid)' rename the key 'uid' with '@uid', and sort members
with a value of each 'age'. We then give the following data,

{'members' => [
   {'name' => 'name1', age => 22, 'uid' => 1},
   {'name' => 'name2', age => 18, 'uid' => 2},
   {'name' => 'name3', age => 30, 'uid' => 3},
   {'name' => 'name4', age => 23, 'uid' => 4},
]}

and get the following result.

<?xml  version="1.0"?>
<members>
  <member uid="1">
    <name>name1</name>
    <age>22</age>
  </member><member uid="4">
    <name>name4</name>
    <age>23</age>
  </member><member uid="3">
    <name>name3</name>
    <age>30</age>
  </member>
</members>

In the same mechanism, we can store and restore the collected data
using an internal stack. Some of such actions are 'push(stackname)'
and 'pop(stackname)'. The life time of an internal stack is same as
one of the current thread. So we can pass collected data across tags.

About XData
------------
XTemplate::XData is a module which has a method 'to_hash()'. This method
must be redefined in a class including the module, and it must return
a Hash object. XTemplate regard an object including the module as a Hash
data for expanding a template.

Using XMLDocument
------------------
We can give an object instantiated from XTemplate::XMLDocument as expansion
data, since the class includes XTemplate::XData. The conversion mechanism
is as follows, though this is an experimental specification.

* All elements are converted into a Hash data which consists of
  single element.
  EX: <tag>...</tag>   => {'tag' => ...}

* Children elements are converted into an Array data which consists of
  Hash data of single element.
  EX: <tag><tag1>1</tag1>...</tagN>N</tagN></tag>
      => {'tag' => [{'tag1' => '1'}, ..., {'tagN' => 'N'}]}

* All attributes are regarded as children of an elements having the attributes.
  EX: <tag attr1="1" ... attrN="N">...</tag>
      => {'tag' => [{'@attr1' => '1', ..., '@attrN' => '2'}]}

So <tag><tag1>1</tag1>...<tagN>N</tagN></tag> is normally transformed
to {'tag' => [{'tag1' => '1'}, ..., {'tagN' => 'N'}]}. However, in an
expansion process, the array object is automatically transformed to
something like {'tag1' => '1', ..., 'tagN' => 'N'}, if there is no
duplicated tag.

Replacing/Expanding Expansion Data 
-----------------------------------
XTemplate can replace an expansion data with the result of expansion by
using the tag 'expand' as follows.

<?xml version="1.0" encoding="EUC-JP"?>
<xt:template xmlns:xt="#{XTemplate::BIND_URI}">
<xt:expand id="//member">
  <a href="mailto:@{email}">(<xt:value-of id="@uid" />)<xt:value-of id="name" />
</a>
</xt:expand>
<members>
   <xt:select id="/members/member" />
</members>
</xt:template>

In this example, <xt:expand id="//member">...</xt:expand> replaces the value of
{'member' => value} with the result of expanding itself. If we give the following
data,

data = {
  'members' => [
    {'member' => {'name' => 'name1', '@uid' => 1, 'email' => 'name1@com'}},
    {'member' => {'name' => 'name2', '@uid' => 2, 'email' => 'name2@com'}},
    {'member' => {'name' => 'name3', '@uid' => 3, 'email' => 'name3@com'}},
  ]
}

a value of each {'member' => ...} is replaced as follows.

  {'member' => '<a href="mailto:name1@com">(1)name1</a>'}
  {'member' => '<a href="mailto:name2@com">(2)name2</a>'}
  {'member' => '<a href="mailto:name3@com">(3)name3</a>'}

So the result of expansion is as follows.

<?xml version="1.0" encoding="EUC-JP"?>
<members>
   
  <a href="mailto:name1@com">(1)name1</a>

  <a href="mailto:name2@com">(2)name2</a>

  <a href="mailto:name3@com">(3)name3</a>

</members>


Replacing Sub-template
-----------------------
We can directly access a sub-template which is enclosed by <template name="...">
and </template> by using a key specified by the "name" attribute. For example,
We replace a sub-template with a copy of another sub-template with the following
script.

t1 = XTemplate::XMLTemplate.new(<<EOF)
<?xml version="1.0"?>
<html xmlns:xt="#{XTemplate::BIND_URI}">
<body>
  <xt:template name="ul">
  <ul>
    <li xt:id="names" />
  </ul>
  </xt:template>
</body>
</html>
EOF

t2 = XTemplate::XMLTemplate.new(<<EOF)
<?xml version="1.0"?>
<html xmlns:xt="#{XTemplate::BIND_URI}">
<body>
  <xt:template name="ol">
  <ol>
    <li xt:id="names" />
  </ol>
  </xt:template>
</body>
</html>
EOF

print(t1.expand(data, :keep_data => true),"\n")
t1['ul'] = t2['ol']
print(t1.expand(data),"\n")

The following XML document is an output.

<?xml version="1.0"?>
<html>
<body>
  <ul>
    <li>name1</li><li>name2</li><li>name3</li>
  </ul>
</body>
</html>
<?xml version="1.0"?>
<html>
<body>
  <ol>
    <li>name1</li><li>name2</li><li>name3</li>
  </ol>
</body>
</html>


For Debugging
-------------
If the result of expanded template is not what you want, please use the
action 'p()' in XPath for inspecting an expansion data. If using 'p(stderr)',
the expansion data is printed to $stderr.

Speedup Tips
-------------
* XTemplate::XMLTemplate#dump(), XTemplate::XMLTemplate.load(str)
  XMLTemplate#dump() serializes the object and returns a string object.
  XMLTemplate.load(str) is a singleton method for loading a serialized
  object and returns a XMLTemplate object. However, this method is not
  so effective with respect to expanding a template.

* XTemplate::use_simple_xpath()
  This function speeds up evaluation of XPath expression. However we can't
  use actions and conditions after calling this function.

* XTemplate::use_simple_expand()
  More speedup! However we can't use any XPath expression after calling this
  function.

* Install 'xtemplate_ext'
  'xtemplate_ext' is an extension module in which some functions are
  implemented in C. If you have an environment to make the extension,
  I recommend you to run 'install.rb config' with '--with-ext' option.

XTemplate's XPath Syntax
------------------------

  xpath := apath
         | rpath
         | xpath '|' xpath
         | xpath '?' xpath

  apath := '/' rpath

  rpath := node opts '/' rpath
         | node opts

  node  := '@' attr           # attribute
         | data-id            # data ID
         | '*'                # all nodes
         | '**'               # all nodes and children
         | '@*'               # all attributes
         | <empty>

  opts  := opt opts
         | <empty>

  opt   := '{' action '}'     # data reconstruction
         | '[' filter ']'     # filter

  action := action;action
          | node
          | p()
          | p(stderr)
          | sort()
          | sort(key)
          | reverse()
          | node()
          | text()
          | attr(a,b,...)
          | unattr(a,b,...)
          | copy(a,b)
          | rename(a,b)
          | delete(a,b,...)
          | tag(a)
          | untag(a)
          | index(a)
          | index(a,i)
          | size()
          | push(a)
          | pop(a)
          | pop_all(a)
          | clear_stack(a)
          | int()
          | float()
          | dump()
          | dump(tag)
          | time(fmt)
          | time(fmt,tag)
          | mktime(fmt)
          | sanitize()
          | unsanitize()
          | import(xml://file)
          | import(yaml://file)
          | import(data://file)
          | import(var:xxx)
          | import(dbi:xxx, query)
          | import(soap://..., namespace, method, arg0,...)
          | import(xmlrpc://..., method, arg0,...)
          | <empty>

  filter := cond              # select nodes which satisfies the condition.
          | beg ',' n         # apply the method [](beg,n)
          | beg '..' end      # apply the method [](beg..end)
          | pos               # apply the method [](pos)

  cond := 'not' cond
        | cond 'and' cond
        | cond 'or'  cond
        | node                # true if there is a node 'node'.
        | expr op expr
        | 'int' '(' expr ')'
        | 'float' '(' expr ')'

  expr := node | int | string
  op   := '&lt;' | '&gt;' | '&lt;=' | '&gt;=' | '=' | '!=' | '=~' | '!~'
