Parse and serialize HomeBank XHB files.
XHB is the XML-based file format used by HomeBank, an open-source personal finance application. This module provides bidirectional conversion between XHB XML and typed JavaScript objects, preserving byte-for-byte fidelity on round-trip.
Features
- Parse XHB XML into a typed
XHBobject - Serialize an
XHBobject back to XML - All HomeBank entity types: accounts, archives, assigns, categories, currencies, operations, payees, properties, tags
- A hook for post-processing serialized entities via
SerializeOptions.onEntity
Parse an XHB string and inspect its contents
Parse an XHB string and inspect its contents
import { assertEquals } from "@std/assert"; import { parse } from "@hertzg/xhb"; // deno-fmt-ignore const xml = [ '<?xml version="1.0"?>', '<homebank v="1.3" d="050204">', '<cur key="1" flags="0" iso="GBP" name="Pound Sterling" symb="£" syprf="1" dchar="." gchar="," frac="2" rate="0" mdate="0"/>', '<account key="1" pos="1" type="1" curr="1" name="Cheque Account" number="01548726554" bankname="Amiga Universal Bank" initial="76.219999999999999" minimum="-30.489999999999998" cheque1="8760951"/>', '<pay key="1" name="Amazon"/>', '<cat key="1" flags="1" name="Food"/>', '<tag key="1" name="groceries"/>', '<ope date="736968" amount="-42.5" account="1" paymode="1" payee="1" category="1" wording="Weekly shop" tags="groceries"/>', '</homebank>', '', ].join("\n"); const xhb = parse(xml); assertEquals(xhb.versions.file, "1.3"); assertEquals(xhb.currencies.length, 1); assertEquals(xhb.currencies[0].isoCode, "GBP"); assertEquals(xhb.accounts.length, 1); assertEquals(xhb.accounts[0].name, "Cheque Account"); assertEquals(xhb.payees.length, 1); assertEquals(xhb.payees[0].name, "Amazon"); assertEquals(xhb.operations.length, 1); assertEquals(xhb.operations[0].amount, "-42.5"); assertEquals(xhb.operations[0].memo, "Weekly shop"); assertEquals(xhb.operations[0].tags, ["groceries"]);
Round-trip: parse then serialize produces identical output
Round-trip: parse then serialize produces identical output
import { assertEquals } from "@std/assert"; import { parse, serialize } from "@hertzg/xhb"; // deno-fmt-ignore const xml = [ '<?xml version="1.0"?>', '<homebank v="1.3" d="050204">', '<cur key="1" flags="0" iso="GBP" name="Pound Sterling" symb="£" syprf="1" dchar="." gchar="," frac="2" rate="0" mdate="0"/>', '<account key="1" pos="1" type="1" curr="1" name="Cheque Account" number="01548726554" bankname="Amiga Universal Bank" initial="76.219999999999999" minimum="-30.489999999999998" cheque1="8760951"/>', '</homebank>', '', ].join("\n"); const xhb = parse(xml); const output = serialize(xhb); assertEquals(output, xml);
Modify a parsed XHB and serialize it back
Modify a parsed XHB and serialize it back
import { assertEquals } from "@std/assert"; import { parse, serialize } from "@hertzg/xhb"; // deno-fmt-ignore const xml = [ '<?xml version="1.0"?>', '<homebank v="1.3" d="050204">', '<pay key="1" name="Amazon"/>', '</homebank>', '', ].join("\n"); const xhb = parse(xml); xhb.payees.push({ key: 2, name: "Grocery Store", payMode: 0, category: 0 }); const output = serialize(xhb); assertEquals(output.includes('name="Grocery Store"'), true); assertEquals(xhb.payees.length, 2);