Oracle EBS XML Publisher RTF Template Syntax Reference
This reference lists the RTF template tags used in Oracle XML Publisher reports in EBS 12.1 and 12.2, with a working example for each. It covers loops, grouping, conditions, formatting, aggregates, variables and page layout.
| Tag/syntax | Category | What it does | Example | Notes |
|---|---|---|---|---|
<?for-each:GROUP?> ... <?end for-each?> | Loop | Repeats content for each element of the group | <?for-each:G_INVOICE_LINE?> ... <?end for-each?> | Place both tags in the same table row to repeat rows. |
<?for-each-group:ELEMENT;./KEY?> | Loop | Regroups flat data by a key | <?for-each-group:ROW;./CUSTOMER_NAME?> | Close with <?end for-each-group?>. |
<?for-each:current-group()?> | Loop | Loops over the rows of the current group inside for-each-group | <?for-each:current-group()?><?ITEM?><?end for-each?> | Only valid inside a for-each-group. |
<?sort:FIELD;'ascending';data-type='text'?> | Loop | Sorts the loop | <?for-each:G_LINE?><?sort:LINE_NUM;'ascending';data-type='number'?> | Put directly after the for-each tag. Use 'descending' to reverse. |
<?if:CONDITION?> ... <?end if?> | Condition | Shows content when the XPath condition is true | <?if:AMOUNT>1000?>Large<?end if?> | Use XPath operators such as =, !=, and, or. |
<?if@inlines:CONDITION?> | Condition | Inline condition inside a paragraph | <?if@inlines:STATUS='OPEN'?>Open<?end if?> | Use when the condition must not create a new paragraph. |
<?if@row:CONDITION?> | Condition | Condition applied to a whole table row | <?if@row:QTY>0?> | Hides the row when false. |
<?choose:?><?when:COND?> ... <?otherwise:?> | Condition | If, else if, else | <?choose:?><?when:STATUS='A'?>Approved<?end when?><?otherwise:?>Other<?end otherwise?><?end choose?> | Each when and otherwise needs its own end tag. |
<?format-date:DATE;'MEDIUM'?> | Format | Formats a date with an abstract format | <?format-date:INVOICE_DATE;'MEDIUM'?> | Masks SHORT, MEDIUM, LONG follow the report locale. Date must be canonical ISO 8601. |
<?format-date:DATE;'DD-MON-YYYY'?> | Format | Formats a date with an Oracle date mask | <?format-date:INVOICE_DATE;'DD-MON-YYYY'?> | Input must still be in canonical format (YYYY-MM-DD or YYYY-MM-DDThh:mm:ss). |
<?format-number:NUM;'999G999D99'?> | Format | Formats a number with an Oracle number mask | <?format-number:AMOUNT;'999G999D99'?> | G and D take the group and decimal separators of the locale. Number must be raw, without separators. |
<?xdofx:to_char(NUM,'999,999.99')?> | Format | SQL style formatting through the xdofx extension | <?xdofx:to_char(AMOUNT,'999,999.99')?> | xdofx supports a set of SQL functions. |
<?xdofx:nvl(FIELD,'N/A')?> | Function | Substitutes a value for null | <?xdofx:nvl(PO_NUMBER,'None')?> | SQL semantics inside xdofx. |
<?xdofx:decode(FIELD,'A','Approved','Other')?> | Function | SQL DECODE | <?xdofx:decode(STATUS,'A','Approved','I','Incomplete','Other')?> | Handy for code to label mapping. |
<?sum(FIELD)?> | Aggregate | Sum of all matching elements | <?sum(LINE_AMOUNT)?> | Wrap in format-number for display. |
<?sum(current-group()/FIELD)?> | Aggregate | Sum within the current group | <?sum(current-group()/LINE_AMOUNT)?> | Use inside for-each-group for group subtotals. |
<?count(ELEMENT)?> | Aggregate | Counts elements | <?count(G_INVOICE_LINE)?> | XPath count. |
<?xdoxslt:set_variable($_XDOCTX,'name',value)?> | Variable | Sets an updatable variable | <?xdoxslt:set_variable($_XDOCTX,'v_total',0)?> | XSL variables are not updatable; this extension is. |
<?xdoxslt:get_variable($_XDOCTX,'name')?> | Variable | Reads the variable | <?xdoxslt:set_variable($_XDOCTX,'v_total',xdoxslt:get_variable($_XDOCTX,'v_total')+AMOUNT)?> | Pattern for running totals. |
<?param@begin:P_NAME?> | Variable | Declares a parameter passed to the template | <?param@begin:P_ORG_NAME;'Default Org'?> then <?$P_ORG_NAME?> | Parameter names must match those passed by the data definition. |
<?split-by-page-break:?> | Layout | Forces a page break between loop iterations | Inside <?for-each:G_INVOICE?> just before <?end for-each?> | One document per element, for example one invoice per page set. |
<?for-each@section:GROUP?> | Layout | Loop that restarts headers, footers and page numbering per element | <?for-each@section:G_INVOICE?> ... <?end for-each?> | Use for batches of invoices or statements. |
<?template:NAME?> ... <?end template?> | Layout | Defines a sub template | <?template:address_block?>...<?end template?> | Can sit in the same file or an imported one. |
<?call-template:NAME?> | Layout | Calls a sub template | <?call-template:address_block?> | Pair with <?template:?> definitions. |
<?import:xdo://APP.TEMPLATE_CODE.lang.TERRITORY?> | Layout | Imports a sub template registered in Template Manager | <?import:xdo://XXAR.XX_ADDR_SUB.en.US?> | Use file:/// for a file path during local testing. |
<?start:body?> ... <?end body?> | Layout | Marks the body when you need headers and footers that hold fields | Header content above <?start:body?>, footer content below <?end body?> | Use when Word header and footer regions cannot hold the needed fields. |
<?attribute@incontext:property;value?> | Layout | Sets a formatting property on the enclosing element | <?if:AMOUNT<0?><?attribute@incontext:color;'red'?><?end if?> | Conditional formatting, for example red negatives or shaded rows. |
<?for-each@column:GROUP?> | Loop | Repeats columns for crosstab layouts | <?for-each@column:G_MONTH?><?MONTH?><?end for-each?> | Use with a row loop and cell values. |
<?position()?> | Function | Prints the position of the current element in the loop | <?for-each:G_LINE?><?position()?>. <?DESCRIPTION?><?end for-each?> | XPath function. Combine with if@row and mod for banded rows. |
<?FIELD?> | Function | Prints a field value | <?CUSTOMER_NAME?> | Template Builder inserts these as Word form fields so the tag is hidden. |
EBS 12.1 and 12.2 run the embedded XML Publisher (XDO) 5.6.x engine, which is older than standalone BI Publisher Enterprise. Later BI Publisher Enterprise releases add tags that the EBS engine does not support, so test each tag in Template Builder preview and in the instance.
Template review
Send us an RTF template and sample XML that misbehaves and we will return the corrected tags and the reason it failed in your XDO version.
Optional. The tool and every export work without this. No spam.
The date format gotcha
format-date only works on dates in canonical ISO 8601 form, such as 2026-10-22 or 2026-10-22T00:00:00.000-05:00. Data templates emit DATE columns in canonical form. Oracle Reports (RDF) XML output, and any query or PL/SQL that converts the date with TO_CHAR before it reaches the XML, emits a string like 22-OCT-26, and format-date then fails or prints the raw string. Keep dates as DATE in the query so the engine writes them in canonical form, or emit TO_CHAR(date, 'YYYY-MM-DD') explicitly. Date parameters of concurrent programs arrive as strings in the FND canonical format YYYY/MM/DD HH24:MI:SS, so convert them in the data layer before you format them in the template.
Template Builder for Word and preview
Build templates in Microsoft Word with the Template Builder add-in (part of BI Publisher Desktop). Load sample XML from the concurrent program (run it with output XML and save the output), then insert fields, tables and repeating groups. Template Builder writes the tags into hidden Word form fields, so the layout stays readable. Use Preview with PDF, Excel or HTML output to test before upload. Validate Template catches unbalanced tags. In EBS, register the data definition and template in XML Publisher Administrator, with the data definition code equal to the concurrent program short name, and set the program output format to XML.
Worked invoice template
A custom invoice prints one invoice per page set with lines, a subtotal and a red balance when overdue. The structure: <?for-each@section:G_INVOICE?> opens the loop so page numbers restart per invoice. The header block prints <?CUSTOMER_NAME?> and <?format-date:TRX_DATE;'DD-MON-YYYY'?>. A table row wraps <?for-each:G_LINE?><?sort:LINE_NUMBER;'ascending';data-type='number'?> and <?end for-each?> around <?DESCRIPTION?>, <?QUANTITY?> and <?format-number:EXTENDED_AMOUNT;'999G999D99'?>. Below the table, <?format-number:sum(G_LINE/EXTENDED_AMOUNT);'999G999D99'?> prints the total. The balance cell holds <?if:DAYS_LATE>0?><?attribute@incontext:color;'red'?><?end if?>. Close with <?end for-each?>.
Common mistakes
Unbalanced tags (a for-each without its end in the same table cell or row) cause errors that point to the wrong line. Group names are case sensitive and must match the XML exactly. Numbers formatted in SQL as strings with commas cannot be summed or reformatted, so send raw numbers. Paths are relative to the current loop context: inside a for-each, refer to parent fields with ../FIELD. Finally, an RTF built with tags from a newer BI Publisher release may preview in a new Template Builder but fail in EBS; keep to tags documented for the XDO version on your instance.
Frequently Asked Questions
How do I format a date in an Oracle RTF template?
Use <?format-date:FIELD;'MEDIUM'?> for a locale based format or <?format-date:FIELD;'DD-MON-YYYY'?> for an Oracle mask. The value must be a canonical ISO 8601 date in the XML. If the XML holds a string like 22-OCT-26, fix the data source rather than the template.
What is XML Publisher in Oracle Apps R12?
It is the reporting engine in EBS (product short name XDO) that merges XML data from a concurrent program or data template with a layout template, usually RTF, to produce PDF, Excel, HTML or RTF output. Templates and data definitions are managed in the XML Publisher Administrator responsibility.
How do I group data in an RTF template?
Use <?for-each-group:ROW;./KEY?> to group, then <?for-each:current-group()?> inside it to loop over the rows of each group. Use <?sum(current-group()/AMOUNT)?> for subtotals and close each tag with its matching end tag.
How do I keep a running total in an RTF template?
Use the updatable variable extensions: initialize with <?xdoxslt:set_variable($_XDOCTX,'v_total',0)?>, then inside the loop add to it with set_variable and get_variable, and print it with <?xdoxslt:get_variable($_XDOCTX,'v_total')?>. Plain XSL variables cannot be updated.
If you want report requests answered without building a template each time, a private AI layer on your EBS data can answer them directly on your own servers, and we can set that up.
Related Tools
Oracle EBS Forms Personalization Tables and Trigger Events Reference
The tables behind Forms Personalization, the trigger events and action types you can use, every common builtin, and the FNDLOAD commands to move rules between instances.
OracleOracle EBS Concurrent Program Registration Request Template
A request form that captures everything an EBS developer needs to register a custom concurrent program: executable, execution method, parameters, request group and incompatibilities.
OracleOracle EBS SQL for Concurrent Requests Generator
Build ready-to-run SQL for recent, running, pending and long-running concurrent requests from a few filter fields.
OracleOracle EBS Lookups, Value Sets and Flexfield Tables Reference
Every FND table and view you need to decode lookup codes, value set values, table-validated value sets, key flexfield segments and DFF ATTRIBUTE columns in EBS 12.1 and 12.2.
More Developer Tools tools
See all- Oracle EBS Onhand Quantity SQL Generator
- Oracle EBS BOM Explosion SQL Generator
- Oracle EBS Pending Transactions SQL Generator for Period Close
- Oracle EBS Public PL/SQL API Reference (OM, INV, PO, AP, AR, TCA, FND)
- Oracle EBS Forms FRM Error Codes Reference (FRM-92101, FRM-40735)
- Oracle EBS OE_ORDER_PUB.PROCESS_ORDER Script Generator
- Oracle EBS FND_REQUEST.SUBMIT_REQUEST Code Generator
- Oracle EBS PL/SQL Concurrent Program Generator (Package plus FND_PROGRAM Registration)
- Oracle EBS Concurrent Program Parameters and Responsibility SQL Generator
Keep exploring
Free tools
- Oracle EBS XML Publisher Data Template GeneratorFill in your query, parameters and elements and get a valid XML Publisher data template, its PL/SQL default package and the registration steps for R12.
- Oracle Fusion BI Publisher Report Specification TemplateDocument a BI Publisher report before you build it: purpose, data model, parameters, layout, schedule and security in one template.
- Oracle EBS Cost Management Tables ReferenceA lookup of the Oracle EBS tables behind item cost, WIP jobs, BOM, routing and inventory transactions used in manufacturing costing.
ERP fixes and how-tos
- How to Create a BI Publisher Report in Oracle EBSBuild an Oracle EBS BI Publisher report end to end: write the data model, register the data definition, design the RTF template, and wire it to a concurrent program.
- Oracle EBS Standard Reports by Module and Sample XML for BI PublisherHow to find and run Oracle EBS standard reports by module, and how to get sample XML data to design a BI Publisher template for an EBS report.
- How to set up BI Publisher output for a JD Edwards reportJDE BI means BI Publisher: how to attach an RTF template to a JD Edwards EnterpriseOne UBE version, what to configure first, and why it may print the old way.
Runs with your ERP
- BarTender and Oracle E-Business Suite: Label Printing from OracleHow BarTender prints labels from Oracle EBS using Oracle XML print requests and Integration Builder: methods, data flows, setup steps, pitfalls and AI help.
- Zebra Enterprise Connector with JD Edwards and Oracle EBS: XML to ZPL labelsHow Zebra's Enterprise Connector and XML-Direct Connect print barcode and RFID labels from Oracle EBS and JD Edwards by converting XML to ZPL: setup, pitfalls.
- Esker Order Management and Oracle E-Business SuiteHow Esker captures customer POs from email, fax and PDF and creates sales orders in Oracle EBS: integration, data flows, setup, pitfalls and a private AI layer.
AI on your ERP
- AI for Oracle E-Business Suite, Without Leaving On-PremHosting Oracle EBS 12.2 on-prem or in a private cloud? Add a private LLM over concurrent programs, interface tables and AP/PO data without moving to Fusion.
- AI for Oracle EBS in Industrial Manufacturing: WIP, MRP, and BOM Questions Answered DirectlyAI for Oracle E-Business Suite in industrial manufacturing: WIP jobs, BOMs, MRP, inventory and purchasing answered in plain English, private and read-only.
Integrations
- How to connect Power BI to Oracle E-Business SuiteConnect Power BI to Oracle E-Business Suite: Oracle connector, reporting replica, on-premises data gateway, manufacturing dashboards and natural-language Q&A.
- How to connect Power BI to Oracle Fusion Cloud ERPHow to connect Power BI to Oracle Fusion Cloud ERP: BICC to a warehouse, BI Publisher and REST options, manufacturing dashboards and natural-language Q&A.