Skip to content

Latest commit

 

History

7 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

Crystal Reports XML Diff

A standalone Blazor WebAssembly application that compares two Crystal Reports definitions (exported to XML) and highlights only the differences that actually affect how a report renders — field layout, section dimensions, text content, data sources, suppression conditions, formulas and print options.

Everything runs entirely in the browser. No file is ever uploaded to a server, which makes the tool safe to use with sensitive report definitions.

This project is a decoupled, self-contained reimplementation of an internal Cirrus demo tool. The comparison logic was extracted into a reusable, framework-agnostic library and paired with a brand-new UI so it can run on its own without the surrounding platform.


What it is for

Crystal Reports .rpt files are opaque binaries, so reviewing what changed between two versions of a report is painful. Standard text diff tools are useless on the exported XML because they drown you in noise: reordered nodes, regenerated identifiers, connection strings and other metadata that have no visual impact on the printed report.

This tool solves that by performing a semantic, rendering-focused diff:

  • It understands the report structure (areas, sections, objects, formulas).
  • It compares only the properties that change the output.
  • It ignores ordering, metadata and database connection details.
  • It produces both a visual side-by-side layout and a categorized, filterable change list.

Typical uses:

  • Reviewing a report change before shipping it.
  • Auditing what a colleague modified in a report.
  • Troubleshooting "the report looks different" reports.

How it works

1. Export the report to XML

.rpt files (Crystal Reports 11) are converted to XML with the open-source RptToXml tool. The app accepts .xml files (or .txt files containing XML).

2. Load two files

Upload the original (old) report on the left and the modified (new) report on the right.

3. Compare

Clicking Compare runs two independent passes over the documents:

  • XmlDiffEngine produces the textual, categorized list of differences.
  • ReportLayoutParser builds a geometric model of each report and annotates every element as unchanged / added / removed / modified so the two layouts can be drawn side by side.

4. Review

  • A visual preview renders both reports as scaled pages, colour-coding each element by its change type.
  • A detailed change summary groups differences by section and category and can be filtered by change type, category and section.

Architecture

The solution is split into three projects to keep the domain logic fully decoupled from the UI and independently testable.

Crystal-Reports-Diff.sln
├── CrystalReportsDiff.Core          # Pure, framework-agnostic domain library
│   ├── Models/                      # ReportLayout, XmlDiffEntry, DiffSummary, ...
│   ├── Comparison/                  # ICrystalReportComparer + XmlDiffEngine
│   │   └── Rules/                   # One IReportComparisonRule per concern
│   ├── Layout/                      # IReportLayoutParser + ReportLayoutParser
│   └── Internal/                    # Shared XML helpers
├── Crystal-Reports-Diff             # Blazor WebAssembly app (the UI)
│   ├── Pages/                       # CrystalReportsDiffPage
│   ├── Components/                  # ReportLayoutView (visual preview)
│   └── Features/CrystalReportsDiff/ # CrystalReportsDiffState (presentation model)
└── CrystalReportsDiff.Core.Tests    # xUnit tests for the Core library

Design decisions

  • Separation of concerns — all comparison/parsing logic lives in CrystalReportsDiff.Core and has no dependency on Blazor. The web app is a thin presentation layer over it. The library could just as easily power a CLI, a desktop app or a server API.
  • Strategy patternXmlDiffEngine owns no comparison logic itself. It runs an ordered set of IReportComparisonRule strategies (PrintOptionsComparisonRule, AreasComparisonRule, FormulaFieldsComparisonRule, RunningTotalsComparisonRule). Each rule is independent, single-responsibility and individually testable, and callers can add, remove or reorder rules.
  • Programming to interfaces + dependency injection — the UI depends on ICrystalReportComparer and IReportLayoutParser, registered in Program.cs, not on concrete types.
  • Presentation modelCrystalReportsDiffState holds all UI state and orchestrates the services, keeping the Razor markup declarative and the state logic unit-testable.
  • Clean code — small focused methods, meaningful names, no dead code, XML documentation on the public surface.

Running the app

Requirements: .NET 9 SDK.

cd Crystal-Reports-Diff
dotnet run --project Crystal-Reports-Diff

Then open the printed URL (for example http://localhost:5219).


Running the tests

cd Crystal-Reports-Diff
dotnet test

The CrystalReportsDiff.Core.Tests project covers the comparison engine (every change category, summary consistency, rule composition, invalid input) and the layout parser (parsing, defaults, change annotation, twip scaling).


What is compared (and what is ignored)

Compared (affects rendering) Ignored (no visual impact)
Object position and size Node ordering
Section height Database connection details
Text content Save/preview metadata flags
Data source expressions Class factory names
Suppression / visibility conditions Parameter/sort/group internal state
Page size, orientation, margins Report options metadata
Formula field expressions
Running total operations

Tech stack

  • .NET 9 / C#
  • Blazor WebAssembly (standalone)
  • Bootstrap 5 + Bootstrap Icons (via CDN) for styling
  • xUnit for testing

About

A .NET tool for analyzing and comparing Crystal Reports (.rpt) definitions through RPT-to-XML conversion and structured diff analysis.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages