Used to interpret XMI Schema
Project description
XMI Schema Python Library
A Python library for interpreting and managing XMI (Cross Model Information) schema data. XMI is an open-source schema for representing built environment information using graph methodology.
Overview
The xmi-schema-python library provides a robust framework for reading, parsing, and managing structural data from JSON dictionaries, converting them into structured Python objects that represent materials, cross-sections, members, connections, and geometric elements.
Feature Parity Status
As of v0.4.0, Phase 5 of the feature-parity plan is complete: base physical entities, their analytical bridge (XmiHasStructuralCurveMember), and the coordinate deduplication point factory are all implemented and fully tested. Phase 6 adds end-to-end integration coverage plus documentation for the new graph patterns so downstream applications can rely on physical ↔ analytical mappings out of the box. This keeps the Python implementation aligned with the C# 0.8.0 reference and ready for the final parity push.
Phase 6 Updates (Testing & Docs)
- ✅ Added integration suites (
tests/xmi/v2/test_integration/) that exercise the entire physical → analytical bridge, including invalid relationship handling and complete model round trips. - ✅ Authored per-entity documentation covering metadata, relationships, and validation guidance for each physical type and its bridge relationship.
- ✅ Surfaced the documentation in this README so consumers can jump directly into the new graph patterns.
| Entity / Relationship | Documentation |
|---|---|
XmiBeam |
docs/entities/XmiBeam.md |
XmiColumn |
docs/entities/XmiColumn.md |
XmiSlab |
docs/entities/XmiSlab.md |
XmiWall |
docs/entities/XmiWall.md |
XmiHasStructuralCurveMember |
docs/relationships/XmiHasStructuralCurveMember.md |
Features
- Two parallel implementations (v1 and v2) with different architectural approaches
- Comprehensive entity support for structural engineering elements
- Pydantic-based validation (v2) for type safety and data integrity
- Shape parameter system supporting 18+ cross-section types
- Relationship tracking between entities
- Error handling with detailed logging
- Well-tested with 138 unit tests and 72% code coverage
Installation
pip install xmi
Development Installation
git clone https://github.com/xmi-schema/xmi-schema-python.git
cd xmi-schema-python
poetry install
Quick Start
Using v2 (Recommended - Pydantic-based)
from xmi.v2.models.xmi_model.xmi_manager import XmiManager
import json
# Load XMI data from JSON file
with open('your_xmi_data.json', 'r') as f:
xmi_dict = json.load(f)
# Parse the XMI data
manager = XmiManager()
xmi_model = manager.read_xmi_dict(xmi_dict)
# Access entities
materials = [e for e in xmi_model.entities
if e.__class__.__name__ == 'XmiStructuralMaterial']
members = [e for e in xmi_model.entities
if e.__class__.__name__ == 'XmiStructuralCurveMember']
# Check for errors
if xmi_model.errors:
for error in xmi_model.errors:
print(f"Error: {error.message}")
Physical Entities & Analytical Bridges
from xmi.v2.models.xmi_model.xmi_manager import XmiManager
manager = XmiManager()
xmi_model = manager.read_xmi_dict(physical_model_dict) # contains XmiBeam/XmiColumn + curves
beams = [e for e in xmi_model.entities if e.entity_type == "XmiBeam"]
bridges = [
rel for rel in xmi_model.relationships
if rel.entity_type == "XmiHasStructuralCurveMember"
]
for bridge in bridges:
print(f"Physical {bridge.source.name} → Analytical {bridge.target.name}")
Each bridge guarantees that the physical entity shares a deduplicated coordinate graph with its analytical counterpart, so graph queries can follow identity relationships rather than re-computing geometry.
Using v1 (Legacy - Slots-based)
from xmi.v1.xmi_manager import XmiManager
import json
# Load and parse XMI data
with open('your_xmi_data.json', 'r') as f:
xmi_dict = json.load(f)
manager = XmiManager()
xmi_model = manager.read_xmi_dict(xmi_dict)
# Access entities
materials = [e for e in xmi_model.entities
if isinstance(e, XmiStructuralMaterial)]
Implemented Entities
Core Structural Entities
| Entity Name | v1 Status | v2 Status | Description |
|---|---|---|---|
| StructuralMaterial | Material definitions (concrete, steel, timber, etc.) | ||
| StructuralPointConnection | Nodal points in 3D space with coordinates | ||
| CrossSection | Cross-section definitions with shape parameters | ||
| StructuralCurveMember | Linear structural members (beams, columns, braces) | ||
| StructuralSurfaceMember | Surface elements (slabs, walls, plates) | ||
| StructuralStorey | Building level/storey definitions | ||
| StructuralUnit | Unit system definitions (SI, Imperial) | ||
| StructuralModel | Top-level model container |
Geometry Classes
| Geometry Type | v1 Status | v2 Status | Description |
|---|---|---|---|
| Point3D | 3D point coordinates (X, Y, Z) | ||
| Line3D | Linear segments between two points | ||
| Arc3D | Circular arc segments with center point | ||
| Segment | Generic segment wrapper for geometry |
Relationship Types
| Relationship | v1 Status | v2 Status | Purpose |
|---|---|---|---|
| HasStructuralMaterial | Links entities to material definitions | ||
| HasCrossSection | Links members to cross-section definitions | ||
| HasStructuralNode | Links members to point connections | ||
| HasSegment | Links members to geometric segments | ||
| HasGeometry | Links entities to geometric elements | ||
| HasLine3D | Links segments to line geometry | ||
| HasPoint3D | Links entities to point geometry | ||
| HasStructuralStorey | Links entities to storey definitions |
Supported Cross-Section Shapes
The library supports 18 different cross-section shape types with strongly-typed parameters:
Solid Sections
- Circular - Parameters:
D(diameter) - Rectangular - Parameters:
H(height),B(width)
Structural Steel Shapes
- I-Shape - Parameters:
D,B,T(flange thickness),t(web thickness),r(radius) - C-Shape - Parameters:
D,B,T,t,r - T-Shape - Parameters:
D,B,T,t,r - L-Shape - Parameters:
D,B,T,t
Hollow Sections
- Circular Hollow - Parameters:
D(outer diameter),T(wall thickness) - Square Hollow - Parameters:
D(outer dimension),T(wall thickness) - Rectangular Hollow - Parameters:
H(height),B(width),T(wall thickness)
Specialty Shapes
- Trapezium - Parameters:
H,B1(top width),B2(bottom width) - Polygon - Parameters:
N(number of sides),R(circumradius)
Angle Sections
- Equal Angle - Parameters:
D,B,T,t - Unequal Angle - Parameters:
D,B,T1,T2,t
Bar Sections
- Flat Bar - Parameters:
H,B - Square Bar - Parameters:
D - Round Bar - Parameters:
D - Deformed Bar - Parameters:
D
Custom
- Custom - Flexible parameters for non-standard shapes
- Unknown - Fallback for unrecognized shapes
Architecture
v1 Implementation (src/xmi/v1/)
- Memory-efficient using
__slots__ - Manual property setters/getters
- Procedural entity creation in
XmiManager.read_xmi_dict() - Direct dictionary parsing
v2 Implementation (src/xmi/v2/)
- Pydantic models for validation and type safety
- Modular architecture with entity type mappings
- Mapping-based entity resolution via
ENTITY_CLASS_MAPPING XmiModel.load_from_dict()handles instantiation- Located in
src/xmi/v2/utils/xmi_entity_type_mapping.py
Key Differences
- v1: Procedural parsing with explicit entity creation logic
- v2: Declarative mapping approach with automatic type resolution
Point Factory & Coordinate Deduplication
The v2 model keeps a single source of truth for Point3D data by routing all coordinate creation through XmiModel.create_point_3d(). When XmiModel.load_from_dict() instantiates geometry-heavy entities (such as XmiStructuralPointConnection, XmiLine3D, and XmiArc3D), it injects this point factory into their from_dict loaders. The factory quantizes coordinates using a tight tolerance (default 1e-10) and reuses an existing XmiPoint3D instance whenever the incoming coordinates match within that tolerance. This lightweight cache means:
- Members, segments, and relationships that reference the same coordinates automatically share the same
XmiPoint3Dobject, producing a graph-friendly topology. - Structural relationships like
XmiHasStructuralCurveMembercan rely on identity equality instead of manual coordinate comparisons when traversing the graph. - Geometry parsing remains deterministic even if the input JSON contains duplicate nodes, since the first occurrence becomes canonical.
You can opt into the same behavior for custom loaders by exposing a point_factory parameter on your entity’s from_dict() function and calling it instead of instantiating XmiPoint3D directly:
@classmethod
def from_dict(cls, data: dict, point_factory: Callable[[float, float, float], XmiPoint3D]):
x, y, z = data["Point"]["X"], data["Point"]["Y"], data["Point"]["Z"]
point = point_factory(x, y, z)
return cls(point=point), []
This pattern keeps the object graph compact while still letting you model additional tolerances or caching strategies by swapping in a different factory.
Development
Running Tests
# Run all tests
poetry run pytest
# Run tests with coverage
poetry run pytest --cov=src/xmi --cov-report=html --cov-report=term
# Run specific test suite
poetry run pytest tests/xmi/v2/
# Run specific test file
poetry run pytest tests/xmi/v2/test_entities/test_xmi_material.py
Test Coverage
Current test coverage: ~72% (188 tests passing)
- v1 Coverage: ~75% average
- v2 Coverage: ~85% average
- Total Tests: 188 passing
- Coverage Report: Generated in
htmlcov/index.html
Generating Coverage Reports Locally
# Generate coverage report with HTML output
poetry run pytest --cov=src/xmi --cov-report=html --cov-report=term
# Open the HTML report in your browser
open htmlcov/index.html # macOS
xdg-open htmlcov/index.html # Linux
start htmlcov/index.html # Windows
Coverage in CI/CD
Coverage is automatically calculated on every PR:
- PR Validation: Runs tests with coverage on Python 3.12
- Coverage Comment: Bot comments coverage metrics on PRs
- Artifacts: HTML coverage reports are uploaded as workflow artifacts
- No Cloud Service: All coverage processing happens locally in GitHub Actions
The PR validation workflow will:
- Run all tests with coverage tracking
- Generate XML and HTML coverage reports
- Calculate coverage percentage
- Post a comment on the PR with coverage metrics
- Upload the full HTML report as an artifact (downloadable for 30 days)
Building the Package
# Build distribution
poetry build
# Install locally (Linux/Mac)
bash install_package.sh
# Install locally (Windows)
setup_and_install.bat
Project Structure
xmi-schema-python/
├── src/xmi/
│ ├── v1/ # Legacy implementation
│ │ ├── entities/ # Entity classes with __slots__
│ │ ├── enums/ # Enumeration types
│ │ ├── geometries/ # 3D geometry classes
│ │ ├── relationships/ # Entity relationships
│ │ ├── shapes/ # Shape definitions
│ │ ├── xmi_manager.py # Entry point for v1
│ │ └── xmi_model.py # Model container
│ │
│ └── v2/ # Modern Pydantic implementation
│ ├── models/
│ │ ├── bases/ # Base classes for entities/relationships
│ │ ├── entities/ # Pydantic entity models
│ │ ├── enums/ # Typed enumerations
│ │ ├── geometries/ # Pydantic geometry models
│ │ ├── relationships/ # Pydantic relationship models
│ │ ├── shape_parameters/# Strongly-typed shape parameters
│ │ └── xmi_model/ # Model and manager
│ └── utils/
│ ├── xmi_entity_type_mapping.py # Entity type mappings
│ └── xmi_errors.py # Error definitions
│
├── tests/ # Comprehensive test suite
│ ├── xmi/v1/ # v1 tests
│ └── xmi/v2/ # v2 tests
│
├── .github/workflows/ # CI/CD workflows
│ ├── pr-validation.yml # PR test validation
│ └── python-publish.yml # PyPI publishing
│
├── pyproject.toml # Poetry configuration
├── pytest.ini # Pytest configuration
└── README.md # This file
Error Handling
Both versions include comprehensive error handling:
# Errors are accumulated without stopping execution
xmi_model = manager.read_xmi_dict(xmi_dict)
# Check for parsing errors
if xmi_model.errors:
for error in xmi_model.errors:
print(f"Entity: {error.entity_type}")
print(f"Index: {error.entity_index}")
print(f"Message: {error.message}")
if error.raw_object:
print(f"Raw data: {error.raw_object}")
Error Types (v2)
XmiError- Base error classXmiInconsistentDatatypeError- Type mismatch errorsXmiMissingReferenceInstanceError- Missing entity referencesXmiMissingRequiredAttributeError- Required field missing
CI/CD
The project uses GitHub Actions for continuous integration:
Pull Request Validation
- Runs on all PRs to
mainbranch - Tests against Python 3.9, 3.10, 3.11, 3.12
- All tests must pass before merging
- Uses Poetry for dependency management
- Cached dependencies for faster builds
Publishing Workflow
- Automatic semantic versioning
- Publishes to PyPI on merge to
main - Creates GitHub releases with artifacts
- Updates version in
pyproject.toml
Contributing
Contributions are welcome! Please follow these guidelines:
- Fork the repository
- Create a feature branch
- Make your changes with tests
- Ensure all tests pass:
poetry run pytest - Submit a pull request
Adding New Entities (v2)
- Create entity class in
src/xmi/v2/models/entities/ - Add tests in
tests/xmi/v2/test_entities/ - Add to
ENTITY_CLASS_MAPPINGinxmi_entity_type_mapping.py - If relationships exist, add to
RELATIONSHIP_CLASS_MAPPING - Update dependency order in
_rearrange_xmi_dict()if needed
License
This project is licensed under the MIT License - see the LICENSE file for details.
Links
- PyPI: https://pypi.org/project/xmi/
- GitHub: https://github.com/xmi-schema/xmi-schema-python
- XMI Schema: https://xmi-schema.org
- Documentation:
docs/entities/(per-class) anddocs/relationships/(bridge patterns)
Acknowledgments
Based on the XMI Schema specification and inspired by the C# implementation:
Version History
- v0.4.0 (Phase 6) - Physical entities + bridges, coordinate deduplication, integration coverage, per-entity documentation
- v0.3.0 - Added shape parameters, improved v2 implementation
- v0.2.x - Enhanced entity support, improved testing
- v0.1.x - Initial release with v1 implementation
Status Legend:
- Fully implemented and tested
- Partially implemented
- Not yet implemented
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file xmi-0.5.0.tar.gz.
File metadata
- Download URL: xmi-0.5.0.tar.gz
- Upload date:
- Size: 158.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
45853ec74855839d98e7dd999a479c8a04af5a81405dc70f4802d3763e4446c1
|
|
| MD5 |
af7086f53a8636057bf15fd915da687c
|
|
| BLAKE2b-256 |
f8ce0039133c65c3e750c14801f08422c6f66f505c0390c9beaf316852dbb200
|
File details
Details for the file xmi-0.5.0-py3-none-any.whl.
File metadata
- Download URL: xmi-0.5.0-py3-none-any.whl
- Upload date:
- Size: 243.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
96402fe758f1443f4cc39715e1eb31e332a056f88541a718877c2d8f6bd34725
|
|
| MD5 |
e1e5754511eb992fc579df0302204452
|
|
| BLAKE2b-256 |
0f70d4cfbd821d91073d360b3e9ef519b07d8029f200bb42df50fdfdd5758981
|