{"id":32867851,"url":"https://github.com/psynetic-software/camt-parser","last_synced_at":"2026-05-18T07:32:54.387Z","repository":{"id":322849588,"uuid":"1091107113","full_name":"psynetic-software/camt-parser","owner":"psynetic-software","description":"CAMT XML Parser for SEPA banking data (C++).","archived":false,"fork":false,"pushed_at":"2025-11-06T18:18:08.000Z","size":35,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-11-06T18:19:47.467Z","etag":null,"topics":["banking","camt","camt052","camt053","camt054","cpp","csv","finance","mit","parser","qif","sepa","swift","xml"],"latest_commit_sha":null,"homepage":"https://www.taxpool.net/","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/psynetic-software.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-06T15:08:24.000Z","updated_at":"2025-11-06T18:18:11.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/psynetic-software/camt-parser","commit_stats":null,"previous_names":["psynetic-software/camt-parser"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/psynetic-software/camt-parser","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/psynetic-software%2Fcamt-parser","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/psynetic-software%2Fcamt-parser/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/psynetic-software%2Fcamt-parser/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/psynetic-software%2Fcamt-parser/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/psynetic-software","download_url":"https://codeload.github.com/psynetic-software/camt-parser/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/psynetic-software%2Fcamt-parser/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33169242,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-18T05:43:36.989Z","status":"ssl_error","status_checked_at":"2026-05-18T05:43:19.133Z","response_time":71,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["banking","camt","camt052","camt053","camt054","cpp","csv","finance","mit","parser","qif","sepa","swift","xml"],"created_at":"2025-11-09T07:00:50.131Z","updated_at":"2026-05-18T07:32:54.354Z","avatar_url":"https://github.com/psynetic-software.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# camt-parser\n\nA high-performance C++ library for parsing SEPA CAMT XML banking formats.\n\nSupports:\n- **camt.052** Bank-to-Customer Account Report\n- **camt.053** Bank-to-Customer Statement\n- **camt.054** Bank-to-Customer Debit/Credit Notification\n\nThe library provides a structured, domain-friendly data model and an optional\nCSV export layer optimized for accounting, reconciliation, and audit workloads.\n\n## Features\n\n- Fully supports **camt.052 / .053 / .054**\n- Extracts complete transaction details (counterparty, remittance, references)\n- Unicode-aware free-text normalization (optional `USE_UTF8PROC`)\n- Bank transaction code → **GVC** mapping included\n- Optional **canonical transaction hash** for duplicate detection\n- CSV export designed for **accounting systems**\n- Zero locale-dependencies (monetary values kept as text until formatted)\n- **MIT License** (commercial-friendly)\n\n## Installation / Build\n\n```bash\ncmake -S . -B build -DCMAKE_BUILD_TYPE=Release\ncmake --build build\n```\n\nOptional dependencies:\n- **pugixml** (MIT) for XML parsing\n- **utf8proc** (MIT) for Unicode normalization (if `USE_UTF8PROC` is defined)\n\n## High-Level Data Model\n\n```\nDocument\n └─ Statement(s)\n     └─ Entry(s)\n         └─ EntryTransaction(s)\n```\n\n### `Document`\nRepresents a full CAMT file (052 / 053 / 054).\n\n### `Statement`\nContains metadata (account, creation time, balances) and `Entry` records.\n\n### `Entry`\nRepresents a booked transaction line (booking date, value date, amount).\n\nMay contain **multiple** `EntryTransaction` elements.\n\n### `EntryTransaction`\nContains full payment details:\n- Counterparty (IBAN/BIC/Name)\n- Remittance text (structured + unstructured)\n- ISO 20022 BankTransactionCode (Domain / Family / SubFamily)\n- Proprietary bank code\n- Charges, fees, reversal indicator, etc.\n\n## Parsing API\n\n```cpp\n#include \u003ccamt_parser_pugi.hpp\u003e\n\ncamt::Parser p;\ncamt::Document doc;\nstd::string err;\n\nif (!p.parse_file(\"statement.xml\", doc, \u0026err)) {\n    std::cerr \u003c\u003c \"Parse error: \" \u003c\u003c err \u003c\u003c \"\\n\";\n}\n```\n\n## CSV Export\n\n```cpp\n#include \u003ccamt_csv.hpp\u003e\n\nstd::ofstream out(\"export.csv\");\n\ncamt::ExportOptions opt;\nopt.write_utf8_bom = true;          // Excel compatible\nopt.remittance_separator = \" | \";   // readable multi-part purpose text\nopt.signed_amount = true;\nopt.credit_as_bool = true;\n\ncamt::export_entries_csv(doc, \u0026out, nullptr, opt);\n```\n## Quick Start Example\n\nThis example demonstrates parsing a CAMT file and exporting transactions to CSV:\n\n~~~cpp\n#include \u003ccamt_parser_pugi.hpp\u003e\n#include \u003ccamt_csv.hpp\u003e\n#include \u003cfstream\u003e\n#include \u003ciostream\u003e\n\nint main() {\n    camt::Parser parser;\n    camt::Document doc;\n    std::string err;\n\n    // Parse CAMT XML from file\n    if (!parser.parse_file(\"statement.camt053.xml\", doc, \u0026err)) {\n        std::cerr \u003c\u003c \"Parse error: \" \u003c\u003c err \u003c\u003c \"\\n\";\n        return 1;\n    }\n\n    // Export to CSV\n    camt::ExportData data;\n    camt::ExportOptions opt;\n    opt.include_header = true;\n\n    std::ofstream out(\"export.csv\", std::ios::binary);\n    camt::export_entries_csv(doc, \u0026out, \u0026data, opt);\n\n    std::cout \u003c\u003c \"Export completed: export.csv\\n\";\n    return 0;\n}\n~~~\n\n### Field Semantics: `first` vs `second`\n\nEach exported field consists of a pair:\n\n- **first** → Human-readable formatted value  \n- **second** → Canonical normalized value used for sorting, hashing, and deduplication\n\n`second` is **never empty**: if not present, it is generated via normalization rules.\n\n### Supported Input Methods\n\n| Input type | Function |\n|-----------|----------|\n| File path | `parse_file(const std::string\u0026 path, ...)` |\n| Input stream | `parse_file(std::istream\u0026, ...)` |\n| Memory buffer | `parse_string(const char* buffer, ...)` |\n\n### Complete Demonstration\n\nA fully working test and demonstration is available here: examples/main.cpp\n\n\n\n## ExportOptions\n\n| Option | Default | Description |\n|--------|---------|-------------|\n| `delimiter` | `';'` | CSV separator (`;`, `,`, or `\\t`) |\n| `include_header` | `true` | Adds header row |\n| `write_utf8_bom` | `false` | Necessary for Excel UTF-8 import |\n| `signed_amount` | `true` | Credit positive / Debit negative |\n| `credit_as_bool` | `true` | `IsCredit = 1/0` instead of `CRDT/DBIT` |\n| `remittance_separator` | `\"\"` | Join multiple `Ustrd[]` lines |\n| `use_effective_credit` | `false` | Apply reversal indicator |\n| `prefer_ultimate_counterparty` | `true` | Prefer `UltmtDbtr` / `UltmtCdtr` |\n\n## Exported Row Format: Display Value (`first`) vs Normalized Value (`second`)\n\nEach exported field consists of a pair:\n- **first**: Human-readable display value (formatted, signed, date-formatted)\n- **second**: Canonical normalized value used for sorting, comparison, and deterministic hashing.\n\n`second` is **never empty** — if not assigned directly, it is generated via normalization rules.\n\n### Field overview (C1 display naming)\n\n| Field | `first` (display) | `second` (normalized raw) | Influenced by options |\n|---|---|---|---|\n| Value Date | `YYYY-MM-DD` | `YYYYMMDD` digits | Sorting (`useBookingDate=false`) |\n| Booking Date | `YYYY-MM-DD` | `YYYYMMDD` digits | Sorting (`useBookingDate=true`) |\n| Amount | Formatted signed or unsigned | Absolute numeric text | `signed_amount`, `use_effective_credit` |\n| Is Credit | `1`/`0` or `CRDT`/`DBIT` | `1`/`0` original direction | `credit_as_bool`, `use_effective_credit` |\n| Reversal | `1` or `0` | `1` or `0` | Affects sign if `use_effective_credit=true` |\n| Currency | `EUR` etc. | Uppercased, trimmed | Normalization only |\n| Counterparty Name | Human-friendly chosen party | NFC/casefold/trim normalized | `prefer_ultimate_counterparty`, normalization |\n| Counterparty IBAN | Formatted IBAN | Uppercase, no spaces | Normalization |\n| Counterparty BIC | Formatted BIC | Uppercase, no spaces | Normalization |\n| Remittance Line | Joined text lines | GS-joined normalized tokens | `remittance_separator`, `USE_UTF8PROC` |\n| Remittance Structured | Display text | Normalized base | Normalization |\n| End-to-End ID | Shown as provided | Uppercase, no spaces | Normalization |\n| Mandate ID | Shown as provided | Uppercase, no spaces | Normalization |\n| Transaction ID | Shown as provided | Uppercase, no spaces | Normalization |\n| Bank Reference | Display reference | Normalized | Normalization |\n| Account IBAN | Statement IBAN | Uppercase, no spaces | Normalization |\n| Account BIC | Statement BIC | Uppercase, no spaces | Normalization |\n| Booking Code | Code as text | Uppercase trimmed | Normalization |\n| Status | Display text | Trimmed | Normalization |\n| Running Balance | Formatted running total | Same as display | Always signed logically (`CRDT = +`, `DBIT = −`) |\n| Charges Amount | Display charges | Same as display | Independent of `signed_amount` |\n| Charges Currency | Display currency | Normalized | Normalization |\n| Charges Included | `1`/`0` | Same | None |\n| Entry Ordinal | Display index | Same | Used as stable tiebreaker |\n| Transaction Ordinal | Display index | Same | Used as stable tiebreaker |\n\nThis section ensures consistent interpretation when converting to CSV, databases, or accounting systems.\n\n (`first`) vs Normalized Value (`second`)\n\nEach exported field consists of a pair:\n- **first**: Human-readable display value (formatted, signed, date-formatted)\n- **second**: Canonical normalized value used for sorting, comparison, and deterministic hashing.\n\n`second` is **never empty** — if not assigned directly, it is generated via normalization.\n\n| Display Name | `first` (human output) | `second` (normalized / for sorting) | Relevant Options |\n|---|---|---|---|\n| **Value Date** | `YYYY-MM-DD` | `YYYYMMDD` | Affects sorting order |\n| **Booking Date** | `YYYY-MM-DD` | `YYYYMMDD` | Sorting if selected |\n| **Amount** | Signed or unsigned amount text | Absolute numeric amount | `signed_amount`, `use_effective_credit` |\n| **Is Credit** | `1` (credit) / `0` (debit) or `CRDT/DBIT` | Always `1/0` for original direction | `credit_as_bool`, `use_effective_credit` |\n| **Reversal** | `1` or `0` | Same | May flip meaning under `use_effective_credit` |\n| **Counterparty Name** | Best resolved party name | Case-normalized canonical text | `prefer_ultimate_counterparty` |\n| **Counterparty IBAN** | Standard IBAN text | Uppercased, spaces removed | Normalization |\n| **Counterparty BIC** | Standard BIC text | Uppercased, spaces removed | Normalization |\n| **Remittance** | Joined free text lines | Canonical token-joined, normalized lines | `remittance_separator`, `USE_UTF8PROC` |\n| **Structured Reference** | Display reference text | Normalized canonical text | `USE_UTF8PROC` |\n| **End-to-End ID** | Displayed as present | Uppercased, spaces removed | Normalization |\n| **Mandate ID / Transaction ID / Bank Reference** | Display text | Normalized ID | Normalization |\n| **Running Balance** | Accumulated signed balance | Same as display | Determined by sorting order |\n| **Opening / Closing Balance** | Displayed balance | Same | Placement depends on statement order |\n\nNormalization rules:\n- Text fields are trimmed and unified\n- Codes \u0026 currency uppercased\n- IBAN/BIC spaces removed\n- Date `.second` always `YYYYMMDD`\n- `Amount.second` is always absolute value\n- Advanced Unicode normalization if compiled with `USE_UTF8PROC`\n\n| Option | Default | Description |\n|--------|---------|-------------|\n| `delimiter` | `';'` | CSV separator (`;`, `,`, or `\\t`) |\n| `include_header` | `true` | Adds header row |\n| `write_utf8_bom` | `false` | Necessary for Excel UTF-8 import |\n| `signed_amount` | `true` | Credit positive / Debit negative |\n| `credit_as_bool` | `true` | `IsCredit = 1/0` instead of `CRDT/DBIT` |\n| `remittance_separator` | `\"\"` | Join multiple `Ustrd[]` lines |\n| `use_effective_credit` | `false` | Apply reversal indicator |\n| `prefer_ultimate_counterparty` | `true` | Prefer `UltmtDbtr` / `UltmtCdtr` |\n\n## Exported Row Format: first vs second\n\nEvery column in `ExportData` is stored as a pair:\n\n- `first` → human-readable, formatted display value\n- `second` → normalized, canonical value used for sorting, hashing, and stable processing\n\nIf a field does not explicitly assign `second`, it is filled from `first` via normalization.\n\nNormalization rules include:\n- Date fields → `YYYYMMDD`\n- IBAN/BIC → uppercase, no spaces\n- Free-text fields → trimmed, casefolded (with utf8proc if enabled)\n- Amounts → `second` stores absolute value\n\nSorting uses `.second` for date ordering.\nRunning balance uses signed logic independent of display formatting.\n\n## Optional Unicode Normalization (`USE_UTF8PROC`)\n\nThis library supports optional full Unicode normalization of free-text fields\n(e.g., remittance lines, counterparty names, references).\n\nIf compiled with `-DUSE_UTF8PROC`, the following normalization is applied using\nthe MIT-licensed `utf8proc` library:\n\n- Normalize text to **NFC**\n- Unicode-aware case folding\n- Removal of zero-width characters\n- Stable whitespace normalization\n\nIf `USE_UTF8PROC` is **not** defined:\n\n- A lightweight ASCII-only fallback is used\n- No external dependencies are required\n- No utf8proc code is linked or distributed\n\n\n## Canonical Transaction Hashing\n\n```cpp\nstd::string hash = camt::accumulate_hash_row(row);\n```\n\nStable fingerprint for:\n- Duplicate detection\n- Ledger synchronization\n- Audit trails\n\n## License\n\nReleased under the **MIT License**.\n\n```\nSPDX-License-Identifier: MIT\nSPDX-FileCopyrightText: 2025 Psynetic\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpsynetic-software%2Fcamt-parser","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpsynetic-software%2Fcamt-parser","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpsynetic-software%2Fcamt-parser/lists"}