Pulp EngineDocument Rendering
Get started

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.