Model Reference

odmlib provides Python model packages for each supported CDISC standard. Select the appropriate package based on the document type you are working with.

Available Model Packages

Package

Standard

Loader

Notes

odmlib.odm_1_3_2

ODM 1.3.2

XMLODMLoader, JSONODMLoader

Primary stable model

odmlib.odm_2_0

ODM 2.0 (draft)

XMLODMLoader with model_package="odm_2_0"

Draft implementation

odmlib.define_2_0

Define-XML 2.0

XMLDefineLoader, JSONDefineLoader

Regulatory submission metadata

odmlib.define_2_1

Define-XML 2.1

XMLDefineLoader with model_package="define_2_1"

Current Define-XML version

odmlib.dataset_1_0_1

Dataset-XML 1.0.1

XMLODMLoader with model_package="dataset_1_0_1"

Tabular dataset transmission

odmlib.ct_1_1_1

CT-XML 1.1.1

XMLODMLoader with model_package="ct_1_1_1"

Controlled terminology

odmlib.arm_1_0

ARM 1.0

XMLArmLoader, JSONArmLoader

Analysis Results Metadata; extends Define-XML 2.1

ODM 1.3.2 Model Structure

The ODM 1.3.2 model follows the CDISC ODM specification hierarchy:

ODM
└── Study
    ├── GlobalVariables (StudyName, StudyDescription, ProtocolName)
    ├── BasicDefinitions (MeasurementUnit)
    └── MetaDataVersion
        ├── Protocol
        │   └── StudyEventRef (links to StudyEventDef)
        ├── StudyEventDef
        │   └── FormRef (links to FormDef)
        ├── FormDef
        │   └── ItemGroupRef (links to ItemGroupDef)
        ├── ItemGroupDef
        │   └── ItemRef (links to ItemDef)
        ├── ItemDef
        │   └── CodeListRef (links to CodeList)
        ├── CodeList (CodeListItem / EnumeratedItem)
        ├── ConditionDef
        ├── MethodDef
        └── Presentation

ODM 2.0 Key Differences

ODM 2.0 uses a flatter structure and adds workflow support:

  • StudyEventDef directly contains ItemGroupRef (no FormDef/FormRef layer)

  • New WorkflowDef and WorkflowRef elements

  • Study has StudyName and ProtocolName as string attributes (not child elements)

  • Timing elements: AbsoluteTimingConstraint, RelativeTimingConstraint, etc.

ODM 2.0 Known Limitations

The ODM 2.0 model is a draft, but every metadata element the ODM 2.0 XSD defines is now modelled. tests/test_odm_2_0_xsd_alignment.py compares the model against the bundled schema and asserts the divergence set equals a declared allowlist, so drift cannot be introduced silently. Two areas remain.

ClinicalData and ReferenceData are not modelled. ODM has no ClinicalData, ReferenceData or Association child, and Location has no Query. The 24 elements of that data layer are scoped to v0.3.0; see ROADMAP.md.

Three deliberate approximations remain, where the XSD says something odmlib’s descriptor model cannot express. Each is documented in the class docstring, and each is caught by ODMSchemaValidator rather than at build time:

  • FormalExpression – the XSD requires exactly one of Code or ExternalCodeLib. odmlib has no way to express an xs:choice, so both children are declared optional; setting neither, or both, builds an object odmlib accepts and the schema rejects.

  • StudyEventGroupDef – the XSD’s repeating (StudyEventGroupRef?, StudyEventRef?) group is approximated by two parallel lists, which emit all groups then all events. Both forms are schema-valid; only an interleaved ordering is lost.

  • TranslatedText – the XSD types it mixed="true" with an optional xhtml:div child, allowing XHTML markup. odmlib models the text-only form; an xhtml:div present in a source document is dropped on load. Plain-text TranslatedText round-trips exactly. An opaque text-only div was tried in v0.2.1 and withdrawn: it could not carry markup either, since element text is XML-escaped on write. See ODM_XSD_ALIGNMENT.md for what real XHTML support would take.

See ODM_XSD_ALIGNMENT.md for the full model/XSD comparison and the remaining work.

Define-XML Extensions

Define-XML extends ODM 1.3.2 with regulatory submission metadata:

New elements in Define-XML 2.1:

  • ValueListDef – permissible value lists

  • WhereClauseDef – filtering conditions

  • CommentDef – annotation definitions

  • Standards / Standard – CDISC standard references (e.g., SDTM, ADaM)

  • leaf – external document references

Extended elements (additional attributes):

  • ItemGroupDef – adds Structure, ArchiveLocationID, CommentOID, StandardOID, HasNoData

  • ItemDef – adds DisplayFormat, CommentOID, Origin, ValueListRef

  • MetaDataVersion – adds DefineVersion, Standards, ValueListDef, WhereClauseDef, CommentDef

Selecting the Right Loader

import odmlib.loader as LD
import odmlib.odm_loader as OL
import odmlib.define_loader as DL

# ODM 1.3.2 XML
loader = LD.ODMLoader(OL.XMLODMLoader(model_package="odm_1_3_2"))

# ODM 2.0 XML
loader = LD.ODMLoader(OL.XMLODMLoader(model_package="odm_2_0"))

# Define-XML 2.1 XML
loader = LD.ODMLoader(DL.XMLDefineLoader(model_package="define_2_1"))

# Define-XML 2.0 JSON
loader = LD.ODMLoader(DL.JSONDefineLoader(model_package="define_2_0"))

# Dataset-XML 1.0.1
loader = LD.ODMLoader(OL.XMLODMLoader(model_package="dataset_1_0_1"))

Creating Custom Extensions

To create a proprietary ODM extension:

  1. Create a new model module importing the base model

  2. Subclass existing elements to add new attributes/elements

  3. Register any new namespaces

  4. Use local_model=True with the full module path

# myext/model.py
import odmlib.odm_1_3_2.model as ODM
import odmlib.typed as T
import odmlib.ns_registry as NS

NS.NamespaceRegistry(prefix="myext", uri="http://example.com/myext")

class ItemDef(ODM.ItemDef):
    CustomAttr = T.String(namespace="myext")

# Load using local_model
loader = LD.ODMLoader(OL.XMLODMLoader(
    model_package="myext",
    local_model=True
))