Tools

Reference parsers in four languages, and converters from formats you already have.

A specification nobody can read is just a document. These are the reference implementations: they turn AODM into data your program already knows how to handle, and they check every rule in the specification while doing it.

All of it is Apache 2.0 licensed and ships in the download package. No dependencies in any language — each implementation uses only its standard library.

Reference parsers

A parser reads AODM’s XML form and hands back the JSON model defined by aodm-core-1.2.schema.json. Both are AODM: the specification defines two serialisations of one model, and the parsers convert between them in either direction.

LanguageFileRequires
Pythonparsers/python/aodm.pyPython 3.8+, standard library
JavaScriptparsers/javascript/aodm.jsNode 18+ or any browser
Javaparsers/java/Aodm.javaJDK 11+, standard library
C#parsers/csharp/Aodm.cs.NET 6+, base class library

Python

from aodm import parse_file

doc = parse_file("knowledge.xml")
doc.facts                 # list of facts
doc.by_id("engine")       # look up any element
doc.to_json()             # JSON matching the published schema
doc.to_xml()              # back to AODM XML
doc.is_valid()            # False if any MUST-level rule is broken

for issue in doc.validate():
    print(issue)          # ERROR R1: The object "ghost" does not match…

JavaScript

const { parse } = require('./aodm');

const doc = parse(xmlString);
doc.facts;        doc.byId('engine');
doc.toJSON();     doc.toXml();
doc.isValid();    doc.validate();

In a browser, load it with a <script> tag and use AODMParser.parse(…). It uses the browser’s own XML parser where available and falls back to a built-in reader under Node, so there is no dependency either way.

Java

Aodm.Document doc = Aodm.parseFile("knowledge.xml");
doc.facts();      doc.byId("engine");
doc.toJson();     doc.toXml();
doc.isValid();    doc.validate();

C#

var doc = Aodm.ParseFile("knowledge.xml");
doc.Facts;        doc.ById("engine");
doc.ToJson();     doc.ToXml();
doc.IsValid();    doc.Validate();

Each also runs from the command line:

python3 aodm.py knowledge.xml              # print the JSON model
python3 aodm.py --validate knowledge.xml   # report rule violations

What the parsers check

Validation is not an optional extra bolted on afterwards — every parser enforces the full rule set from VALIDATION-RULES.md, including the constraints that no schema language can express: referential integrity, derivation cycles, duplicate ids, cardinality, measurement coherence, temporal ordering, polarity handling and digest format. Errors are MUST-level violations; warnings are SHOULD-level.

Why four implementations rather than one. Beyond covering more stacks, independent implementations are how a specification gets tested. If two of them disagreed about the same document, the fault would be in the specification, not the code. A conformance suite runs all four over the same inputs and requires identical output — currently 18 rule cases across four languages, alongside 21 schema checks, 24 XBRL constructs and 33 graph and reasoning checks.

Converters

Most organisations already hold structured data in a standard format. A converter turns that into AODM without re-authoring anything, which is usually the difference between adopting a format and reading about it.

XBRL

XBRL is mandatory for financial reporting to the SEC, ESMA, HMRC and most other regulators, so essentially every listed company already produces it. The converter implements the whole of the XBRL 2.1 instance document syntax.

python3 xbrl_to_aodm.py instance.xml             # AODM JSON
python3 xbrl_to_aodm.py instance.xml --xml      # AODM XML
python3 xbrl_to_aodm.py instance.xml --validate
XBRLBecomes
Reporting entity identifierentity type="reporting-entity"
Reported factfact, statement = element name
Numeric content + unitvalue/@number + @unit
Divided unit (USD/share)@unit="USD/shares"
Fraction@number, numerator ÷ denominator
Duration periodvalid-from / valid-to
Instant periodvalid-from = valid-to
Forever periodno temporal bounds
@decimals / @precisionvalue/@tolerance
Explicit & typed dimensionsrelationship to a member entity
Tuples, nestedentity type="fact-group" + composition
Footnotesappended to the fact statement

A stated accuracy of decimals="-6" means the figure is rounded to millions, so the real value sits within half a million either way. That becomes an AODM tolerance rather than being discarded — which is the whole point: the precision of a reported number is information, and most pipelines throw it away.

Scope, stated precisely. This covers the XBRL 2.1 instance document syntax completely. It does not interpret the taxonomy — linkbases, label resolution and calculation trees live in separate files an instance only references, and resolving them is a different problem. Element names therefore appear verbatim rather than as human-readable labels. Inline XBRL (iXBRL embedded in HTML) is a different serialisation and is not read.

Graph compiler

Compiles AODM into graph structures for reasoning engines and graph databases. Engine ──requires──▶ Spark becomes node, edge, node.

python3 aodm_graph.py doc.xml --format cypher    # Neo4j
python3 aodm_graph.py doc.xml --format turtle    # RDF, for SPARQL/OWL
python3 aodm_graph.py doc.xml --format graphml   # Gephi, yEd
python3 aodm_graph.py doc.xml --format dot       # Graphviz

Facts, rules and sources become nodes rather than properties. That is not a stylistic choice: with sources as nodes, “what rests on this source?” is one traversal, and retraction becomes possible. Flattened into text properties it is a full scan with string matching.

Inference engine

Forward chaining over the compiled graph, implementing the inference section of the specification (section 10), so its conclusions are reproducible by any other conformant engine.

$ python3 reasoner.py doc.xml
Derived 2 conclusion(s):
  step 1: failure-risk     confidence 0.5985
           by risk-rule from temp-rise, pressure-nominal
  step 1: shorten-service  confidence 0.53865
           by service-rule from failure-risk

Confidence multiplies along the chain, so a conclusion is never more certain than the weakest premise supporting it. It also answers two questions a reasoner usually cannot:

  • Why is this believed? --explain walks the chain back to the observed facts and their sources.
  • What falls if this source is wrong? --retract follows the derivations forward and lists every conclusion that depended on it.
  • What was true then? --at 2025-06-01 reasons as at a date; a rule outside its validity window does not fire.

LLM context

Renders a document into prompt-ready context for any model. Dropping raw facts into a prompt is easy and mostly useless: the model gets a pile of assertions with no way to tell a measurement from a guess, and states them all with equal confidence.

python3 context.py doc.xml                   # markdown
python3 context.py doc.xml --format text     # compact, for tight budgets
python3 context.py doc.xml --format json     # structured, for tool use
python3 context.py doc.xml --max-chars 4000  # budget-aware

The renderer states confidence in words as well as numbers, marks known-false facts explicitly rather than omitting them, excludes superseded knowledge while saying that it did, and labels inferred facts as inferred. Those are the signals that let a model hedge accurately instead of asserting everything flatly.