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 |
|---|---|---|---|
|
ODM 1.3.2 |
|
Primary stable model |
|
ODM 2.0 (draft) |
|
Draft implementation |
|
Define-XML 2.0 |
|
Regulatory submission metadata |
|
Define-XML 2.1 |
|
Current Define-XML version |
|
Dataset-XML 1.0.1 |
|
Tabular dataset transmission |
|
CT-XML 1.1.1 |
|
Controlled terminology |
|
ARM 1.0 |
|
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:
StudyEventDefdirectly containsItemGroupRef(no FormDef/FormRef layer)New
WorkflowDefandWorkflowRefelementsStudyhasStudyNameandProtocolNameas 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 ofCodeorExternalCodeLib. odmlib has no way to express anxs: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 itmixed="true"with an optionalxhtml:divchild, allowing XHTML markup. odmlib models the text-only form; anxhtml:divpresent in a source document is dropped on load. Plain-text TranslatedText round-trips exactly. An opaque text-onlydivwas tried in v0.2.1 and withdrawn: it could not carry markup either, since element text is XML-escaped on write. SeeODM_XSD_ALIGNMENT.mdfor 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 listsWhereClauseDef– filtering conditionsCommentDef– annotation definitionsStandards/Standard– CDISC standard references (e.g., SDTM, ADaM)leaf– external document references
Extended elements (additional attributes):
ItemGroupDef– addsStructure,ArchiveLocationID,CommentOID,StandardOID,HasNoDataItemDef– addsDisplayFormat,CommentOID,Origin,ValueListRefMetaDataVersion– addsDefineVersion,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:
Create a new model module importing the base model
Subclass existing elements to add new attributes/elements
Register any new namespaces
Use
local_model=Truewith 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
))