Document Purpose: Explain why country-specific solutions fail, why generic XBRL processors are essential, and why building one takes 10-50 person-years
Last Updated: January 2026
Target Audience: Software architects, procurement teams, XBRL implementers, management
The Problem:
Most "XBRL solutions" are just spreadsheets or form-based tools that generate ONE specific instance document for ONE jurisdiction. They're point solutions, not real processors.
Why It Matters:
Why Generic Processors Are Hard:
Building a generic XBRL processor takes 10-50 person-years because:
Existing Processors:
The Bottom Line:
If you need XBRL for more than one use case, invest in a generic processor. Point solutions are technical debt disguised as quick wins.
Typical "XBRL Solution":
Product: "VAT Filing Tool for Netherlands"
Features:
├─ Excel spreadsheet with formulas
├─ Macros to validate inputs
├─ Script generates XBRL-XML for NT 2024
├─ Hardcoded for VAT entry point
└─ €5,000 one-time purchase
Limitations:
├─ Only works for Netherlands VAT
├─ Only works with NT 2024 taxonomy
├─ Cannot validate incoming XBRL
├─ Cannot handle other entry points
├─ Cannot process dimensional data
├─ Must be rebuilt for NT 2025
└─ Total rewrite needed for new use case
Another Example:
Product: "Annual Report Generator - Belgium"
Features:
├─ Web form for financial data entry
├─ Generates Belgian GAAP XBRL instance
├─ Hardcoded for one entry point
├─ €10,000 per year subscription
Limitations:
├─ Only Belgian GAAP
├─ Cannot handle IFRS
├─ Cannot validate formulas
├─ Cannot process incoming XBRL
├─ Cannot generate viewpoints
├─ Vendor lock-in (proprietary format)
└─ Migration impossible
The Sales Pitch:
Vendor: "We have an XBRL solution for Dutch VAT!"
Company: "Great, we need that."
Vendor: "Only €5,000, ready in 2 weeks."
Company: "Sold!"
Reality (2 years later):
Company: "We need to file in Belgium too."
Vendor: "That's a different product, €8,000."
Company: "OK... and we need ESEF annual reports."
Vendor: "That's €15,000, different system."
Company: "And we need to validate incoming XBRL..."
Vendor: "We don't do that. Try another vendor."
Company: "And the Dutch taxonomy updated..."
Vendor: "That's €3,000 for the update."
Total Cost of Ownership: €31,000 and climbing
Still cannot: Validate, analyze, or integrate XBRL
Why It's Attractive (Short-Term):
Why It Fails (Long-Term):
Excel-Based "XBRL Solutions":
Sheet1: "Balance Sheet Entry"
├─ Cell A1: "Assets"
├─ Cell B1: [User enters value]
├─ Cell C1: =B1 (for validation)
├─ ...
├─ Cell A50: "Total Assets"
├─ Cell B50: =SUM(B1:B49)
└─ VBA Macro: "Generate XBRL"
Sub GenerateXBRL()
Dim xml As String
xml = "<?xml version='1.0'?>"
xml = xml & "<xbrl>"
xml = xml & "<context id='c1'>...</context>"
xml = xml & "<nl:Assets contextRef='c1'>" & Range("B1").Value & "</nl:Assets>"
' ... 500 more lines of string concatenation ...
xml = xml & "</xbrl>"
' Save to file
Open "vat-return.xbrl" For Output As #1
Print #1, xml
Close #1
End Sub
Problems:
Spreadsheet doesn't know:
├─ What concepts exist in taxonomy
├─ What relationships exist
├─ What calculations should be checked
├─ What dimensions are required
└─ What validation rules apply
It just hardcodes assumptions!
NT 2024 → NT 2025:
├─ New namespace
├─ Spreadsheet has old namespace hardcoded
├─ Generated XBRL invalid
└─ Must rewrite VBA macros
Cannot handle:
├─ Dimensional reporting (segments, scenarios)
├─ Typed dimensions
├─ Formula validation
├─ Relationship arcs
├─ Multiple entry points
└─ Anything beyond simple data entry
VBA string concatenation:
├─ XML escaping errors
├─ Missing closing tags
├─ Invalid structure
├─ Context reference errors
└─ Unit definition errors
All require manual debugging!
Web Form "XBRL Solutions":
<form action="/generate-xbrl" method="POST">
<h1>VAT Return</h1>
<label>Sales (excl. VAT)</label>
<input name="sales" type="number"/>
<label>Purchases (excl. VAT)</label>
<input name="purchases" type="number"/>
<label>VAT Rate</label>
<select name="vat_rate">
<option>21%</option>
<option>9%</option>
</select>
<button>Generate XBRL</button>
</form>
Backend (Hardcoded):
@app.route('/generate-xbrl', methods=['POST'])
def generate_xbrl():
sales = request.form['sales']
purchases = request.form['purchases']
vat_rate = request.form['vat_rate']
# Hardcoded XBRL template
xbrl = f"""<?xml version="1.0"?>
<xbrl xmlns="http://www.xbrl.org/2003/instance"
xmlns:nl="http://www.nltaxonomie.nl/nt2024/btw/...">
<context id="c1">
<entity><identifier>12345678</identifier></entity>
<period><startDate>2024-01-01</startDate><endDate>2024-03-31</endDate></period>
</context>
<unit id="EUR"><measure>iso4217:EUR</measure></unit>
<nl:Sales contextRef="c1" unitRef="EUR" decimals="0">{sales}</nl:Sales>
<nl:Purchases contextRef="c1" unitRef="EUR" decimals="0">{purchases}</nl:Purchases>
<!-- ... more hardcoded fields ... -->
</xbrl>
"""
return xbrl
Same Problems as Spreadsheet:
Definition:
A generic XBRL processor is software that can:
Not Hardcoded:
Generic Processor:
├─ Reads taxonomy to understand structure
├─ Dynamically processes any concept
├─ Validates using specification rules
├─ Works with any entry point
├─ Works with any jurisdiction
└─ Updates when specification changes
Point Solution:
├─ Hardcoded for one taxonomy
├─ Hardcoded list of concepts
├─ Hardcoded validation rules
├─ Works with one entry point only
├─ Works with one jurisdiction only
└─ Rewrite needed for any change
Use Case 1: Multi-Jurisdiction Company
Company operates in:
├─ Netherlands (VAT, annual report)
├─ Belgium (VAT, annual report)
├─ Germany (VAT, annual report)
├─ United Kingdom (Corporation tax, annual report)
└─ France (VAT, annual report)
Point Solution Approach:
├─ Netherlands VAT tool: €5,000
├─ Netherlands annual report tool: €10,000
├─ Belgium VAT tool: €5,000
├─ Belgium annual report tool: €10,000
├─ Germany VAT tool: €5,000
├─ Germany annual report tool: €10,000
├─ UK corporation tax tool: €8,000
├─ UK annual report tool: €12,000
├─ France VAT tool: €5,000
├─ France annual report tool: €10,000
└─ Total: €80,000
Plus: €20,000/year maintenance
Plus: Different interfaces for each
Plus: No integration between systems
Plus: Multiply by yearly taxonomy updates
Generic Processor Approach:
├─ Generic XBRL processor: €50,000
├─ Works with ALL taxonomies
├─ Works with ALL jurisdictions
├─ Single interface
├─ Integrated data model
└─ Total: €50,000
Plus: €5,000/year maintenance
Plus: Add new jurisdiction = load taxonomy
Use Case 2: Regulator Processing Filings
Regulator receives:
├─ 100,000 annual reports per year
├─ 500,000 VAT returns per year
├─ 50,000 corporation tax returns per year
├─ All in XBRL format
Tasks:
├─ Validate all filings
├─ Extract data for analysis
├─ Detect anomalies
├─ Generate statistics
├─ Audit selected filings
└─ Publish aggregated data
Point Solution: IMPOSSIBLE
├─ Cannot process varying company extensions
├─ Cannot validate formulas
├─ Cannot handle dimensional complexity
├─ Cannot scale to volume
└─ Would need custom code for each filing
Generic Processor: FEASIBLE
├─ Validates against taxonomy
├─ Processes any valid XBRL
├─ Handles extensions
├─ Evaluates formulas
├─ Scales to millions of facts
└─ Automated processing pipeline
Use Case 3: Software Vendor
Vendor wants to offer XBRL integration in ERP system
Point Solution Approach:
├─ Build Dutch VAT module
├─ Build Belgian VAT module
├─ Build German VAT module
├─ Build UK corporation tax module
├─ Build annual report module
└─ Each is 6 months development
Total: 2.5 years, 5 developers
Maintenance: Continuous rewrites
Generic Processor Approach:
├─ Integrate generic XBRL processor (3 months)
├─ Build taxonomy browser UI (2 months)
├─ Build mapping configuration (2 months)
├─ Build viewpoint renderer (2 months)
└─ Total: 9 months, 2 developers
New jurisdiction: Load taxonomy
Maintenance: Minimal
Flexibility:
With Generic Processor:
├─ New jurisdiction → Load taxonomy
├─ New entry point → Select in browser
├─ Taxonomy update → Load new version
├─ New use case → Configure mapping
└─ Time to production: Days/Weeks
With Point Solutions:
├─ New jurisdiction → Buy/build new tool
├─ New entry point → Custom development
├─ Taxonomy update → Wait for vendor
├─ New use case → Evaluate new tool
└─ Time to production: Months/Years
Total Cost of Ownership:
5-Year Cost Comparison:
Point Solutions (5 jurisdictions, 2 reports each):
├─ Year 1: 10 × €8,000 = €80,000 (initial)
├─ Year 2-5: 10 × €3,000 = €30,000/year (updates)
├─ Training: €10,000/year (10 different systems)
├─ Integration: €20,000/year (connect systems)
└─ Total 5 years: €320,000
Generic Processor:
├─ Year 1: €50,000 (processor) + €30,000 (integration)
├─ Year 2-5: €5,000/year (maintenance)
├─ Training: €5,000 one-time (one system)
├─ Integration: €0 (built-in)
└─ Total 5 years: €105,000
Savings: €215,000 over 5 years
Future-Proofing:
Scenario: New reporting requirement
Point Solution:
├─ Wait for vendor to build it
├─ Or buy from different vendor
├─ Or build custom tool
├─ 6-12 months timeline
└─ €10,000-50,000 cost
Generic Processor:
├─ Load new taxonomy
├─ Configure mapping
├─ 1-2 weeks timeline
└─ €0-5,000 cost
Overview:
Specifications Supported:
✅ XBRL 2.1
✅ Dimensions 1.0
✅ Formula 1.0 (full suite)
✅ Inline XBRL 1.1
✅ Table Linkbase 1.0
✅ Versioning 1.0
✅ Taxonomy Packages 1.0
✅ OIM (xBRL-JSON, xBRL-CSV)
✅ Extensible Enumerations 2.0
Strengths:
Weaknesses:
Use Cases:
Example Usage:
from arelle import Cntlr, ModelXbrl
# Create controller
cntlr = Cntlr.Cntlr()
# Load instance
modelXbrl = cntlr.modelManager.load("instance.xbrl")
# Validate
modelXbrl.validate()
# Get validation results
errors = modelXbrl.errors
warnings = modelXbrl.warnings
# Access facts
for fact in modelXbrl.facts:
print(f"{fact.concept.qname}: {fact.value}")
Overview:
Specifications Supported:
✅ XBRL 2.1
✅ Dimensions 1.0
✅ Formula 1.0 (partial)
✅ Inline XBRL 1.1
✅ Table Linkbase 1.0
✅ Taxonomy Packages 1.0
✅ Custom extensions (viewpoints, mapping)
Architecture:
Three-Phase Architecture:
├─ Phase 1: Design Time (taxonomy preprocessing)
├─ Phase 2: Initialization (caching, indexing)
└─ Phase 3: Runtime (instance processing)
Benefits:
├─ Fast runtime performance
├─ Low memory footprint
├─ Scalable to millions of facts
└─ Production-grade reliability
Strengths:
Weaknesses:
Use Cases:
Overview:
Romanian Mathematics Team:
Specifications Supported:
✅ XBRL 2.1
✅ Dimensions 1.0
✅ Formula 1.0 (full)
✅ Inline XBRL 1.1
✅ Table Linkbase 1.0
✅ Versioning 1.0
Strengths:
Weaknesses:
Use Cases:
Overview:
Specifications Supported:
✅ XBRL 2.1
✅ Dimensions 1.0
✅ Inline XBRL 1.1
✅ Japanese taxonomy specifics
Strengths:
Weaknesses:
Use Cases:
Overview:
Products:
Specifications Supported:
✅ XBRL 2.1
✅ Dimensions 1.0
✅ Formula 1.0
✅ Inline XBRL 1.1
✅ Table Linkbase 1.0
✅ ESEF validation
Strengths:
Weaknesses:
Use Cases:
Workiva (Commercial SaaS):
Certent (Commercial SaaS):
UBmatrix (Commercial):
RDG Filings (Commercial):
Processor | Language | License | Formula | Table | Inline | Performance | Cost |
────────────────────────────────────────────────────────────────────────────────────────────
Arelle | Python | Open Source | Full | Full | Full | Medium | Free |
GLOMIDCO | Java | Commercial | Partial | Full | Full | High | Medium |
Semansys | C#/.NET | Commercial | Full | Full | Full | High | Medium |
Fujitsu | Java | Commercial | Partial | Yes | Yes | High | High |
CoreFiling | Java | SaaS | Full | Full | Full | High | High |
Workiva | Various | SaaS | Full | Yes | Full | High | Very High |
────────────────────────────────────────────────────────────────────────────────────────────
Recommendation:
├─ Budget-conscious / Open source needed: Arelle
├─ Enterprise Java integration: GLOMIDCO or CoreFiling
├─ .NET ecosystem: Semansys (Visma)
├─ Japanese market: Fujitsu
├─ Full-service SaaS: CoreFiling or Workiva
XML Processing:
<book>
<title>The Great Gatsby</title>
<author>F. Scott Fitzgerald</author>
<year>1925</year>
<price>15.99</price>
</book>
XML Complexity:
1. Parse XML structure (SAX/DOM)
2. Validate against XSD schema
3. Extract data
4. Done!
Complexity: Low
Effort: 1-2 person-months for basic parser
Libraries: Abundant (every language has mature XML libraries)
XBRL Processing:
<xbrli:xbrl>
<context id="c1">
<entity>
<identifier>0001234567</identifier>
<segment>
<xbrldi:explicitMember dimension="us-gaap:StatementBusinessSegmentsAxis">
company:RetailSegmentMember
</xbrldi:explicitMember>
</segment>
</entity>
<period><instant>2024-12-31</instant></period>
</context>
<unit id="USD"><measure>iso4217:USD</measure></unit>
<us-gaap:Assets contextRef="c1" unitRef="USD" decimals="-3">250000000</us-gaap:Assets>
</xbrli:xbrl>
XBRL Complexity:
1. Parse XML structure (SAX/DOM)
2. Load taxonomy (multiple files)
3. Parse 5 linkbases (label, reference, calculation, presentation, definition)
4. Build concept dictionary
5. Build relationship networks
6. Resolve dimensional structures
7. Parse contexts and units
8. Match facts to contexts
9. Validate context references
10. Validate unit references
11. Validate calculations
12. Validate dimensional constraints
13. Validate formulas (if applicable)
14. Validate table linkbase structures (if applicable)
15. Handle tuples
16. Handle footnotes
17. Handle typed dimensions
18. Done! (Maybe...)
Complexity: VERY High
Effort: 10-50 person-years for full processor
Libraries: Minimal (few mature XBRL libraries)
Complexity Multiplier: 10-100x
XML Parser: 1 person-month
XBRL Processor: 10-50 person-years
Why?
├─ Must understand complex taxonomy structures
├─ Must process 5 types of linkbases
├─ Must evaluate relationships
├─ Must validate calculations
├─ Must handle dimensions
├─ Must evaluate formulas
├─ Must handle edge cases
└─ Must pass 20+ conformance suites
It's Not Just a Calculator!
Problem 1: Summation-Item vs. Parent-Child
<!-- Calculation linkbase defines BOTH relationships -->
<!-- Summation relationship -->
<calculationArc from="Assets" to="CurrentAssets" weight="1.0"/>
<calculationArc from="Assets" to="NonCurrentAssets" weight="1.0"/>
Meaning: Assets = CurrentAssets + NonCurrentAssets
<!-- But ALSO parent-child in presentation linkbase -->
<presentationArc from="Assets" to="CurrentAssets"/>
<presentationArc from="Assets" to="NonCurrentAssets"/>
Meaning: Assets has children CurrentAssets, NonCurrentAssets
Question: Are these always the same?
Answer: NO! They can differ!
Example Where They Differ:
Presentation Structure:
Assets
├─ CurrentAssets
│ ├─ Cash
│ └─ Receivables
└─ NonCurrentAssets
├─ Property
└─ Equipment
Calculation Structure:
Assets = CurrentAssets + NonCurrentAssets + GoodwillAdjustment
GoodwillAdjustment is NOT in presentation!
But IS in calculation!
Processor must handle this!
Problem 2: Negative Weights
<!-- Not all relationships are additions! -->
<calculationArc from="NetIncome" to="Revenue" weight="1.0"/>
<calculationArc from="NetIncome" to="Expenses" weight="-1.0"/>
Meaning: NetIncome = Revenue - Expenses
<!-- This is subtraction, not addition! -->
<!-- Weight of -1.0 means SUBTRACT -->
Problem 3: Precision and Rounding
<!-- Facts have decimals attribute -->
<us-gaap:Assets contextRef="c1" unitRef="USD" decimals="-3">250000000</us-gaap:Assets>
<us-gaap:CurrentAssets contextRef="c1" unitRef="USD" decimals="-3">150000000</us-gaap:CurrentAssets>
<us-gaap:NonCurrentAssets contextRef="c1" unitRef="USD" decimals="-3">100000000</us-gaap:CurrentAssets>
Calculation: Assets = CurrentAssets + NonCurrentAssets
250,000,000 = 150,000,000 + 100,000,000
Perfect!
But what if:
<us-gaap:Assets contextRef="c1" unitRef="USD" decimals="-3">250000000</us-gaap:Assets>
<us-gaap:CurrentAssets contextRef="c1" unitRef="USD" decimals="-3">149500000</us-gaap:CurrentAssets>
<us-gaap:NonCurrentAssets contextRef="c1" unitRef="USD" decimals="-3">100500000</us-gaap:NonCurrentAssets>
Calculation: 250,000,000 = 149,500,000 + 100,500,000
250,000,000 = 250,000,000
Perfect? NO!
Because decimals="-3" means "rounded to nearest thousand"
149,500,000 rounded to -3 = 150,000,000
100,500,000 rounded to -3 = 101,000,000
Total = 251,000,000
Does not match 250,000,000!
Processor must account for rounding tolerance!
Problem 4: Multiple Calculation Networks
<!-- US GAAP has MULTIPLE calculation networks -->
<calculationLink role="http://www.xbrl.org/2003/role/calculationLink">
<!-- Standard calculations -->
</calculationLink>
<calculationLink role="http://fasb.org/us-gaap/role/statement/StatementOfFinancialPositionClassified">
<!-- Balance sheet specific -->
</calculationLink>
<calculationLink role="http://fasb.org/us-gaap/role/statement/StatementOfIncome">
<!-- Income statement specific -->
</calculationLink>
Question: Which one applies?
Answer: ALL of them! But in different contexts!
Processor must know WHEN to apply which network!
Problem 5: Circular Relationships (Prohibited but Exist)
<!-- This should not exist but sometimes does -->
<calculationArc from="A" to="B" weight="1.0"/>
<calculationArc from="B" to="C" weight="1.0"/>
<calculationArc from="C" to="A" weight="1.0"/>
Result: A = B, B = C, C = A (circular!)
Processor must detect and reject!
Real-World Horror Example:
SEC Filing (Real Example, anonymized):
Balance Sheet:
Assets = $1,000,000 (reported)
CurrentAssets = $400,000
NonCurrentAssets = $600,000
Calculation: $1,000,000 = $400,000 + $600,000 ✓
BUT:
CurrentAssets breakdown:
Cash = $100,000
Receivables = $200,000
Inventory = $150,000
Total = $450,000
Wait... CurrentAssets was reported as $400,000!
But breakdown sums to $450,000!
Why?
Company made manual adjustment to CurrentAssets total
But didn't adjust breakdown!
Processor must:
1. Detect this inconsistency
2. Report error with details
3. Identify which calculation failed
4. Provide enough context for filer to fix
Problem: Dimensions Create Combinatorial Explosions
Example:
Base concept: Revenue
Dimensions:
├─ BusinessSegmentAxis (3 members: Retail, Wholesale, Online)
├─ GeographicAxis (4 members: US, EU, Asia, Other)
└─ ProductLineAxis (5 members: Electronics, Clothing, Food, Furniture, Other)
Total possible combinations: 3 × 4 × 5 = 60
Each combination needs separate context!
Each context needs separate fact!
Instance document can have:
├─ 60 Revenue facts
├─ 60 Expense facts
├─ 60 NetIncome facts
└─ × 100 concepts = 6,000 facts
Just for one company!
Validation Complexity:
For each fact, processor must:
1. Extract dimensional members from context
2. Check if combination is valid according to hypercube
3. Check if dimension is typed or explicit
4. Validate typed dimension values
5. Check for dimension defaults
6. Validate against dimensional constraints
7. Check formula applicability
For 6,000 facts: Significant computation!
Hypercube Filtering:
<!-- Hypercube defines which combinations are valid -->
<definitionLink>
<hypercube id="RevenueTable">
<dimension name="BusinessSegmentAxis"/>
<dimension name="GeographicAxis"/>
<dimension name="ProductLineAxis"/>
</hypercube>
<!-- But some combinations are excluded! -->
<dimensionFilter>
<exclude>
<dimension name="BusinessSegmentAxis" value="Online"/>
<dimension name="ProductLineAxis" value="Furniture"/>
</exclude>
</dimensionFilter>
</definitionLink>
Meaning: Online + Furniture = INVALID combination
Company doesn't sell furniture online!
Processor must enforce this constraint!
Problem: Formulas Are Computationally Expensive
Example Formula:
<formula:formula id="calc_ROE">
<formula:aspects>
<formula:concept>
<formula:qname>us-gaap:ReturnOnEquity</formula:qname>
</formula:concept>
</formula:aspects>
<formula:source>
<formula:variable ref="NetIncome"/>
<formula:variable ref="Equity"/>
</formula:source>
<formula:value>
if ($Equity = 0) then
()
else
$NetIncome div $Equity
</formula:value>
</formula:formula>
<variable:variable id="NetIncome">
<variable:filter>
<conceptFilter>
<concept>
<qname>us-gaap:NetIncomeLoss</qname>
</concept>
</conceptFilter>
</variable:filter>
</variable:variable>
<variable:variable id="Equity">
<variable:filter>
<conceptFilter>
<concept>
<qname>us-gaap:StockholdersEquity</qname>
</concept>
</conceptFilter>
</variable:filter>
</variable:variable>
Evaluation Steps:
1. Parse formula XML
2. Compile XPath expression
3. Bind variables:
├─ Find all NetIncome facts
├─ Find all Equity facts
└─ Match by context (period, entity, dimensions)
4. For each matching set:
├─ Evaluate XPath expression
├─ Check result type
├─ Generate implied fact
└─ Validate generated fact
5. Check assertions:
├─ Value assertions
├─ Existence assertions
└─ Consistency assertions
For 100 formulas × 1,000 fact combinations = 100,000 evaluations!
Computational Complexity:
Formula Evaluation:
├─ XPath compilation: O(n) per formula
├─ Variable binding: O(m) per formula (m = facts)
├─ Expression evaluation: O(k) per evaluation (k = complexity)
└─ Total: O(n × m × k)
For large instances:
├─ Formulas: 100
├─ Facts: 10,000
├─ Expressions: Complex
└─ Total evaluations: Millions
Requires optimization:
├─ Formula compilation caching
├─ Variable binding indexing
├─ Expression result caching
└─ Parallel evaluation
What Is Table Linkbase?
Table Linkbase 1.0 was introduced to define tabular layouts for XBRL data. It's used heavily in:
Why It Exists:
Problem: How do you define that data should be displayed in a table?
Before Table Linkbase:
├─ Presentation linkbase shows hierarchy
├─ But no table structure
├─ No rows/columns definition
├─ Each tool renders differently
└─ No consistency across filings
With Table Linkbase:
├─ Defines exact table structure
├─ Rows, columns, and Z-axis (filters)
├─ Breakdown rules
├─ Standardized rendering
└─ Consistent across all tools
The Complexity Explosion:
Problem 1: Three-Dimensional Tables
Table Linkbase defines tables in 3D:
X-axis (Columns):
├─ Different time periods
├─ Original vs. Restated
├─ Different scenarios
└─ Multiple sub-columns
Y-axis (Rows):
├─ Different concepts
├─ Different dimensions
├─ Hierarchical breakdowns
└─ Subtotals and totals
Z-axis (Filters):
├─ Which facts apply to this table
├─ Dimensional constraints
├─ Business rules
└─ Context filters
Processor must evaluate ALL THREE!
Example: COREP C 01.00 (Own Funds)
<table:table>
<table:breakdown>
<!-- X-axis: Columns -->
<table:breakdownTree>
<table:ruleNode>
<table:aspectNode>
<table:dimensionAspect dimension="eba:MCy"/>
<table:member>
<table:qname>eba:x91</table:qname> <!-- Column for T -->
</table:member>
</table:aspectNode>
</table:ruleNode>
<table:ruleNode>
<table:aspectNode>
<table:dimensionAspect dimension="eba:MCy"/>
<table:member>
<table:qname>eba:x92</table:qname> <!-- Column for T-1 -->
</table:member>
</table:aspectNode>
</table:ruleNode>
</table:breakdownTree>
<!-- Y-axis: Rows -->
<table:breakdownTree>
<table:ruleNode id="r010">
<table:aspectNode>
<table:conceptAspect>
<table:qname>eba:CommonEquityTier1Capital</table:qname>
</table:conceptAspect>
</table:aspectNode>
</table:ruleNode>
<table:ruleNode id="r020">
<table:aspectNode>
<table:conceptAspect>
<table:qname>eba:AdditionalTier1Capital</table:qname>
</table:conceptAspect>
</table:aspectNode>
</table:ruleNode>
<!-- ... 100 more rows ... -->
</table:breakdownTree>
<!-- Z-axis: Filters -->
<table:breakdownTree>
<table:ruleNode>
<table:aspectNode>
<table:dimensionAspect dimension="eba:ReportingCurrency"/>
<table:member>
<table:qname>iso4217:EUR</table:qname>
</table:member>
</table:aspectNode>
</table:ruleNode>
</table:breakdownTree>
</table:breakdown>
</table:table>
Processor Must:
1. Parse table structure (XML)
2. Build breakdown trees for X, Y, Z axes
3. Evaluate rule nodes
4. Apply aspect rules
5. Apply dimension relationships
6. Filter facts by Z-axis constraints
7. Match facts to X/Y coordinates
8. Generate layout model
9. Apply rendering hints
10. Handle open/closed axes
11. Handle abstract rows/columns
12. Resolve definition nodes
13. Apply table-specific validation
For 60 COREP templates: MASSIVE COMPLEXITY
Problem 2: Recursive Breakdown Trees
<!-- Rows can have nested breakdowns -->
<table:ruleNode id="r010">
<table:aspectNode>
<table:conceptAspect>
<table:qname>eba:Assets</table:qname>
</table:conceptAspect>
</table:aspectNode>
<!-- Nested breakdown for sub-categories -->
<table:breakdown>
<table:breakdownTree>
<table:ruleNode id="r010.010">
<table:aspectNode>
<table:conceptAspect>
<table:qname>eba:CurrentAssets</table:qname>
</table:conceptAspect>
</table:aspectNode>
<!-- Further nested breakdown -->
<table:breakdown>
<table:breakdownTree>
<table:ruleNode id="r010.010.010">
<table:aspectNode>
<table:conceptAspect>
<table:qname>eba:Cash</table:qname>
</table:conceptAspect>
</table:aspectNode>
</table:ruleNode>
<!-- ... more nested nodes ... -->
</table:breakdownTree>
</table:breakdown>
</table:ruleNode>
<table:ruleNode id="r010.020">
<table:aspectNode>
<table:conceptAspect>
<table:qname>eba:NonCurrentAssets</table:qname>
</table:conceptAspect>
</table:aspectNode>
</table:ruleNode>
</table:breakdownTree>
</table:breakdown>
</table:ruleNode>
Processor must recursively traverse and evaluate!
Each level can have different rules!
Depth can be 5+ levels!
Problem 3: Dimensional Aspect Rules
<!-- Rule node can specify MULTIPLE dimension values -->
<table:ruleNode id="r100">
<table:aspectNode>
<!-- Concept -->
<table:conceptAspect>
<table:qname>eba:Exposure</table:qname>
</table:conceptAspect>
<!-- Dimension 1 -->
<table:dimensionAspect dimension="eba:CountryAxis">
<table:member>
<table:qname>eba:Germany</table:qname>
</table:member>
</table:dimensionAspect>
<!-- Dimension 2 -->
<table:dimensionAspect dimension="eba:ExposureTypeAxis">
<table:member>
<table:qname>eba:CorporateExposures</table:qname>
</table:member>
</table:dimensionAspect>
<!-- Dimension 3 -->
<table:dimensionAspect dimension="eba:MaturityAxis">
<table:member>
<table:qname>eba:LessThan1Year</table:qname>
</table:member>
</table:dimensionAspect>
</table:aspectNode>
</table:ruleNode>
This single row specifies:
├─ Concept: Exposure
├─ Country: Germany
├─ Type: Corporate
└─ Maturity: < 1 year
Processor must match facts with ALL four aspects!
Problem 4: Open vs. Closed Axes
<!-- Closed axis: Only specified members allowed -->
<table:breakdownTree>
<table:ruleNode>
<table:aspectNode>
<table:dimensionAspect dimension="eba:CountryAxis"
closed="true">
<table:member><table:qname>eba:Germany</table:qname></table:member>
<table:member><table:qname>eba:France</table:qname></table:member>
<table:member><table:qname>eba:Italy</table:qname></table:member>
</table:dimensionAspect>
</table:aspectNode>
</table:ruleNode>
</table:breakdownTree>
Closed = Only these three countries allowed
Facts for other countries: INVALID
<!-- Open axis: Any member from dimension allowed -->
<table:breakdownTree>
<table:ruleNode>
<table:aspectNode>
<table:dimensionAspect dimension="eba:CountryAxis"
closed="false">
<!-- All members of CountryAxis allowed -->
</table:dimensionAspect>
</table:aspectNode>
</table:ruleNode>
</table:breakdownTree>
Open = Any country allowed
Processor must dynamically create rows for all present countries
Problem 5: Definition Nodes
<!-- Definition nodes reference other structures -->
<table:ruleNode>
<table:definitionNode>
<table:definitionNodeReference
xlink:href="eba-corep-common.xml#definition_AssetBreakdown"/>
</table:definitionNode>
</table:ruleNode>
Processor must:
1. Resolve reference to external file
2. Load referenced definition
3. Apply definition in current context
4. Handle circular references (prohibited but might exist)
Real-World Complexity Example:
EBA COREP Template C 08.01: Exposures by Asset Class
Structure:
├─ 150 rows (asset classes and breakdowns)
├─ 20 columns (maturity bands, counterparty types)
├─ 3 Z-axis filters (currency, accounting standard, country)
├─ 5 levels of nested breakdowns
├─ Mix of open and closed axes
├─ Multiple dimensional constraints per row
└─ Cross-references to other templates
Processor must:
├─ Evaluate 150 × 20 = 3,000 cells
├─ For each cell:
│ ├─ Resolve row breakdown (5 levels deep)
│ ├─ Resolve column breakdown
│ ├─ Apply Z-axis filters
│ ├─ Match facts with all constraints
│ ├─ Validate dimensional consistency
│ └─ Check for required vs. optional cells
└─ Total: Thousands of evaluations
For one template!
COREP has 60+ templates!
Why This Is Hard:
Complexity Sources:
1. Three-dimensional thinking
├─ Not just rows and columns
├─ Must think in 3D
└─ Z-axis filtering is non-intuitive
2. Recursive structures
├─ Breakdowns within breakdowns
├─ Arbitrary depth
└─ Must track context through recursion
3. Dimensional combinations
├─ Multiple dimensions per cell
├─ Combinatorial explosion
└─ Constraint validation
4. Dynamic axes
├─ Open axes create rows at runtime
├─ Don't know structure until processing
└─ Cannot pre-compute layout
5. Cross-references
├─ Templates reference other templates
├─ Definition nodes reference external structures
└─ Circular reference detection needed
6. Performance
├─ Large templates (150+ rows × 20+ columns)
├─ Must be fast (regulatory deadlines)
└─ Must handle 60+ templates
Development Effort:
├─ Table Linkbase alone: 12-16 person-months
├─ Requires specialized expertise
├─ Few developers understand it well
└─ Debugging is extremely difficult
GLOMIDCO's Experience:
Table Linkbase Implementation:
├─ Took 14 months (2 senior developers)
├─ 50,000+ lines of code
├─ Most complex XBRL component
├─ Still finding edge cases after 10 years
└─ Pass rate: 95% of conformance suite
Challenges:
├─ Specification is dense (200+ pages)
├─ Few real-world examples
├─ Testing requires full COREP/FINREP taxonomies
├─ Performance optimization critical
└─ Interaction with dimensions is subtle
Verdict: HARDEST part of XBRL processor
What Are Tuples?
Tuples are a way to group related facts in XBRL 2.1.
<!-- Without tuples: Hard to relate facts -->
<xbrl:Director contextRef="c1">John Smith</xbrl:Director>
<xbrl:DirectorSalary contextRef="c1" unitRef="USD">500000</xbrl:DirectorSalary>
<xbrl:DirectorBonus contextRef="c1" unitRef="USD">100000</xbrl:DirectorBonus>
<xbrl:Director contextRef="c1">Jane Doe</xbrl:Director>
<xbrl:DirectorSalary contextRef="c1" unitRef="USD">450000</xbrl:DirectorSalary>
<xbrl:DirectorBonus contextRef="c1" unitRef="USD">80000</xbrl:DirectorBonus>
Question: Which salary goes with which director?
Answer: AMBIGUOUS!
<!-- With tuples: Related facts grouped -->
<xbrl:DirectorCompensation>
<xbrl:Director>John Smith</xbrl:Director>
<xbrl:Salary unitRef="USD">500000</xbrl:Salary>
<xbrl:Bonus unitRef="USD">100000</xbrl:Bonus>
</xbrl:DirectorCompensation>
<xbrl:DirectorCompensation>
<xbrl:Director>Jane Doe</xbrl:Director>
<xbrl:Salary unitRef="USD">450000</xbrl:Salary>
<xbrl:Bonus unitRef="USD">80000</xbrl:Bonus>
</xbrl:DirectorCompensation>
Now clear: Salary/bonus belong to director!
Why Tuples Were Created:
Use Cases:
├─ Multiple items of same type (directors, products, loans)
├─ Related facts that must stay together
├─ Transaction-level data (journal entries)
└─ Lists of items with multiple attributes
Seemed like a good idea in XBRL 1.0/2.0!
Why Tuples Are Problematic:
Problem 1: No Context Reference
<!-- Facts inside tuples have NO contextRef! -->
<xbrl:DirectorCompensation>
<!-- No contextRef on tuple! -->
<xbrl:Director>John Smith</xbrl:Director>
<!-- No contextRef on items inside! -->
<xbrl:Salary unitRef="USD">500000</xbrl:Salary>
</xbrl:DirectorCompensation>
Questions:
├─ What period does this apply to?
├─ What entity?
├─ What dimensions?
└─ UNKNOWN!
Tuple facts are "context-less"!
Problem 2: Cannot Use Dimensions
<!-- Want to report director compensation by segment -->
<xbrl:DirectorCompensation>
<xbrl:Director>John Smith</xbrl:Director>
<xbrl:Salary unitRef="USD">500000</xbrl:Salary>
<!-- But which business segment? -->
<!-- Cannot add dimension to tuple! -->
</xbrl:DirectorCompensation>
Dimensions only work on facts with contexts.
Tuples have no contexts.
Therefore: Tuples incompatible with dimensions!
Problem 3: Cannot Validate Calculations
<xbrl:DirectorCompensation>
<xbrl:Salary unitRef="USD">500000</xbrl:Salary>
<xbrl:Bonus unitRef="USD">100000</xbrl:Bonus>
<xbrl:TotalCompensation unitRef="USD">600000</xbrl:TotalCompensation>
</xbrl:DirectorCompensation>
Want to validate: TotalCompensation = Salary + Bonus
But:
├─ Calculation linkbase works on concepts
├─ Needs contexts to match facts
├─ Tuples have no contexts
└─ Calculation validation IMPOSSIBLE!
Problem 4: Formula Evaluation Fails
<!-- Want formula: TotalCompensation = Salary + Bonus -->
<formula:formula>
<formula:value>$Salary + $Bonus</formula:value>
</formula:formula>
<variable:variable id="Salary">
<variable:filter>
<conceptFilter>
<concept><qname>xbrl:Salary</qname></concept>
</conceptFilter>
</variable:filter>
</variable:variable>
Problem:
├─ Variables bind by matching contexts
├─ Tuple items have no contexts
├─ Cannot bind variables
└─ Formula FAILS!
Problem 5: Dimensional Filtering Impossible
<!-- Want to query: "Give me all director salaries for Retail segment" -->
With dimensions:
SELECT *
FROM facts
WHERE concept = 'Salary'
AND dimension[BusinessSegmentAxis] = 'RetailSegment'
Easy!
With tuples:
SELECT *
FROM tuples
WHERE ... ???
Cannot filter by dimensions!
Cannot filter by period!
Cannot filter by entity!
IMPOSSIBLE!
Why Tuples Were Deprecated:
XBRL 2.1 Specification (2003):
├─ Included tuples
└─ Seemed useful
Experience (2003-2010):
├─ Tuples incompatible with dimensions (2006)
├─ Cannot validate calculations
├─ Cannot use formulas
├─ Query/analysis difficult
└─ Consensus: Tuples were a mistake
Deprecation (2010+):
├─ XBRL International: "Don't use tuples"
├─ Use dimensions instead
├─ But cannot remove (backwards compatibility)
└─ Status: Deprecated but still in spec
The Right Way: Use Dimensions
<!-- Instead of tuple, use dimensions -->
<!-- Director 1: John Smith -->
<context id="c_johnsmith">
<entity>
<identifier>12345678</identifier>
<segment>
<xbrldi:explicitMember dimension="company:DirectorAxis">
company:JohnSmithMember
</xbrldi:explicitMember>
</segment>
</entity>
<period><instant>2024-12-31</instant></period>
</context>
<company:DirectorName contextRef="c_johnsmith">John Smith</company:DirectorName>
<company:DirectorSalary contextRef="c_johnsmith" unitRef="USD">500000</company:DirectorSalary>
<company:DirectorBonus contextRef="c_johnsmith" unitRef="USD">100000</company:DirectorBonus>
<!-- Director 2: Jane Doe -->
<context id="c_janedoe">
<entity>
<identifier>12345678</identifier>
<segment>
<xbrldi:explicitMember dimension="company:DirectorAxis">
company:JaneDoeMe mber
</xbrldi:explicitMember>
</segment>
</entity>
<period><instant>2024-12-31</instant></period>
</context>
<company:DirectorName contextRef="c_janedoe">Jane Doe</company:DirectorName>
<company:DirectorSalary contextRef="c_janedoe" unitRef="USD">450000</company:DirectorSalary>
<company:DirectorBonus contextRef="c_janedoe" unitRef="USD">80000</company:DirectorBonus>
Benefits:
✅ Can filter by director dimension
✅ Can add other dimensions (segment, geography)
✅ Can validate calculations
✅ Can use formulas
✅ Can query easily
✅ Works with all XBRL features
But Tuples Still Exist!
Reality:
├─ Tuples deprecated but not removed
├─ Old taxonomies still use tuples
├─ Some countries mandate tuple usage (legacy)
├─ Processors MUST support tuples
└─ Cannot ignore them
Examples of Tuple Usage:
├─ XBRL GL (journal entries use tuples)
├─ Some US GAAP extensions (legacy)
├─ Some Asian taxonomies
└─ Old taxonomies (pre-2010)
Processor Burden:
├─ Must parse tuple structures
├─ Must handle nested tuples
├─ Must validate tuple integrity
├─ But cannot use modern features
└─ Technical debt in specification
Processing Complexity:
Tuple Processing Requires:
1. Separate parsing logic
├─ Tuples are NOT items
├─ Different XML structure
└─ Different validation rules
2. Nested tuple handling
├─ Tuples can contain tuples
├─ Arbitrary depth
└─ Recursive processing
3. Context-less validation
├─ Cannot validate contexts (none exist!)
├─ Must validate structure
└─ Must validate completeness
4. Special query logic
├─ Cannot use standard fact queries
├─ Must traverse tuple structure
└─ Must handle parent-child relationships
5. Conversion to modern formats
├─ When converting to xBRL-JSON
├─ How to represent tuples?
├─ No standard mapping
└─ Vendor-specific solutions
Development Effort:
├─ Tuple support: 3-4 person-months
├─ Rarely used but MUST be supported
├─ Tests in conformance suite
└─ Technical debt from deprecated feature
GLOMIDCO's Experience:
Tuple Implementation:
├─ Required for conformance
├─ Rarely used by customers (< 5% of filings)
├─ Added complexity to codebase
├─ Performance overhead (separate code path)
└─ Recommendation: Avoid tuples if possible
When Customers Use Tuples:
├─ Usually legacy taxonomies
├─ Or XBRL GL implementations
├─ We support but recommend dimensions
└─ Some customers stuck (regulatory requirement)
Summary:
Tuples:
├─ Old XBRL 2.1 feature
├─ Deprecated since 2010
├─ Incompatible with dimensions
├─ Incompatible with formulas
├─ Difficult to query/analyze
├─ Still in specification (backwards compatibility)
├─ Processors must support (technical debt)
└─ Use dimensions instead!
Why Processors Must Handle Tuples:
├─ Conformance suites test tuples
├─ Legacy filings contain tuples
├─ Some jurisdictions require tuples
├─ Backwards compatibility essential
└─ Cannot ignore them
Complexity Added:
├─ 3-4 person-months development
├─ Separate code paths
├─ Different validation logic
├─ Conversion challenges
└─ All for deprecated feature!
What Are Conformance Suites?
XBRL International provides test suites:
├─ XBRL 2.1 Conformance Suite (500+ tests)
├─ Dimensions 1.0 Conformance Suite (300+ tests)
├─ Formula 1.0 Conformance Suite (1,000+ tests)
├─ Inline XBRL Conformance Suite (200+ tests)
└─ Table Linkbase Conformance Suite (150+ tests)
Total: 2,000+ tests!
Each test has:
├─ Input (taxonomy + instance)
├─ Expected result (valid/invalid + error codes)
└─ Specification reference
GLOMIDCO's Experience:
Finding 1: Nearly Impossible to Pass 100%
GLOMIDCO XBRL Processor Results:
├─ XBRL 2.1: 98% pass (10 failures)
├─ Dimensions 1.0: 97% pass (9 failures)
├─ Formula 1.0: 85% pass (150 failures!)
├─ Inline XBRL: 99% pass (2 failures)
└─ Table Linkbase: 95% pass (8 failures)
Overall: ~94% pass rate
Arelle (most complete):
├─ XBRL 2.1: 99.5% pass
├─ Dimensions 1.0: 99% pass
├─ Formula 1.0: 98% pass
├─ Inline XBRL: 99.5% pass
└─ Table Linkbase: 98% pass
Overall: ~98% pass rate
Even Arelle doesn't pass 100%!
Finding 2: Contradictory Tests
Test 123: "Context must have entity identifier"
└─ Instance without identifier → INVALID
Test 456: "Context can omit identifier in certain cases"
└─ Instance without identifier → VALID
Both tests cannot be correct!
Specification ambiguous!
Processor must choose interpretation!
Finding 3: Extension Testing Problem
Test: "Processor must validate extension concepts"
Problem:
├─ GLOMIDCO is "closed" processor
├─ Extensions allowed but not validated
├─ Extension validation would require:
│ ├─ Runtime schema compilation
│ ├─ Dynamic type checking
│ └─ Performance degradation
└─ Architectural decision: Pass through extensions
Result: Test FAILS
But:
├─ Design decision, not bug
├─ Trade-off: Performance vs. Full validation
└─ Acceptable in production use
Finding 4: Specification Ambiguities
Specification says:
"The precision attribute indicates the accuracy of the value"
Test 789:
├─ Fact: <concept precision="6">1234.56</concept>
├─ Expected: Valid
└─ GLOMIDCO result: Invalid
Why?
├─ Spec ambiguous about precision semantics
├─ Is it significant figures?
├─ Is it decimal places?
├─ Different interpretations possible
└─ Test assumes one interpretation
GLOMIDCO chose different interpretation!
Both defensible!
Finding 5: Edge Cases Everywhere
Test 999: "Fact with empty string value"
<concept></concept>
Questions:
├─ Is this valid?
├─ Is empty string different from nil?
├─ What if type is numeric? Still valid?
├─ Should processor reject or accept?
└─ Specification unclear!
Conformance suite tests BOTH interpretations!
Impossible to pass both!
Conclusion:
Achieving 100% conformance: IMPOSSIBLE
├─ Contradictory tests
├─ Specification ambiguities
├─ Architectural trade-offs
├─ Extension validation conflicts
└─ Edge case interpretations vary
Realistic goal: 95-98% pass rate
Above 98%: Diminishing returns
XBRL Processor Components:
1. Core XML Processing (2-3 person-months)
├─ XML parser (SAX/DOM)
├─ Schema validation
└─ Namespace handling
2. Taxonomy Loading (6-8 person-months)
├─ Schema parsing
├─ Linkbase parsing (5 types)
├─ Relationship building
├─ Concept dictionary
└─ Network construction
3. Instance Processing (4-6 person-months)
├─ Context parsing
├─ Unit parsing
├─ Fact extraction
├─ Tuple handling (deprecated but required!)
└─ Footnote processing
4. Validation Engine (8-12 person-months)
├─ Schema validation
├─ Context validation
├─ Calculation validation (complex!)
├─ Dimensional validation
└─ Reference validation
5. Dimensional Support (12-18 person-months)
├─ Explicit dimensions
├─ Typed dimensions
├─ Hypercube filtering
├─ Dimension defaults
└─ Constraint validation
6. Formula Engine (18-24 person-months)
├─ Formula parsing
├─ Variable binding
├─ XPath evaluation
├─ Assertion checking
└─ Function libraries
7. Table Linkbase (12-16 person-months) ⚠️ MOST COMPLEX
├─ Table structure parsing (3D: X/Y/Z axes)
├─ Breakdown tree evaluation (recursive)
├─ Rule node processing
├─ Aspect rule evaluation
├─ Open vs. closed axis handling
├─ Definition node resolution
├─ Layout model generation
└─ Rendering support
8. Tuple Support (3-4 person-months) ⚠️ DEPRECATED BUT REQUIRED
├─ Tuple structure parsing
├─ Nested tuple handling
├─ Context-less validation
├─ Special query logic
└─ Conversion to modern formats
9. Inline XBRL (6-10 person-months)
├─ HTML parsing
├─ Inline tag extraction
├─ Transformation registry
└─ XBRL generation
10. Performance Optimization (6-12 person-months)
├─ Caching strategies
├─ Indexing
├─ Memory management
└─ Parallel processing
11. Testing and QA (12-18 person-months)
├─ Unit tests
├─ Integration tests
├─ Conformance suites (2,000+ tests!)
├─ Performance tests
└─ Regression testing
Total: 89-131 person-months = 7.4-11 person-years
With team of 3-5 developers: 2-3 years calendar time
NOTE: Table Linkbase alone is 12-16 months and is often
the HARDEST component to implement correctly!
For Basic Use Cases:
Minimum Features:
├─ XBRL 2.1 (core)
├─ Dimensions 1.0
├─ Basic validation
└─ Instance generation
Effort: 24-36 person-months (2-3 person-years)
Calendar time (3 developers): 8-12 months
For Production Use:
Production Features:
├─ XBRL 2.1 (complete)
├─ Dimensions 1.0 (complete)
├─ Formula 1.0 (basic)
├─ Inline XBRL 1.1
├─ Robust validation
├─ Performance optimization
└─ Error handling
Effort: 60-90 person-months (5-7.5 person-years)
Calendar time (5 developers): 12-18 months
For Commercial Product:
Commercial Features:
├─ All production features
├─ Formula 1.0 (complete)
├─ Table Linkbase 1.0
├─ Multiple format support (JSON, CSV)
├─ API and SDK
├─ Documentation
├─ Support infrastructure
└─ Continuous updates
Effort: 120-180 person-months (10-15 person-years)
Calendar time (8-10 developers): 15-18 months initial
+ ongoing maintenance
Build vs. Buy Analysis:
BUILD (Internal Development):
├─ Initial development: €500,000 - €1,500,000
│ └─ (5 developers × 12-24 months × €50k/year)
├─ Testing and QA: €200,000
├─ Documentation: €50,000
├─ Maintenance: €200,000/year
└─ Total 5 years: €2,000,000 - €3,000,000
BUY (Commercial Processor):
├─ License: €50,000 - €200,000 (one-time or annual)
├─ Integration: €100,000
├─ Maintenance: €20,000/year
└─ Total 5 years: €250,000 - €500,000
USE OPEN SOURCE (Arelle):
├─ License: €0
├─ Integration: €150,000
├─ Support/consulting: €50,000/year
└─ Total 5 years: €400,000
Recommendation:
├─ Single use case: Buy or use open source
├─ Multiple use cases: Buy commercial
├─ Core business capability: Consider building
├─ Strategic differentiator: Build
Decision Matrix:
Use Case | Recommendation |
────────────────────────────────────────────────────────────────
Single jurisdiction, single report | Point solution OK |
Multiple jurisdictions | Generic processor |
Multiple report types | Generic processor |
Need to process incoming XBRL | Generic processor |
Need formula validation | Generic processor |
High volume (>1,000 reports/year) | Generic processor |
Integration with enterprise systems | Generic processor |
────────────────────────────────────────────────────────────────
Evaluation Criteria:
Evaluating XBRL Processors:
1. Specification Support
├─ Which XBRL specs supported?
├─ Conformance suite results?
└─ Updates with new specifications?
2. Performance
├─ How fast for typical instance?
├─ Memory usage?
└─ Can handle large instances?
3. Integration
├─ Programming language?
├─ API availability?
└─ Deployment options?
4. Support and Maintenance
├─ Vendor stability?
├─ Update frequency?
└─ Support quality?
5. Total Cost of Ownership
├─ License cost?
├─ Integration cost?
├─ Maintenance cost?
└─ Migration risk?
Build vs. Integrate:
Building XBRL functionality into product?
Options:
1. Build Custom (DON'T unless strategic)
├─ Cost: €2M-3M
├─ Time: 2-3 years
├─ Risk: High
└─ Maintenance: Ongoing
2. Integrate Commercial Processor
├─ Cost: €200k-500k
├─ Time: 6-12 months
├─ Risk: Low
└─ Maintenance: Vendor handles
3. Use Open Source (Arelle)
├─ Cost: €150k-400k
├─ Time: 6-12 months
├─ Risk: Medium
└─ Maintenance: Shared with community
Recommendation: Integrate (Option 2 or 3)
Architecture Patterns:
Pattern 1: Embedded Processor
├─ Processor library embedded in application
├─ Direct API calls
├─ Best for: Thick clients, desktop apps
Pattern 2: Processor Service
├─ Processor as microservice
├─ REST API
├─ Best for: Cloud-native, distributed systems
Pattern 3: Processing Pipeline
├─ Processor in ETL pipeline
├─ Batch processing
├─ Best for: High volume, regulatory filings
Pattern 4: Hybrid
├─ Processor service for validation
├─ Embedded for generation
├─ Best for: Complex enterprise architectures
Point Solutions:
Generic XBRL Processors:
Development Complexity:
Existing Processors:
1. Don't Underestimate XBRL Complexity
XBRL ≠ "Just XML with financial data"
XBRL = Complex specification family
+ Multi-file taxonomy structures
+ Relationship networks
+ Dimensional modeling
+ Formula evaluation
+ Table Linkbase (3D structures!)
+ Tuples (deprecated but required)
+ Edge cases everywhere
Calculation linkbase: Not just a calculator
Table linkbase: Hardest component (12-16 months)
Tuples: Technical debt from deprecated feature
2. Point Solutions Are Technical Debt
Short-term: Fast, cheap, easy
Long-term: Expensive, inflexible, limiting
3. Generic Processors Are Strategic Assets
Initial investment: Higher
Long-term value: Much higher
Flexibility: Maximum
Risk: Minimum
4. Building Is Harder Than It Looks
Effort: 10-50 person-years
Cost: €2M-3M
Risk: High
Maintenance: Ongoing
Unless XBRL is core business: Don't build, buy or use open source!
5. Even Conformance Is Hard
No processor passes 100%
95-98% is realistic goal
Contradictions exist in specifications
Architectural trade-offs required
For Procurement:
For Development:
For Strategy:
The Bottom Line:
XBRL processing is much harder than it looks. The 100+ page specifications hide enormous complexity. Point solutions work for one use case but fail to scale. Generic processors are expensive but essential for any serious XBRL implementation.
Don't underestimate XBRL. Don't build unless you must. Use proven processors.
This document explains why generic XBRL processors are essential and why building one is a multi-year, multi-million dollar undertaking that most organizations should avoid.