Migrate legacy reports
Convert an existing report into an editable first draft, review the fidelity report, then save it as an ordinary Pulp template. Imports are deterministic and do not execute SQL, Java, Groovy, VB, Crystal formulas or helper scripts. The translator accepts a restricted expression grammar.
API and SDKs
{
"format": "rdl",
"source": "<Report ...>...</Report>",
"options": { "key": "invoice", "name": "Invoice", "layout": "flow" }
}
Send this JSON to POST /templates/import. The same endpoint retains its multipart document-import mode. The JSON response contains template, report, sampleData and extractedAssets; it does not save a template. Admin and editor credentials may convert reports. Save the reviewed definition through POST /templates and its sample through PUT /templates/:key/sample.
const result = await client.templates.import('rdl', source, { key: 'invoice' })
result = client.templates.import_definition("rdl", source, {"key": "invoice"})
Typed report parameters use the existing parameter prompt contract. Handlebars accesses them as @params and expressions as $params; render-request parameters override defaults. Timestamp parameters use string prompts to retain clock precision and are marked approximated. Input-schema mirrors remain available where they do not conflict with dataset names.
Offline CLI
pulp-engine import ./legacy --from rdl --out ./templates --strict
pulp-engine import invoice.jrxml --from jrxml --dataset-path rows
pulp-engine import invoice.html --from html --dialect liquid
pulp-engine import invoice.xml --from crystal-xml --layout absolute
The CLI converts files or directories without an API connection. It writes a template JSON, .import-report.json, .sample.json and extracted image files for each input. Strict mode exits 1 when any feature is unsupported; approximations remain reviewable. Parse failures also produce exit 1, while valid files in the batch still convert. Duplicate output keys are rejected. Directory traversal skips symlinks and hidden entries.
Fidelity report
Each item has a sourcePath, status, feature, message and, where a corresponding editable node exists, nodeId. Expressions preserve their original source and translated target. Counts equal the item tallies. XML elements appear once across the item and expression inventories.
| Status | Meaning |
|---|---|
| mapped | The source feature has a supported representation. |
| approximated | The draft uses a different layout or expression convention; review it. |
| unsupported | The feature needs manual migration. Rendered unsupported objects become visible placeholders. |
Flow layout sorts band objects into reading order and uses columns for overlapping objects. It records the coordinate-to-flow approximation. Absolute layout keeps fixed band coordinates and records its weaker DOCX/PPTX portability. Imported output is not a promise of pixel parity.
The editor offers Open or import template, format detection, HTML dialect selection, a filtered review summary and a separate Load action. After loading, approximated nodes have dismissible hints and unsupported nodes have warnings in the Issues panel. Clicking an issue selects its node.
Embedded raster images remain inline for offline preview and also appear in extractedAssets with portable references. The editor uploads them into the current tenant and rewrites the references before loading. Remote resources are never fetched by the importer.
RDL / RDLC
| Source | Draft representation |
|---|---|
| 2005/01, 2008/01, 2010/01, 2016/01 report namespaces | Report body and page setup |
| DataSets and Fields | Typed array properties and sample rows |
| ReportParameters | Typed parameter prompts, defaults and static choices |
| Details Tablix | Table columns, header and aggregate footer |
| Row group field | Native table grouping |
| One supported column group | Pivot table |
| Visibility / Hidden | Negated expression condition |
| PageHeader / PageFooter | Page chrome; page-number spans |
| EmbeddedImages | Inline preview plus extracted upload assets |
| Queries | Advisory metadata, never executed |
Root field references outside a row use the first dataset item and are marked approximated. Complex crosstabs, source-specific grouping bands, unsupported functions and older Table/List structures require review or placeholders. Query parameters and database connection setup are not executed or recreated.
Microsoft documents RDL as an XML report definition with versioned schemas: RDL documentation.
JRXML
| Source | Draft representation |
|---|---|
| Legacy elements and JasperReports 7 element-kind syntax | Editable text, frames and band layout |
| Parameters and fields | Typed prompts and the main dataset, rows by default |
| Aligned columnHeader and detail | Table |
| Other detail layouts | Repeater |
| Title / summary | Content before / after detail |
| Simple field group | Native table grouping and bands |
| Sum variable | Aggregate footer or summary expression |
| noData | Empty message or children |
| Background, charts, subreports and unrecognised components | Review placeholders |
Numeric patterns such as #,##0.00 map to number formatting. Unsupported variables and Java/Groovy functions are reported instead of executed. See the official legacy schema and JasperReports 7 element examples.
Crystal XML
Binary .rpt files must first be exported with RptToXml on a Windows machine with the required SAP Crystal runtime:
RptToXml.exe invoice.rpt invoice.xml
| RptToXml source | Draft representation |
|---|---|
| ReportDefinition / Areas / Sections | Report and detail bands |
| TextObject / FieldHeadingObject | Text |
| FieldObject / DataSource | Field, parameter or supported formula binding |
| Detail fields | Table or repeater |
| Simple groups | Native group bands |
| PageNumber special field | Page-number span in page chrome |
| Parameters and database fields | Typed schema, prompts and sample data |
| Unsupported objects, formulas and subreports | Review placeholders |
Geometry is converted from twips. The implementation follows the upstream writer structure and uses original local fixtures. Representative customer-file validation remains pending by owner decision; treat Crystal support as a preview.
HTML dialects
| Source | Draft representation |
|---|---|
| Handlebars headings, text, inline marks, links and images | Existing deterministic HTML mapper |
| each / for around table rows | Data-bound table |
| Other loops | Repeater |
| if / else and common comparison helpers | Conditional and else branch |
| Liquid / Jinja upper, lower, default, date, number and currency filters | Allow-listed helpers, with review where conventions differ |
| CSS style blocks / supplied local CSS companions | Safe-mode custom CSS |
| Triple-stash | Escaped interpolation, reported |
| Scripts, event handlers, unsafe links, helper scripts | Removed or reported; never executed |
Complex filters, ancestor aliases in nested dialect loops, arbitrary helper functions and subreport resolution need manual review. Companion files are supplied explicitly through options.companions; the importer does not open filesystem paths or fetch URLs.
Limits and deployment
IMPORT_ENABLED defaults true and controls the legacy JSON mode independently of AI document imports. IMPORT_MAX_SOURCE_BYTES defaults to 4194304 and can be lowered to 1024 bytes. The complete JSON envelope must fit the configured limit. The standalone converter also caps source text at 4 MiB, XML/HTML depth at 64 and XML/source-tree elements at 20000. Names are limited to 128 characters, source paths to 2048 characters, individual XML expressions to 16 KiB and converted drafts to 16 MiB. The shared HTML mapper retains its 2000 editable-node and 512 KiB inline-image limits. HTML companions are capped at 1 MiB in total.
Malformed or hostile XML returns 422 import_parse_failed; unsupported namespaces return 422 import_format_unsupported; oversized requests return 413 payload_too_large; disabled conversion returns 503 service_unavailable. Capabilities expose import.formats so older or disabled servers keep the JSON-only editor flow.
The owner approved MIT for the private legacy-import package and the reused deterministic HTML mapping subset for CLI bundling. Rendering and PDF conversion remain commercial; see LICENSING.md.