When a template is evaluated, it can only access the attributes of the feature which is currently being processed. In order to allow a template to access the attributes of multiple features, the concept of sub-templates was introduced. Using the fme:process-features function, the transformer can evaluate a sub-template on a set of features, and then insert the results into the first template. In the transformer interface, each sub templates will be given a name. This name will then be used in the fme:process-features call to identify the sub-template to evaluate. In addition, a transformer input port will be created for each sub-template. The sub-template will be processed on features which enter the corresponding transformer input. Features which enter one of these input ports will be referred to as sub-features.
In the following example, the Root template constructs a <village> element, with information from a single feature. It then populates the <houses> element, using attribute values from features which entered the HOUSE input port.
<village>
<name>{fme:get-attribute("name")}</name>
<population>{fme:get-attribute("population")}</population>
<houses>
{fme:process-features("HOUSE")}
</houses>
</village>
The template associated with the HOUSE input port creates a <house> element.
<house>
<address>{fme:get-attribute("address")}</address>
<owner>{fme:get-attribute("owner")}</owner>
</house>
If a single feature enters the Root input and two features enter the HOUSE input, the resulting XML document could look like this:
<village>
<name>Anytown, USA</name>
<population>2568</population>
<houses>
<house>
<address>123 Main Street</address>
<owner>John Doe</owner>
</house>
<house>
<address>324 Main Street</address>
<owner>Jane Doe</owner>
</house>
</houses>
</village>
A template may call many sub-templates. For example, in the above example, we could add another sub-template named BUSINESS, and then used the process-features function to run this sub-template from the Root template. Additionally, a sub-template may run another sub-template, with the restriction that a sub-template may not directly or indirectly run itself.
Selecting the Sub-Features to Process
Often there is a hierarchical structure to the features that enter the XMLTemplater. For example, each village will have a number of houses, and each house will have several rooms, etc. If the fme:process-features function is used as described above, the resulting document will probably not be correct. Suppose there are two villages, each with five houses. Each village and house is represented by a separate FME feature. The village features are routed into the Root input port while the house features are routed into the HOUSE input port.
If the transformer is run with the above templates, there will be two output features, as expected. However, both of the <village> elements will include all ten <house> elements. The correct behavior is to only evaluate the sub-template on the HOUSE features which correspond to the current village feature.
The fme:process-features function provides a way to do this. Additional function parameters may be used to filter the sub-features which are to be processed. The second parameter is a list of attribute names, and the third is a list of attribute values. Only sub-features whose attributes match the given list of attribute names and values will be processed.
This function call will evaluate the HOUSE sub-template on all HOUSE features whose village_id attribute matches the id attribute of the current feature.
fme:process-features("HOUSE", "village_id", fme:get-attribute("id"))
More than one attribute/value pair can be specified. In this case, the attribute names and attribute values have to be contained in parenthesis. The following function call will evaluate the HOUSE sub-template on all HOUSE features whose village_id attribute matches the id attribute of the current feature, and whose num_floors attribute is 2.
fme:process-features("HOUSE", ("village_id","num_floors"), (fme:get-attribute("id"), 2) )
Running Multiple Sub-Templates with a Single Function Call
It is possible to evaluate multiple sub-templates using a single function call. Simply pass a list of template names to the fme:process-features function. The sub-templates will be evaluated on each of the sub-features named in the list. The features will be processed in the order that they entered the transformer. The following function call processes the HOUSE and BUSINESS sub-templates:
fme:process-features( ("HOUSE","BUSINESS") )
The sub-feature selection parameters may still be used when the fme:process-features function is used to evaluate multiple sub-templates.
Running a Sub-Template on the Same Feature
It is possible to evaluate a sub-template using the same feature which is being used to evaluate the current template. The fme:process-template function takes a name, or list of names, of sub-templates which should be evaluated. These templates will be evaluated and the results will be inserted into the current template. To evaluate a template, just enter the name of the sub-template as a function parameter. For example, while a HOUSE feature is being processed, we could evaluate the OWNER template using the following function call. The OWNER template will be evaluated using the feature that entered the HOUSE input port.
fme:process-template("OWNER")
To evaluate a set of templates, pass a list of names:
fme:process-template( ("OWNER","ADDRESS") )
This technique may be used to modularize XML templates, by moving repeated template structures into a single place. For example, if both houses and businesses have an address, the address could be extracted into an ADDRESS template, and the HOUSE and BUSINESS templates could then use the fme:process-template function to insert the address values. This way, the address template does not have to be duplicated inside the HOUSE and BUSINESS templates.