Skip to main content

FHIR Mapping Language

The Ignixa.FhirMappingLanguage package provides execution of FHIR Mapping Language (FML) transformations via a compiled expression AST.

Installation

dotnet add package Ignixa.FhirMappingLanguage

Quick Start

using Ignixa.FhirMappingLanguage.Evaluation;
using Ignixa.Abstractions;

// Define the mapping context
var context = new MappingContext(sourceElement, targetElement);

// Create the evaluator
var options = new MappingEvaluatorOptions();
var evaluator = new MappingEvaluator(options);

// Execute the mapping (assuming a pre-parsed StructureMap)
var result = await evaluator.EvaluateAsync(structureMap, context, cancellationToken);

if (result.IsSuccessful)
{
Console.WriteLine("Mapping succeeded");
Console.WriteLine($"Output: {result.Value}");
}
else
{
foreach (var error in result.Errors)
{
Console.WriteLine($"Error: {error.Message}");
}
}

Mapping Evaluation

MappingEvaluator

Executes pre-parsed StructureMap transformations using FHIRPath expressions.

var evaluator = new MappingEvaluator(options);

var result = await evaluator.EvaluateAsync(
structureMap, // Pre-parsed StructureMap
context, // MappingContext with source/target elements
cancellationToken
);

// Check result
if (result.IsSuccessful)
{
var output = result.Value; // Transformed element
}
else
{
foreach (var error in result.Errors)
{
Console.WriteLine($"Error at {error.Location}: {error.Message}");
if (error.InnerException != null)
{
Console.WriteLine($"Details: {error.InnerException.Message}");
}
}
}

MappingContext

public class MappingContext : ITransformContext
{
// Create context from source and target elements
public MappingContext(IElement source, IElement target)
{
Source = source;
Target = target;
}

// Source element being transformed
public IElement Source { get; }

// Target element being populated
public IElement Target { get; }

// Custom variables
public Dictionary<string, object> Variables { get; }

// Pass-through metadata
public Dictionary<string, object> Metadata { get; }
}

Execution Results

ExecutionResult<T>

public class ExecutionResult<T>
{
// True if evaluation succeeded
public bool IsSuccessful { get; }

// The result value (on success)
public T? Value { get; }

// Execution errors (if any)
public IReadOnlyList<ExecutionError> Errors { get; }
}

ExecutionError

public class ExecutionError
{
// Error message
public string Message { get; }

// Source location information
public ISourcePositionInfo? Location { get; }

// Underlying exception (if any)
public Exception? InnerException { get; }
}

Error Handling

Error Mode

var options = new MappingEvaluatorOptions
{
// Stop on first error
ErrorMode = ErrorMode.FailFast,

// Or: collect all errors
// ErrorMode = ErrorMode.Collect
};

var result = await evaluator.EvaluateAsync(structureMap, context, cancellationToken);

if (!result.IsSuccessful)
{
foreach (var error in result.Errors)
{
Console.WriteLine($"{error.Message} at line {error.Location?.StartLine}");
}
}

Exceptions

MappingExecutionException

Thrown for fatal mapping execution errors:

try
{
var result = await evaluator.EvaluateAsync(structureMap, context, cancellationToken);
}
catch (MappingExecutionException ex)
{
Console.WriteLine($"Mapping failed: {ex.Message}");
if (ex.InnerException != null)
{
Console.WriteLine($"Cause: {ex.InnerException.Message}");
}
}

Expression Types

The StructureMap AST includes the following expression types:

// Mapping rule (source → target transform)
public class RuleExpression : Expression { }

// FHIRPath expression
public class FhirPathExpression : Expression { }

// Literal value
public class LiteralExpression : Expression { }

// Identifier reference
public class IdentifierExpression : Expression { }

// Qualified identifier (e.g., "Resource.field")
public class QualifiedIdentifierExpression : Expression { }

// Group invocation
public class GroupInvocationExpression : Expression { }

// Transform function call
public class TransformExpression : Expression { }

// ConceptMap reference
public class ConceptMapCodeMapExpression : Expression { }

FHIRPath Integration

The evaluator integrates with FHIRPath for expression evaluation:

var context = new MappingContext(sourceElement, targetElement);

// FHIRPath expressions are evaluated with source element as context
// e.g., "Patient.name.family" extracts family name from Patient
var result = await evaluator.EvaluateAsync(structureMap, context, cancellationToken);

Parsing Note

This package executes pre-compiled StructureMap resources. For parsing FHIR Mapping Language source code into AST, consult the FHIR specification parser documentation.