An Oracle blog about BI Publisher

Dynamic Content using Sub Templates

I have written about sub templates in the past on a few occasions; the principle behind them is pretty simple. If you have common report components that can be shared across reports; be they blocks of text like standard contract clauses or maybe some common calculation or function, drop them into a sub template and share the love. Develop once, use everywhere!
A colleague was recently tasked with conditionally bringing into a report output, paragraphs of static text based on some user preferences. That’s an ideal candidate for a sub template approach; drop all of the paragraphs in to an RTF subtemplate and then just conditionally pull them in based on some boolean expressions.
You might, quite naturally think about conditionally importing a series of sub templates rather than defining one, with all the content. However, XSL does not allow the conditional import of sub templates so you must take the single template approach. You can of course, import multiple sub templates if you have a lot of content to bring in but in most cases I would expect a single sub template will suffice.

BIP does need to know what those paragraphs need to be for each user whether that’s as a set of parameter values or a data element in the incoming data set. For this example I have used both approaches and they work all flavors of BIP. Implementation of the sub template onto the servers is going to be a little different but the main principle is the same. I have mercilessly ripped out a nice graphic from Leslie’s (doc writer extraordinaire) documentation.

This is for the 11g version that supports loading sub templates into the report catalog as objects.  They can then be referenced in your main template using the import statement:


The subtemplate folder is going to be from the /SharedFolders  or /My Folders root. For instance, I have a sub template ‘paragraphs’ loaded into a ‘test’ folder under  Shared Folders. The import statement in my main template is ‘<?import:xdoxsl:///Test/ParaSubTemplate.xsb?>’

Update from Leslie

For those of you testing using your own My Folder area. The syn tax is

<?import:xdoxsl:///~username/path to subtemplate.xsb?> where username is your user name. For example: <?import:xdoxsl:///~tdexter/Subtemplates/Template1.xsb?>

Recommend you move them into the shared folder area in production.

For 10g you will either need to drop them into an accessible directory and use the file URI or mount them into the web server directory structure and access them via an http URI. I normally mount them in a directory under the ‘xmlpserver’ directory e.g J2EE_HOME\applications\xmlpserver\xmlpserver\subtemplates, a template is then accessible via the URI ‘http://server:port/subtemplates/template.rtf’

Make sure you set the Allow External References property to true for the report so that the sub template can be accessed.

The actual content of the sub template is pretty straight forward. It’s a series of paragraphs bounded by the ‘template’ command e.g.


<?end template?>

<?end template?>

<?end template?>
Now we have the dynamic content defined it’s a case of conditionally bringing it into the main template. For this example I have demonstrated two approaches; both rely on the required paragraph information to be in the main dataset:
1.    Using parameters to allow the user to select the appropriate paragraphs to be brought in. This means creating the parameters and ensuring that you have set the property on the data model to include the parameter values in the XML result set.

Once that’s done its just a simple case of using id statements to check if a given paragraph should be included:

<?if:.//PARA1='1'?><?call:para1?><?end if?>

This assumes my parameter is called PARA1 and that a ‘1’ means include it, it could easily be a ‘Y’ or ‘True’ value, you are just testing for it.

2.    Including a value in the data to define what paragraphs should be included. If you have stored what paragraphs should be included for a given entity i.e. customer, supplier, employee, etc. Then you can extract those values into the data set and test for them. For this demo I have a 5 character set of ‘1’s and ‘0’s to represent the paragraphs that need to be included e.g. 10110. I just use a substring command to find out if a particular paragraph needs to be included.

<?if:substring(.//PARAS,1,1)='1'?><?call:para1?><?end if?>

Where PARAS is the element holding the ‘1’s and ‘0’s string to be parsed.
You can of course use some other means of marking whether a paragraph needs to be included or not. It’s just a case of parsing out the values with a substring or similar command.
You should be able to generate dynamic content such as this:

 Notice that I have rendered the code so that I can see that the paragraphs are coming in i.e 10001 means we get paragraphs 1 and 5. I have built out demo files for the second method, available here.

Join the discussion

Comments ( 9 )
  • guest Thursday, December 1, 2011

    Hi Tim,

    Can we have company logo in the header and some other related information in the footer in a sub template

    and call them in all our custom EBS reports instead of putting the logo on each report template? That way if for some reason, we need to change the logo we can just modify the sub template instead of modifying all the templates.

    Please let me know.



  • guest Friday, December 2, 2011

    Hi Shree

    You certainly can, you'll just need to mount the sub template somewhere that can be accessed from the conc manager. Just on a web server will do fine



  • guest Wednesday, December 7, 2011

    I wish you could take it a step further and allow the path/filenames to be dynamic, as well as the name of the subtemplate to be dynamic as well. I can put the path/filename and subtemplate name in xml tags.

    Then, my master templates would not have to change as I add subtemplates. And I'd have 2 lines of code.

    For example, the import statement would be like


    and the call to the template would be like


  • Tim Wednesday, December 7, 2011

    The dynamic filename would be cool but its a limitation of or an imposed rule by the XSL standard and not BIP. The only way around it is to have some pre-processing of the template to generate the final template before it gets applied to the data i.e the template just contains a place holder for the filename. You then parse the template and insert the new filename value and then let the XSL processor go to town.

    Thats just not available today with the BIP server. At an API level, I could do it in my sleep.

    You could log an SR and ask support to log an enhancement request to investigate the feasibility of providing the pre-process hook.

  • guest Tuesday, December 20, 2011

    Hi Tim,

    As i understand catalogs are only supported in 11g. And Catalogs are necesary to use localization on subtemplates.

    So, does that mean that subtemplate localization is not possible in 10g ?

    My guess is, <?import:xdoxsl...?loc=${_XDOLOCALE}?> will not work till the time i wrap my RTF subtemplate into a calatog object.

    Also, http URI or file access does not support localizations

    Your views ?

    Many thanks


  • guest Tuesday, December 20, 2011

    Hi Tim,

    Does BIP 10g support usage of catalogs ? The purpose is to use subtemplate localisation in 10g.


  • Tim Tuesday, December 20, 2011

    In 10g you need to mount the sub template somewhere yourself. Its not supported like 11g. I think its covered in the text above?


  • guest Tuesday, December 20, 2011

    Yes, the above text does mentioning mounting of the subtemplates on an accessible folder or on server directory and then access them using URI.

    But, in that case we would be using <?import:file///...?> or <?import:http://...?> syntax to call the sub template. I dont think these 2 syntax give an option to pass locale.

    In that case, is there way BIP allows localization in 10G, except for conditionally calling seperate subtemplate based on the locate.

  • tim Wednesday, December 21, 2011

    I think your only option would be to do it in a sub template and pass it as a parameter. There is just not the infrastructure in 10g to handle sub templates like that. Can you move to 11g?


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.