Dynamic Content using Sub Templates
By Tim Dexter-Oracle on Dec 01, 2011
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.
<?template:para1?> … … <?end template?> <?template:para2?> … … <?end template?> <?template:para3?> … … <?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:
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.
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.