Skip to main content
Question

XML Templater empty subtemplate

  • September 12, 2017
  • 2 replies
  • 21 views

jdh
Contributor
Forum|alt.badge.img+28
  • Contributor

I am looking for a way to have a "default value"  if there is no data in a subtemplate.

 

 

Consider the house, village example from the help documentation.  If we have multiple villages with an id, and multiple houses with a village_id,  we can set the Root template to 

<village>
<name>{fme:get-attribute("name")}</name>
<population>{fme:get-attribute("population")}</population>
<houses>
{fme:process-features("HOUSE""village_id", fme:get-attribute("id"))}
</houses>
</village>

and the correct houses will be associated with the correct village.

 

and you could end up with an output like

 

<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>

However if there are no houses for a specific village, the result is

<village>
	<name>Anytown, USA</name>
	<population>2568</population>
	<houses>

	 </houses>
</village>
Instead of empty space, I would like to specify an alternate value.

Something like

<village>
	<name>Anytown, USA</name>
	<population>2568</population>
	<houses>No houses available</houses>
</village>

In my data the root feature (village) has no information as to the number of subfeatures (houses) associated with it, so I can't simply use a conditional like

<houses>
{ if( (fme:get-attribute("housecount") eq "0") )
then {fme:process-features("HOUSE""village_id", fme:get-attribute("id"))}
else "No houses available" 
}
</houses>

Any thoughts?  I have several thousand root features and several hundred thousand subfeatures so I would like to avoid using a featureMerger on the data prior to the XMLTemplater if at all possible.

2 replies

takashi
Influencer
  • September 12, 2017

Hi @jdh, this expression might help you.

<village>
<name>{fme:get-attribute("name")}</name>
<population>{fme:get-attribute("population")}</population>
{
let $houses := <houses>{
    fme:process-features("HOUSE""village_id", fme:get-attribute("id"))
}</houses>
return if (0 < fn:count($houses/house))
then $houses
else <houses>No houses available</houses> 
}
</village>

takashi
Influencer
  • September 13, 2017
takashi wrote:

Hi @jdh, this expression might help you.

<village>
<name>{fme:get-attribute("name")}</name>
<population>{fme:get-attribute("population")}</population>
{
let $houses := <houses>{
    fme:process-features("HOUSE""village_id", fme:get-attribute("id"))
}</houses>
return if (0 < fn:count($houses/house))
then $houses
else <houses>No houses available</houses> 
}
</village>
This expression is also available.

 

<village>
<name>{fme:get-attribute("name")}</name>
<population>{fme:get-attribute("population")}</population>
<houses>{
let $houses := {
    fme:process-features("HOUSE""village_id", fme:get-attribute("id"))
}
return
if (0 < fn:count($houses)) then $houses else "No houses available"
}</houses>
</village>
For what it's worth, in my experiences, XMLTemplater with a sub template worked not so efficient in many cases. Depending on the conditions, processing a list attribute within a single root expression could be faster. e.g.

0684Q00000ArMhGQAV.png

<village>
<name>{fme:get-attribute("name")}</name>
<population>{fme:get-attribute("population")}</population>
<houses>{
let $houses := {
    let $owners := fme:get-list-attribute("_list{}.owner")
    for $address at $i in fme:get-list-attribute("_list{}.address")
    return
    <house>
        <address>{$address}</address>
        <owner>{$owners[$i]}</owner>
    </house>
}
return
if (0 < fn:count($houses)) then $houses else "No houses available"
}</houses>
</village><br>

Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings