This
page
is
part
of
the
FHIR
Specification
(v3.0.2:
STU
3).
The
current
version
which
supercedes
this
version
is
5.0.0
.
For
a
full
list
Continuous
Integration
Build
of
available
versions,
see
FHIR
(will
be
incorrect/inconsistent
at
times).
See
the
Directory
of
published
versions
.
Page
versions:
R5
R4B
R4
R3
Responsible
Owner:
FHIR
Infrastructure
Work
Group
|
|
The
FHIR
Specification
includes
a
mapping
language.
The
mapping
language
has
a
concrete
syntax,
defined
and
described
in
this
page,
and
an
abstract
syntax,
which
is
found
in
the
StructureMap
resource
(and
there
is
an
antlr
grammar
for
the
concrete
syntax
).
resource.
See
also
the
Tutorial
.
The mapping language describes how one set of Directed Acyclic Graphs (an instance) is transformed to another set of directed acyclic graphs. It is not necessary for the instances to have formal declarations and/or be strongly typed - just that they have named children that themselves have properties. On the other hand, when the instances are strongly typed - specifically, when they have formal definitions that are represented as Structure Definitions , the mapping language can use additional type related features.
Note that while the mapping language applies to directed acyclic graphs that allow for poly-hierarchies, most of the contexts of use are strict mono-hierarchies (a.k.a trees), including the types defined as part of the FHIR specification.
The mapping language addresses two very different kinds of transformations:
A
map
has
6
7
parts:
The
Mapping
Language
and
the
StructureMap
resource
are
built
on
top
of
FHIRPath
,
and
a
FHIRPath
implementation
is
required
in
order
to
execute
a
StructureMap.
Maps are executed by a mapping engine. This takes one or more inputs of instances (directed acyclic graphs) and a map, and produces a set of outputs as specified by the map. The exact details of the form that the instances take are a matter for the map engine / application API. This language assumes that the engine can query an element in the instance for its children, its primitive value, and (optionally) its type. The language also assumes that the engine has application support for the following operations:
These functions constitute a Mapping Support API that makes maps portable between different systems
Generally, it is assumed the invocation of the engine follows some pattern like this:
Some host applications may be able to determine how to combine maps and inputs on the fly based on their metadata, and require minimal configuration, while others may require manual arrangements in order to manage the map execution process.
Mapping
files
are
always
plain
text
in
unicode.
Unicode.
Whitespace
is
any
unicode
Unicode
whitespace,
and
the
particular
whitespace
used
is
not
significant,
except
that
unicode
Unicode
end
of
line
characters
terminate
a
comment.
Comments
are
started
by
the
characters
"//".
"//"
and
can
be
found
anywhere.
The abstract model includes documentation for each item. The canonical text representation is for each item to be on its own line, with documentation at the end of the line as a comment.
All
names
defined
by
the
map
language
-
group,
rule
and
variable
names
-
must
be
valid
ids
(1-64
characters,
upper
and
lowercase
letters,
numbers,
dashes,
dots
and
underscores),
dashes
and
must
dots).
To
avoid
parsing
ambiguities
however,
they
SHALL
start
with
a
letter.
The
special
boolean
character,
cannot
be
one
of
the
keywords
used
in
the
language
(see
section
Reserved
Keywords
below)
and
cannot
contain
a
dot
or
dash.
These
id
values
'true'
SHALL
NOT
be
surrounded
with
backticks.
The
names
of
context
elements
(
source.context
and
'false'
target.context
)
are
not
allowed
as
variable
names.
constrained
to
simple
names
in
the
same
way
since
they
come
from
the
source
and
target
data
models,
and
these
may
be
surrounded
with
backticks.
src document4 `not-found` `section4.5` `group`
The
media
type
for
the
FHIR
Mapping
language
is
text/fhir-mapping
.
Note
that
in
order
to
conform
to
RFC
6657
,
the
charset=utf-8
parameter
SHALL
be
appended.
The
first
part
of
the
a
mapping
syntax
establishes
file
defines
the
name
of
metadata
about
the
mapping:
map
using
the
metadata
from
the
StructureMap
resource.
Metadata
is
defined
using
the
syntax
///
name{.property}*
=
{value}
where:
"""
and
may
cover
multiple
lines
of
markdown
Examples:
/// url = 'http://hl7.org/fhir/StructureMap/CodeSystem3to4' /// name = 'CodeSystemR3R4' /// title = 'R3 to R4 Conversions for CodeSystem' /// experimental = true /// status = 'active' /// jurisdiction = /// jurisdiction.coding = /// jurisdiction.coding.system = 'urn:iso:std:iso:3166' /// jurisdiction.coding.code = 'AQ' /// description = """ You should use my *awesome* map. It does really cool things. """
todo:
add
additional
metadata?
Values
for
url
and
name
SHALL
be
provided.
If
no
value
is
provided
for
status
,
then
the
status
"draft"
is
assumed.
The next optional section of the map references the set of structure definitions that are used or produced by this map. For example:
uses "[url]" (alias name) as [mode] // documentationuses "http://hl7.org/fhir/3.0/StructureDefinition/CodeSystem" alias CodeSystemR3 as source // documentation uses "http://hl7.org/fhir/StructureDefinition/CodeSystem" as target // documentation
This
optional
section
lists
one
or
more
structure
definitions
that
the
map
makes
use
of,
and
indicates
for
each
structure
definition,
how
it
is
used.
It
may
also
provide
an
Alias
alias
-
a
name
used
for
the
type
inside
the
mapping
language
-
this
may
be
necessary
when
transforming
from
source
to
target
where
both
source
and
target
use
overlapping
type
names
(not
unusual).
If
no
alias
is
given,
the
name
for
the
type
will
default
to
the
name
given
in
the
StructureDefinition
(StructureDefinition.name).
Any
kind
of
structure
definition
may
be
referenced,
including
data
types,
datatypes,
resources,
constraints
on
those,
and
logical
models.
There are 4 modes in which a structure definition may be used:
The simplest case, which is common, is where a single structure is converted to another single structure. in this case, the map specifies one target, and one source. Such maps are easy to use automatically - the host application has content in one format, creates an empty instance of the target, and asks the mapping engine to convert.
However,
many
mappings
are
not
so
simple.
For
instance,
converting
from
a
single
CDA
document
to
FHIR
typically
creates
a
set
of
resources.
In
this
case,
there
is
a
single
target
-
a
Bundle
,
but
it
is
also
useful
to
specify
a
set
of
other
structure
definitions
for
resources
that
may
be
created
as
part
of
the
bundle.
Alternatively
Alternatively,
converting
from
one
source
model
to
another
might
involve
looking
up
other
information
in
other
instances
of
data.
It's
also
possible
for
a
map
not
so
to
specify
any
structure
definition
dependencies.
A
map
that
doesn't
indicate
any
structure
definitions
can
still
be
used,
but
the
type
features
of
the
map
language
can't
be
used,
and
such
maps
typically
require
special
development
to
integrate
the
execution
of
the
map
into
an
application.
This
next
optional
section
references
additional
maps
that
are
used
by
this
map:
map.
For
example:
imports "[url]" // documentationimports "http://hl7.org/fhir/StructureMap/*3to4" // documentation
Typically,
maps
that
are
imported
are
type
based,
such
as
Maps
can
be
broken
up
into
several
files,
each
containing
a
coherent
set
of
groups.
For
example,
when
writing
mappings
for
CDA
-->
FHIR
to
FHIR,
one
might
have
one
file
to
map
that
makes
use
of
a
the
main
document,
and
another
file
containing
the
mappings
for
the
datatypes
(e.g.,
CD
-->
CodeableConcept
map.
to
CodeableConcept).
How
imported
maps
are
actually
used
is
discussed
below.
The
[url]
url
in
the
import
statement
may
contain
a
"*"
"*"
as
a
wildcard
character
(as
shown
above)
to
include
any
matching
maps
that
are
available
to
the
mapping
engine.
The map may define any number of constant values that may be re-used through out the rules that follow. Each constant has the following grammar:
let [name] = [fhirpath expression];
This
defines
a
reusable
variable
that
has
the
same
value
across
all
the
maps.
The
value
of
the
variable
is
a
FHIRPath
expression
terminated
by
the
separator
';'
(for
syntactical
simplicity,
and
so
non-FHIRPath
aware
parsers
can
parse
the
syntax).
Some
rules
that
apply
to
the
constant
declarations:
or
the
mapping
language
let
name
=
'example';
Each
Mapping
source
map
contains
one
or
more
groups
of
groups,
each
optionally
containing
one
or
more
mapping
rules.
Each
group
defines
declares
a
set
of
related
mapping
rules
that
take
the
same
input
and
output
variables,
variables
that
are
shared
by
the
rules.
The
in-
and
output
variables
define
exactly
which
instances
are
passed
to
the
mapping,
and
provides
names
by
which
they
may
be
passed
when
invoking
the
map:
For example:group (for type) [group-name] (extends [other-group]) input [name] : [type] as [mode] // documentationgroup [group-name] (inputs) (extends [other-group]) (<<stereotype>>) { // documentation .. rules .. }
group CodeSystem(source src : CodeSystemR3, target tgt : CodeSystem) extends DomainResource <<type+>>
{
// documentation
.. rules ..
}
Each
group
has
a
name,
which
is
how
the
mapping
is
invoked.
The
first
group
is
special,
in
that
this
is
the
group
invoked
if
no
name
is
provided
(e.g.
(e.g.,
starting
the
mapping
by
a
host
application).
The
inputs
of
a
group
are
also
referred
to
(below)
as
its
input
parameters,
or
just
as
parameters;
or
as
input
variables.
variables,
and
are
a
comma-separated
list
where
each
items
has
the
format:
[mode] [name]( : [type])
Each
input
to
the
group
has
a
name.
This
is
the
name
that
applications
use
when
passing
the
instance
to
the
invocation
engine,
or
that
rules
use
when
invoking
the
group.
Inputs
may
have
a
type
-
and
should
have
(see
the
discussion
above),
but
are
not
required
to.
Input
All
input
variables
also
have
a
mode,
which
may
be
one
of
source
or
target
(see
above).
Inputs
may
have
a
type,
but
are
not
required
to.
There
must
be
at
least
two
input
variables
(source
and
target)
-
else
there's
nothing
to
map.
Maps
map,
except
for
the
special
case
of
the
first
group
that
may
only
have
a
single
input.
Groups
may
have
additional
input
or
output
inputs,
where
that's
necessary.
Groups
may
extend
other
groups,
which
means
that
the
rules
in
the
other
group
also
apply
(typically,
this
is
used
with
specialising
specializing
classes
in
an
OO
context).
When
a
group
extends
another
group,
it
SHALL
have
the
same
input
parameters
(by
mode,
name,
type
and
mode)
type
if
specified)
though
their
order
may
differ,
and
it
MAY
have
additional
parameters.
The
key
word
for
is
used
stereotypes
<<types>>
or
<<type+>>
can
be
added
to
the
end
of
the
group
declaration
to
indicate
that
this
group
provides
a
set
of
mappings
that
are
intended
to
be
used
as
the
default
way
to
map
from
source
to
target.
There
are
2
variants:
for
types
:
Use
this
by
default
when
a
[source]
of
the
specified
type
must
be
converted
to
a
[target]
of
the
specified
type,
and
no
specific
dependent
rules
(see
below)
are
specified.
for
type+types
:
in
addition,
to
the
above
use,
when
a
[source]
of
the
specified
type
must
be
converted
to
a
[target]
and
the
type
of
For
more
information,
see
the
target
is
not
fixed,
use
this
group
section
on
"Default
mapping
groups"
below.
In
both
these
cases,
the
group
Default
mapping
groups
SHALL
have
2
two
parameters,
a
source,
and
a
target,
in
that
order,
and
both
SHALL
have
specified
types
for
the
inputs.
The main portion of a map consists of a set of transform rules that describe how source content is transformed into target content. The full format for a rule looks like this:
For example:name_of_rule: for src_context.field as new_variable where condition make tgt_context.field as new_variable = create([type]) then [details].src_context.field as new_variable where (condition) -> tgt_context.field = create([type]) as new_variable then [details] "name";
src.value : code as vs0 -> tgt.value = create("code") as vt0 then code(vs0, vt0) "valueCode";
Each
rule
has
4
three
main
sections:
parts:
Rules
in
a
group
may
be
applied
in
any
order;
there
is
no
sense
of
sequentially
applying
one
rule
after
another.
7.6.0.7.1
Name
Each
rule
is
may
be
assigned
a
name.
name,
though
this
is
usually
inferred
by
the
parser
and
not
specified
directly.
The
name
is
used
when
specifying
rule
links,
and
in
traces
trace
logs
(a
record
generated
by
the
conversion
engine
recording
the
transform
process).
Names
must
be
unique
within
the
context
of
the
map.
Typically,
the
name
is
trivial
and
can
be
safely
and
usefully
generated
by
the
engine
processing
the
map,
so
this
is
often
left
out.
The three main parts are described in more detail in the following sections.
Rules may be applied in any order. In other words, the order is implementation-defined. Mappings should take care to ensure that either:
first
and
last
keywords
to
help
manage
order
Each
rule
specifies
The
source
content
is
formed
by
one
or
more
elements
taken
from
the
source
that
define
variables
that
statements,
which
can
be
assigned
a
variable
name
and
then
be
used
when
specifying
target
content,
or
re-used
in
subsequent
transforms
on
the
rule.
and
dependent
rules.
Multiple
source
elements
statement
are
separated
by
a
comma,
like
this:
comma:
rule_name: for [source], [source], make ...[source], [source] -> ...
Each [source] contains the following items:
context.element { : type {min..max}} {default [value]} { list-option } as variable where [FHIRPath] check [FHIRPath]context.element {: type} {min..max} {default ([value])} { list-option } as variable where ([FHIRPath]) check ([FHIRPath])
For example:
src.value : integer 0..* default (10) first as vs0
where (value >= 10) check (value <= 100)
log (value)
The
context
is
an
identifier
which
is
either
declared
elsewhere
in
as
a
source
for
the
map
('as
variable'
below,
or
in
the
input
as
a
source
variables)
parameter
or
any
named
variable
within
the
group
in
which
this
rule
is
nested.
The
element
:
An
optional
is
an
(optional)
name
of
a
child
element
of
the
context.
If
this
the
name
is
not
provided,
the
source
is
the
context.
If
this
it
is
provided,
the
rule
will
apply
once
for
each
element
on
the
context
that
matches
this
name.
If
the
element
name
contains
spaces
(possible
in
some
contexts),
it
can
be
quoted
using
"
If
all
the
there
are
multiple
source
elements
have
a
match
statements,
the
rule
applies
for
the
permutation
of
the
source
elements
(e.g.
from
each
source
statement.
e.g.,
if
there
are
2
elements,
source
statements,
each
with
2
matches,
matching
elements,
the
rule
applies
4
times,
one
for
each
combination).
combination.
Typically,
if
there
is
more
than
one
source
element,
statement,
only
one
of
the
elements
can
would
repeat.
If
any
of
the
source
data
elements
have
no
value,
then
the
rule
never
applies;
only
existing
permutations
are
executed:
for
multiple
source
statements,
all
of
them
need
to
match.
Once
The
where
,
check
and
log
statements
are
executed
in
order;
where
first
of
all
filters
the
full
source
list,
then
check
checks
that
what
passed
the
filter
meets
the
author's
expectations,
and
finally
log
writes
what
has
passed
the
checks
to
the
application
log.
Note
that
the
aliases
are
mapped
prior
to
running
these
FHIRPath
statements,
so
that
the
individual
items
being
transformed
can
be
tested
or
logged
correctly.
Example
Given this mapping statement:
for src.row as row, row.firstName as firstName
applied to this source:
"row" : [{
"firstName" : "John"
},{
"firstName" : "Peter"
}]
Will result in the the rule firing 4 times: row #1 & "John", row #2 & "Peter", row #2 & "John", and row #1 & "Peter". This somewhat contrived example shows how the iteration works; it's unlikely that this combination of source statements would be useful. The same mapping statement with this data:
"row" : [{
"family" : "John"
},{
"family" : "Peter"
}]
Because there's no firstName values, the rule will never fire.
Once
the
source
content
is
evaluated,
the
engine
performing
the
evaluation
has
a
list
of
variables,
elements
assigned
to
variables.
For
each
time
the
rule
is
applied,
each
of
which
the
variables
contains
a
single
value
for
each
named
variable.
value.
These
variables
are
now
mapped
into
the
target
structures
in
the
target
transformation.
To avoid potential parsing ambiguities, all embedded FHIRPath expressions within the mapping language (where conditions, check conditions, log statements, default values) MUST be surrounded by a set of parentheses: "([FHIRPath])".
Each source can include a log statement:
log ([expression])
Where expression is a FHIRPath statement. e.g.,
log ('not handled yet')
Puts a plain string in the log file. Alternatively, the log statement can contain FHIRPath:
log (src.field)
Log statements are often used to note that some particular source element is not yet mapped.
Note
that
the
log
statement
is
equivalent
to
the
trace()
function
in
FHIRPath
and
the
output
usually
ends
up
in
the
same
place.
Each
rule
specifies
zero
or
more
elements
target
transformation
statements,
which
specify
how
source
content
is
used
to
be
created
in
the
create
target
structure.
content.
These
targets
target
statements
can
also
be
assigned
to
variables
that
can
be
used
in
subsequent
transform
rules.
If
no
targets
are
specified,
specified
(no
->),
no
transformation
is
done
and
there
are
not
no
created
targets,
just
newly
defined
source
variables.
variables,
which
can
then
be
used
in
subsequent
dependent
rules.
Multiple
target
elements
statements
are
separated
by
a
comma,
like
this:
... make [target], [target] then by...... -> [target], [target] then...
Each [target] contains the following items:
make context.element = transform_code(parameters...) as variable {list_modes}context.element = transform_code(parameters...) as variable {list_modes}
For example:
context.element = copy(parameter, ...) as vt1 first
The
context
is
an
identifier
which
is
either
declared
elsewhere
in
as
a
target
for
the
map
('as
variable'
below,
map,
a
target
parameter
or
in
any
named
variable
within
the
input
target
variables)
element
:
group
(including
the
variables
from
the
source
content)
in
which
this
rule
is
nested.
The element is the name of a child element that is valid in the context. The created value will be placed into the named element
The
element
may
be
further
qualified
by
a
subElement
(recursively
to
any
further
depth).
src.c.p
as
p
...
is
semantically
equivalent
to
src.c
as
t
then
{
t.p
as
p
...
}
though
t
is
never
made
explicit
in
the
case
of
subElements
and
cannot
be
referred
to
Context
and
Element
are
optional
as
Transform
statements
may
just
contain
an
invocation
of
a
pair.
If
no
context/element
is
specified,
then
transform
function.
In
this
case,
a
variable
must
be
defined,
and
the
created
value
is
only
available
in
the
variable.
variable
for
use
in
subsequent
transformations.
Each
time
the
rule
is
applied,
the
engine
determines
the
value
from
the
transforms,
considers
the
list
mode,
if
required,
required
and
creates
that
specified
content
in
the
target
instance.
Within
a
given
transform
url,
target
transform,
the
targets
target
statements
are
processed
in
order,
so
that
a
transform
rule
statement
may
refer
to
a
variable
defined
by
a
prior
transform
rule.
statement.
The following list specifies that transforms that can be specified. Each transform takes one or more parameters:
| Name |
|
Documentation |
|
| create | type | use the standard API to create a new instance of data. Where structure definitions have been provided, the type parameter must be a string which is a known type of a root element. Where they haven't, the application must know the name somehow | n/a |
| copy | source | simply copy the source to the target as is (only allowed when the types in source and target match- typically for primitive types). In the concrete syntax, this is simply represented as the source variable, e.g., src.a = tgt.b | n/a |
| truncate | source, length | source must be some stringy type that has some meaningful length property |
substring
|
| escape | source, format1, format2 | Change the internal escaping of a string element. Note: this is not often needed, as mostly the escaping is done on the base format | n/a |
| cast | source, type? |
cast
source
from
one
type
to
another.
target
type
can
be
left
as
implicit
if
there
is
one
and
only
one
target
type
)
| n/a |
| append | source... | source is element or string - just append them all together |
&
(String
concatenation)
|
| translate | source, map_uri, output | use the translate operation . The source is some type of code or coded datatype, and the source and map_uri are passed to the translate operation. The output determines what value from the translate operation is used for the result of the operation (code, system, display, Coding, or CodeableConcept) | %terminologies.translate() |
| reference | source | return a string that references the provided tree properly | n/a |
|
|
|
| n/a |
| unixToDateTime | source, time-zone offset? |
Convert
a
Unix-offset
(ticks)
into
a
date-time
object,
applying
the
specified
time-zone
information
(not
present
will
convert
to
UTC).
Note that if a different source epoch is required, this can be achieved by adding or subtracting the difference in ticks prior to calling this transform. | n/a |
| toDate | source, format string |
Parse
a
string
into
a
date
| n/a |
| unixToDate | source, time-zone offset? |
Convert
a
Unix-offset
(ticks)
into
a
date
object,
applying
the
specified
time-zone
information
(not
present
will
convert
to
UTC).
Note that if a different source epoch is required, this can be | n/a |
| toTime | source, format string | Parse a string into a time object, see Date Time Transformation Details for format information. | n/a |
| unixToTime | source, time-zone offset? |
Convert
a
Unix-offset
(ticks)
into
a
time
object,
applying
the
specified
time-zone
information
(not
present
will
convert
to
UTC).
Note that if a different source epoch is required, this can be achieved by adding or subtracting the difference in ticks prior to calling this transform. | n/a |
| uuid | n/a | Generate a random UUID (in lowercase). No Parameters | n/a |
| pointer | resource | Return the appropriate string to put in a Reference that refers to the resource provided as a parameter | related to resolve() |
| translate | (varies) | translate(source, uri_of_map) - use the translate operation | n/a |
| evaluate | resource |
Execute
the
supplied
FHIRPath
expression
and
use
the
value
returned
by
that.
The
2nd
parameter
-
FHIRPath
expression
-
is
evaluated
in
the
context
of
the
first
parameter,
and
the
result
used
as
the
value.
If
the
outcome
of
the
evaluation
of
the
FHIRPath
expression
is
an
empty
collection,
no
element
is
created
in
the
target.
If
the
outcome
has
a
single
value,
the
target
is
created
with
that
value.
If
the
outcome
has
more
than
one
value,
and
the
element
is
repeating,
a
separate
target
instance
will
be
created
for
each
value.
If
there
is
more
than
one
value
and
the
element
is
non-repeating
this
is
treated
as
an
error.
In the concrete syntax, there is a short hand for this operation, by supplying () around the parameter. In this case, there is no explicit context for the FHIRPath expression, and | n/a |
| cc | (text) or (system. Code[, display]) | Create a CodeableConcept from the parameters provided | %factory.CodeableConcept() "> |
| c | system. Code[, display] | Create a Coding from the parameters provided | %factory.Coding() "> |
| qty | (text) or (value, unit, [system, code]) |
Create
a
quantity.
Parameters
=
(text)
or
(value,
unit,
[system,
code])
where
text
=s
the
natural
|
%factory.Quantity() "> |
| id | system, value[, type] | Create an identifier. where type is a code from the identifier type value set | %factory.Identifier() "> |
| cp | (value) or (system, value) |
Create
a
contact
|
%factory.ContactPoint() "> |
TODO: explain how optional parameters work with transforms (append only?), document list mode
Parsing textual content into date/time values is a complex task, given the wide variety of formats in use in the real world. The date and time translations provide a way to parse a wide variety of date/time formats into FHIR date/time types. Unfortunately, there is no single standard for date/time formats across the contexts where FHIR is used (e.g., most programming languages have their own date/time formats), so the this specification defines the following format codes below.
Note that:
| Format Code | Support | Description |
|---|---|---|
yy
| optional |
2-digit
year
(e.g.,
80
for
1980)
Implementations have discretion on how to interpret the century for 2-digit years (e.g., based on contextual knowledge). A common approach is to interpret values 00-49 as 2000-2049 and 50-99 as 1950-1999. Note that this format code is discouraged due to the ambiguity it introduces. |
yyyy
| required | 4-digit year (e.g., 2024) |
M
| optional | 1- or 2-digit month of year (1=January, etc.) |
MM
| required | 2-digit month of year (01=January, etc.) |
MMM
| optional | The localized abbreviated name of the month (e.g., 'Jun' for en-US, 'juin' for fr-FR) |
MMMM
| optional | The localized full name of the month (e.g., 'June' for en-US, 'juni' for da-DK) |
d
| optional | 1- or 2-digit day of month (1 through 31) |
dd
| required | 2-digit day of month (01 through 31) |
h
| optional | 1- or 2-digit hour of AM/PM (1 through 12) |
hh
| required | 2-digit hour of AM/PM (01 through 12) |
H
| optional | 1- or 2-digit hour of day (00 through 23) |
HH
| required | 2-digit hour of day (00 through 23) |
m
| optional | 1- or 2-digit minute of hour (0 through 59) |
mm
| required | 2-digit minute of hour (00 through 59) |
s
| optional | 1- or 2-digit second of minute (0 through 59) |
ss
| required | 2-digit second of minute (00 through 59) |
S[+]
| required |
1-digit
fraction
of
second
(0
through
9)
Note that consecutive fractional seconds are grouped together, e.g.
SSS
for
milliseconds.
Implementations MUST support at least 3 digits (milliseconds); support for additional digits is optional. |
a
| required |
1-
or
2-letter
localized
AM/PM
specifier.
e.g., en-US:
A
,
AM
,
P
,
etc.
e.g., ja-JP:
午
,
午前
,
etc.
|
z
| optional |
Time
zone
literal
(name
or
id).
E.g.,
America/Los_Angeles
,
Pacific
Standard
Time
,
or
PST
. |
Z
| required |
Time
zone
offset
from
UTC
(e.g.,
+0200
,
-0500
)
or
Z
literal
for
UTC
|
The underlying type systems for source and target MAY define required implicit conversions, especially around how primitive values are handled and represented as strings (often required implicitly when executing the mapping rules).
As
an
example,
see
the
FHIRPath
specification
implicit
type
conversions
,
which
applies
to
source
and/or
target
if
they
are
resources
(or
content
described
by
FHIR
logical
models).
In some cases, the transform statements will cause the automatic creation of objects in the target content. If the target model describes a choice of types for the automatically constructed object, then the engine raises an error. In such cases, an explicit create should be used:
tgt.aa = create("x") as t_aa...
Once
the
source
elements
are
evaluated,
and
any
specifed
specified
targets
created,
the
engine
has
a
set
of
variables
that
represent
source
and
target
contexts
in
which
further
mapping
may
occur.
The
set
of
variables
includes
those
provided
to
the
group
that
contains
the
rule,
and
those
created
by
the
application
of
the
rule.
For
some
created
elements
that
are
primitive
types,
that's
the
end
of
the
road
-
there's
nothing
more
to
do
with
them.
But
if
either
or
both
the
source
and
target
types
are
complex,
there
are
usually
additional
mapping
rules
that
need
to
apply
to
the
newly
created
variables.
Transform
Dependent
rules
specify
what
additional
rules
are
evaluated
when
the
rule
is
complete,
by
containing
other
rules:,
complete:
.. then {
.. other rules...
}
When
a
rule
contains
other
rules,
the
variables
from
the
containing
rules
are
all
available
to
the
contained
rules.
Alternatively,
a
rule
can
nominating
another
group
nominate
other
groups
of
rules
from
the
same
or
an
imported
mapping.
Each
rule
or
group
is
listed
by
name,
and
then
a
set
of
parameters
are
provided.
.. then rule(param, param).. then group(param, param)
The
parameters
provided
must
match
the
parameters
required
by
the
dependenct
rule,
dependent
group,
in
order.
In
addition,
the
mode
of
the
variable
must
match
-
inputs
that
are
targets
must
be
target
variables.
Note,
though,
that
target
variables
can
be
treated
as
source
for
a
group.
Multiple groups may be specified, each separated by a comma. The last group invocation of the rule may be followed by a set of dependent rules. Dependent rules are evaluated after all nominated groups have been invoked.
Groups
are
resolved
by
name
by
looking
through
all
the
groups
in
all
the
available
maps
referened
referenced
by
the
uses
(see
above)
statements.
The
name
must
be
unique
within
the
scope
of
these
maps.
If
no
dependent
rules
are
specified,
and
if
the
is
only
one
source
and
target,
and
they
both
speecify
specify
a
variable,
the
rule
can
be
written
in
an
abbreviated
form:
"name" : for src.element make tgt.elementsrc.element -> tgt.element;
This is implicitly the same as
"name" : for src.element as vvs make create([type]) tgt.element as vvt then [typeGroup](vvs, vvt)src.element as vvs -> tgt.element = create('type') as vvt then defaultMappingGroup(vvs, vvt)
Where
the
name
of
the
type
given
as
a
parameter
to
'create'
and
typeGroup
the
group
invoked
by
the
'then'
are
determined
by
the
context
of
src.element
and
tgt.element:
typeGroup
is
determined
by
looking
through
tgt.element
and
the
available
rule
groups
labeled
selected
default
mapping
group,
as
"for
types"
documented
in
the
next
section.
Note
that
default
mapping
groups
are
only
invoked
when
no
dependent
rules
or
"for
type+types"
and
checking
explicit
group
invocations
are
specified.
This
simple
form
is
sometimes
known
as
the
identity
transform,
though
strictly,
the
types
of
their
inputs
looking
for
the
source
and
the
target
may
be
different
(e.g.,
different
FHIR
versions),
but
have
the
same
properties
and
value
domains.
The
simple
transform
(copy
all
properties
as
is
recursively
following
the
types)
is
sufficiently
common
that
there's
an
even
shorter
form
defined:
src -> tgt: type, subtype, action, recorded;
This
syntax
is
allowed
as
the
first
entry
in
the
rules
section,
and
is
a
match
purely
syntactic
short-cut
for
the
longer
form:
src.type -> tgt.type; src.subtype -> tgt.subtype; src.action -> tgt.action; src.recorded -> tgt.recorded;
The
primary
attraction
of
this
shorter
form
is
that
it
allows
the
reader
to
focus
on
the
type
parts
of
src.element,
and
[type]
the
transform
that
involve
change,
which
is
attractive
in
version
to
version
changes
where
there
is
changes
on
only
a
few
elements.
It is not necessary to explicitly invoke groups for each mapping. Instead groups can be declared to be the "default" mapping for a given source and target type. Groups acting as defaults have either <<types>> or <<type+>> in their declaration.
Groups
marked
with
type
types
is
determined
are
used
by
default
when
the
engine
encounters
a
mapping
with
a
source
and
target
type
where
the
types
match
the
source
and
target
type
of
tgt.element.
If
tgt.element
the
group.
Of
course,
there
can
have
more
than
be
only
one
type,
then
the
such
group
for
each
combination
of
source
and
target
type
is
inferred
by
looking
through
for
the
available
engine
to
unambiguously
determine
which
default
group
to
invoke.
In
addition
to
the
above
use,
groups
labeled
"for
type+types"
for
may
be
marked
with
type+
.
They
will
act
like
a
match
default
mapping
group,
just
like
type+
group
will
be
used
as
the
default
as
long
as
the
source
type
of
src.element
the
instance
to
map
matches
the
source
type
of
the
group.
Even
so,
the
target
will
then
always
be
taken
to
be
the
target
type
of
the
group.
todo
The
formal
grammar
for
the
mapping
language,
specified
using
ANTLR,
can
be
found
here
.
Note
that
this
grammar
uses
FHIRPath
as
an
embedded
syntax.
Full
details
on
FHIRPath
and
its
grammar
can
be
found
here
.
todo
This is the list of reserved keywords, which cannot be used as identifiers and names for variables, unless escaped.
map uses as alias imports group extends default where check log then true false types type first not_first last not_last only_one share single source target queried produced conceptMap prefix