Skip to content

Preserve xsi:nil state in parsed XBRL facts #1254

Description

@synfonia-llc

Feature Category

  • New API functionality
  • Performance improvement
  • Developer experience improvement
  • Documentation enhancement
  • Tool/utility addition

Problem Statement

Is your feature request related to a problem? Please describe.

The parsed Fact/FactQuery surface does not expose whether a source fact was explicitly filed with xsi:nil="true". A nil fact and a present, non-nil element with empty lexical content both hydrate as value="", numeric_value=None, with no is_nil or nil key.

Current documentation warns that the parser model can be lossy when exact nil provenance matters, and I did not find a public contract promising nil-state preservation. This is therefore an additive feature request rather than a claim that the current documented object shape is broken.

Who would benefit from this feature?

  • Beginner Python users working with SEC filings
  • Financial analysts and researchers
  • Advanced developers building financial applications
  • Data scientists working with financial datasets

Proposed Solution

Describe the solution you'd like

Add an explicit boolean or equivalent nil-state field to the parsed fact model and expose it consistently through FactsView, FactQuery.execute(), and DataFrame projections. A source element with xsi:nil="true" should be distinguishable from a non-nil element whose lexical value is empty.

Describe alternatives you've considered

Callers can reparse the filed instance XML and join nodes back to facts by XML id. That preserves the source bit but duplicates parser work, requires source-document access, and is cumbersome for bulk workflows. Using an empty-string sentinel is not sufficient because the two source states already collide on that representation.

Use Case Example

How would you use this feature?

from pathlib import Path

from edgar.xbrl import XBRL

xbrl = XBRL.from_files(instance_file=Path("xbrl.xml"))
rows = (
    xbrl.query()
    .by_concept("us-gaap:CommitmentsAndContingencies", exact=True)
    .execute()
)

for row in rows:
    print(row["fact_id"], row["value"], row["is_nil"])

Implementation Considerations

Complexity Level:

  • Simple (minor API addition)
  • Moderate (new functionality with existing patterns)
  • Complex (significant architectural changes)

Backwards Compatibility:

  • This feature maintains backwards compatibility
  • This feature might break existing code (please explain below)
  • Unsure about compatibility impact

An additive optional field should preserve existing consumers. DataFrame schemas and serialization tests may need corresponding updates.

Additional Context

Verified environment: EdgarTools import version 5.55.0, Python 3.14.4, Microsoft Windows 11, production edgar/** from main at a0ff18089c844ddfe81bd21a1c7c56f4ed629e55; audit worktree HEAD 70c31469dc7e6d4b386a6f8fe4ce1276d48fca51. The reused editable virtual environment has stale distribution metadata reporting 5.54.0.

Zymeworks accession 0001937653-26-000015 contains two explicit nil facts:

<us-gaap:CommitmentsAndContingencies
    contextRef="c-4" id="f-137" unitRef="usd" xsi:nil="true"/>
<us-gaap:CommitmentsAndContingencies
    contextRef="c-5" id="f-138" unitRef="usd" xsi:nil="true"/>

Both currently return value="", numeric_value=None, no is_nil key, and no nil key. Zevra accession 0001437749-24-026474 contains a non-nil, self-closing ExtensibleList fact (id="c116236184") and exposes the same value-level shape. This empirically demonstrates the collision without assuming a current nil-preservation contract.

XBRL 2.1 section 5.1.1 permits nil-value items, and calculation semantics treat them differently from contributing numeric facts. InstanceParser._extract_facts() currently derives value from text and does not retain the XML Schema-instance nil attribute; the Fact model has no nil-state field.

This is distinct from Draft 69, which concerns extensible-enumeration metadata and resolved values. The ZVRA fact is only a non-nil empty control here.

A live search of the open and closed GitHub issue tracker is still required immediately before submission.


Feature requests are evaluated based on EdgarTools' core principles: Simple yet powerful, accurate financials, beginner-friendly, and joyful UX.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions