All posts · BI Reports

BI Publisher and XSLT: Advanced Transformation Techniques

When RTF templates aren't enough, XSLT-FO gives you complete control over PDF layout — page settings, complex headers/footers, and pixel-perfect formatting.

Anurag Jangra · February 2, 2026 · 6 min read · ... views

When to use XSL-FO over RTF

RTF templates are excellent for most reports. Use XSL-FO (XSLT Formatting Objects) when you need:

  • Pixel-perfect multi-column layouts
  • Complex running headers/footers that differ by page
  • Fixed-position elements (watermarks, background images)
  • Reports that mix portrait and landscape sections
  • Precise control over pagination

XSL-FO basics

XSL-FO is an XML vocabulary for describing page layouts. BIP processes it using the Apache FOP engine:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:fo="http://www.w3.org/1999/XSL/Format">

<xsl:template match="/">
  <fo:root>
    <fo:layout-master-set>
      <fo:simple-page-master master-name="A4"
        page-height="29.7cm" page-width="21cm"
        margin-top="2cm" margin-bottom="2cm"
        margin-left="2.5cm" margin-right="2.5cm">
        <fo:region-body margin-top="1cm" margin-bottom="1cm"/>
        <fo:region-before extent="1cm"/>
        <fo:region-after extent="1cm"/>
      </fo:simple-page-master>
    </fo:layout-master-set>
    
    <fo:page-sequence master-reference="A4">
      <fo:static-content flow-name="xsl-region-before">
        <!-- Header content -->
        <fo:block font-size="10pt" color="grey">
          Company Confidential — <fo:inline><xsl:value-of select="//REPORT_DATE"/></fo:inline>
        </fo:block>
      </fo:static-content>
      
      <fo:flow flow-name="xsl-region-body">
        <!-- Main content -->
        <xsl:for-each select="//EMPLOYEES/EMPLOYEE">
          <fo:block font-size="11pt">
            <xsl:value-of select="NAME"/>
          </fo:block>
        </xsl:for-each>
      </fo:flow>
    </fo:page-sequence>
  </fo:root>
</xsl:template>
</xsl:stylesheet>

BIP’s simplified XSL syntax

BIP supports its own simplified tag syntax that can be embedded in XSL-FO:

<?for-each:EMPLOYEES?> ... <?end for-each?>
<?EMPLOYEE_NAME?>
<?xdofx:to_char(AMOUNT, '$999,999')?>

These are preprocessed by BIP before being passed to the FO processor.

Tables in XSL-FO

<fo:table width="100%">
  <fo:table-column column-width="30%"/>
  <fo:table-column column-width="40%"/>
  <fo:table-column column-width="30%"/>
  <fo:table-header>
    <fo:table-row>
      <fo:table-cell><fo:block font-weight="bold">Employee</fo:block></fo:table-cell>
      <fo:table-cell><fo:block font-weight="bold">Department</fo:block></fo:table-cell>
      <fo:table-cell><fo:block font-weight="bold">Salary</fo:block></fo:table-cell>
    </fo:table-row>
  </fo:table-header>
  <fo:table-body>
    <?for-each:EMPLOYEES?>
    <fo:table-row>
      <fo:table-cell><fo:block><?EMPLOYEE_NAME?></fo:block></fo:table-cell>
      <fo:table-cell><fo:block><?DEPT_NAME?></fo:block></fo:table-cell>
      <fo:table-cell text-align="right"><fo:block><?SALARY?></fo:block></fo:table-cell>
    </fo:table-row>
    <?end for-each?>
  </fo:table-body>
</fo:table>

Think Beyond the Implementation

Questions worth sitting with after reading this

01

Why is this architecture appropriate for this specific context — and where would it be the wrong choice?

02

What assumptions did we make that aren't stated explicitly? What happens if those assumptions are wrong?

03

What would break first if the requirements changed — volume doubled, a third system was added, or the deadline halved?

04

What alternatives did we reject, and why? Was the decision made on evidence — or habit?

AJ
Anurag Jangra
Oracle Cloud PaaS Consultant · OIC & VBCS Specialist

4.5+ years delivering enterprise Oracle Cloud integrations and VBCS applications across manufacturing, IT services, and financial sectors. OCI Certified — writes about real-world OIC, VBCS, SQL, and BI Publisher patterns from production experience.

Chat on WhatsApp