Every IFC schema (IFC2x3, IFC4, IFC4.3) is written entirely in EXPRESS, the data modeling language standardized as ISO 10303-11:2004. EXPRESS is declarative : it describes what a valid population of data looks like, never behaviour or algorithms. This skill teaches how to read an EXPRESS declaration and how it maps to a serialized IFC instance. The EXPRESS schema is the single source of truth : the STEP physical file, ifcXML, and ifcJSON are all derived encodings of the same EXPRESS model.
Quick Reference
The three attribute kinds : the most important table
| Kind | Stored? | Serialized in the STEP file? | What it is |
|---|---|---|---|
| Explicit | Yes | Yes : a positional value | An independently stored value, supplied in the file |
| DERIVE | No | No : slot holds * |
A value computed by an expression (:=) |
| INVERSE | No | No : occupies no slot at all | A navigable back-reference, reconstructed by the reader |
ALWAYS count only explicit attributes (across the full inheritance chain) when reading or writing a STEP instance. NEVER give a DERIVE or INVERSE attribute a value.
EXPRESS construct cheat-sheet
| Construct | Declares | Example |
|---|---|---|
TYPE name = base; END_TYPE; |
A defined type (a named, optionally constrained base type) | TYPE IfcLengthMeasure = REAL; END_TYPE; |
TYPE name = ENUMERATION OF (...); END_TYPE; |
A fixed list of named values | IfcWallTypeEnum |
TYPE name = SELECT (...); END_TYPE; |
A type union (one-of alternatives) | IfcUnit |
ENTITY name ... END_ENTITY; |
An entity type with attributes and inheritance | IfcWall |
RULE name FOR (...); ... END_RULE; |
A schema-level population constraint | global rules |
FUNCTION name(...) : T; ... END_FUNCTION; |
A computation used by DERIVE / WHERE | IfcBaseAxis |
STEP physical file markers (the EXPRESS-to-file mapping)
| Marker in the file | EXPRESS meaning |
|---|---|
#42=IFCWALL(...) |
An instance ; keyword upper-case, #id file-local |
$ |
An unset OPTIONAL explicit attribute |
* |
A DERIVE (or re-declared) attribute slot ; computed, not stored |
| (absent) | An INVERSE attribute : no slot exists in the parentheses |
.STANDARD. .T. .F. .U. |
An enumeration, BOOLEAN, or LOGICAL value (dotted) |
IFCLENGTHMEASURE(2.5) |
A SELECT-of-defined-type value (wrapped in the type name) |
#84 |
A SELECT-of-entity value (a bare reference, no wrapper) |
(0.,0.,0.) |
Any aggregate (LIST / SET / ARRAY / BAG : the wire syntax is the same) |
The four aggregations
| Aggregation | Ordered | Duplicates | Bounds | Notes |
|---|---|---|---|---|
LIST [lo:hi] OF T |
Yes | Allowed (unless OF UNIQUE) |
Optional, default [0:?] |
Indexable |
SET [lo:hi] OF T |
No | Never | Optional | Set semantics |
ARRAY [lo:hi] OF T |
Yes | Allowed (unless UNIQUE) |
Mandatory | Only one that allows OPTIONAL holes |
BAG [lo:hi] OF T |
No | Allowed | Optional | Unordered multiset |
? as the high bound means unbounded. LIST OF UNIQUE differs from SET only in that
it is ordered.
The three equality tokens (NEVER confuse these)
=: value equality (deep, structural comparison).:=:: instance equality (identity : same#id).:=: assignment ; used ONLY to give a DERIVE attribute its expression. It is not a comparison operator.
Decision Trees
Which attribute kind is this, and does it go in the file?
Where is the attribute declared in the ENTITY body?
|
+-- In the main attribute block (before DERIVE/INVERSE/WHERE)
| --> EXPLICIT attribute. Serialized as a positional value.
| If marked OPTIONAL and unset --> written as $
|
+-- Under the DERIVE keyword (has := and an expression)
| --> DERIVE attribute. NEVER serialized as a value ; slot is *
|
+-- Under the INVERSE keyword (has a FOR clause)
--> INVERSE attribute. NEVER serialized ; no slot exists at all.
Which TYPE construct is this?
TYPE name = ... END_TYPE; what follows the "=" ?
|
+-- A base type / another defined type (REAL, INTEGER, IfcLengthMeasure, ...)
| --> Defined type. A named alias, optionally narrowed by a WHERE rule.
|
+-- ENUMERATION OF (V1, V2, ..., USERDEFINED, NOTDEFINED)
| --> Enumeration. A fixed list of dotted values.
|
+-- SELECT (A, B, C)
--> Select (type union). An attribute typed by it holds ONE of A, B, C.
This is NOT inheritance : the alternatives need not share a supertype.
ONEOF vs ANDOR (subtype constraint)
SUPERTYPE OF (...) contains which operator?
|
+-- ONEOF (A, B, C) --> a concrete instance is EXACTLY ONE of A, B, or C.
| Mutually exclusive. The overwhelmingly common IFC case.
|
+-- A ANDOR B --> an instance may be A alone, B alone, OR A and B together.
Multiple inheritance. IFC uses ANDOR rarely.
Can I instantiate this entity?
Does the ENTITY declaration say ABSTRACT SUPERTYPE?
|
+-- YES --> NEVER instantiate it. IfcRoot, IfcProduct, IfcElement,
| IfcObjectDefinition exist only as supertypes. No #id=IFCELEMENT(...).
|
+-- NO --> It is concrete and instantiable (IfcWall, IfcDoor, IfcCartesianPoint).
A concrete entity may still be a SUPERTYPE OF other entities.
Patterns
Pattern : Read an ENTITY declaration top to bottom
An ENTITY ... END_ENTITY; block has a fixed order of sections :
ENTITY IfcRoot
ABSTRACT SUPERTYPE OF (ONEOF
(IfcObjectDefinition, IfcPropertyDefinition, IfcRelationship));
GlobalId : IfcGloballyUniqueId;
OwnerHistory : OPTIONAL IfcOwnerHistory;
Name : OPTIONAL IfcLabel;
Description : OPTIONAL IfcText;
UNIQUE
UR1 : GlobalId;
END_ENTITY;
ALWAYS read in this order :
ABSTRACT(if present) : the entity cannot be instantiated.SUPERTYPE OF (...): its direct subtypes, withONEOForANDOR.SUBTYPE OF (...): its direct supertype(s). Absent on a root entity.- The explicit attribute block : independently stored values, in declared order.
DERIVE(if present) : computed attributes.INVERSE(if present) : back-references.WHERE(if present) : per-instance rules.UNIQUE(if present) : per-population uniqueness rules.
A subtype inherits every attribute of every supertype. A serialized IfcWall (chain
IfcRoot to IfcObjectDefinition to IfcObject to IfcProduct to IfcElement to
IfcBuiltElement to IfcWall) carries every explicit attribute of all seven levels, in
supertype-first order.
IfcBuiltElement is the IFC4.3 name. In IFC2x3 and IFC4 the equivalent supertype is
IfcBuildingElement ; IFC4.3 renamed IfcBuildingElement to IfcBuiltElement. See
ifc-core-entity-hierarchy.
Pattern : Treat the three attribute kinds correctly
ALWAYS check which keyword block an attribute sits under before reasoning about a file.
- Explicit attributes are the only ones that appear as positional values. The number of values inside the parentheses MUST equal the count of explicit attributes across the full inheritance chain.
- DERIVE attributes (introduced with
:=and an expression, for exampleIfcDirection.Dim := HIINDEX(DirectionRatios);) are recomputed by every reader. Their positional slot holds*, never a value. - INVERSE attributes (which always have a
FORclause, for exampleIfcProduct.ReferencedBy : SET [0:?] OF IfcRelAssignsToProduct FOR RelatingProduct) occupy no slot at all. The reader rebuilds them by indexing forward#idreferences. This is the foundation of the IFC objectified-relationship pattern.
Pattern : Read the INVERSE FOR clause
ReferencedBy : SET [0:?] OF IfcRelAssignsToProduct FOR RelatingProduct reads :
"the set of every IfcRelAssignsToProduct instance whose RelatingProduct explicit
attribute points at this instance." The FOR names the explicit attribute on the other
entity that this INVERSE mirrors. The cardinality (SET [0:?], SET [0:1], ...)
constrains how many back-links may exist. See ifc-core-relationships.
Pattern : Apply the WHERE / UNIQUE / RULE scope correctly
The three constraint mechanisms differ in scope :
- A WHERE rule constrains one instance. A named boolean expression that MUST
evaluate TRUE for every instance. On a defined type,
SELFis the value (IfcPositiveLengthMeasure.WR1 : SELF > 0.;) ; on an entity,SELFis the instance. - A UNIQUE rule constrains across the whole population of one entity type.
IfcRoot.UR1 : GlobalId;forbids twoIfcRootinstances from sharing aGlobalId. A UNIQUE rule may list several attributes for a compound key. - A global RULE constrains populations across entity types. It is declared at schema level, not on any entity, and can range over an entire population. An entity WHERE rule cannot see other instances ; a global RULE can.
NEVER read a WHERE rule, RULE, or function as application behaviour. They are constraints and computations, never algorithms with side effects.
Pattern : Read the SELF backslash supertype path
Inside a WHERE rule or DERIVE expression, SELF\Supertype.Attribute names an attribute
inherited from a supertype. The backslash \ is the supertype-cast operator : it
narrows the view of SELF to a named supertype.
DimIs3D : SELF\IfcCartesianTransformationOperator.Dim = 3; reads "this instance,
viewed as its supertype IfcCartesianTransformationOperator, its Dim attribute." The
qualifier is required because EXPRESS allows an attribute name to be re-declared in a
subtype. ALWAYS expect SELF\... whenever a rule reaches up the inheritance chain.
Pattern : Read the built-in functions in WHERE rules
The functions that actually appear in IFC WHERE rules :
EXISTS(v): TRUE ifvis set. The standard guard for OPTIONAL attributes.SIZEOF(agg): element count of an aggregate.TYPEOF(v): the set of type-name strings ofv; used withIN, for example'IFC4X3.IFCWALL' IN TYPEOF(x). The type-name string is schema-qualified, upper-case.HIINDEX(agg)/LOINDEX(agg): the actual high / low index of a populated aggregate. Distinct fromHIBOUND/LOBOUND, which return the declared bounds.QUERY(x <* agg | condition): iterate-and-filter.<*bindsxto each element ; returns the elements where the filter is TRUE. Almost always wrapped inSIZEOF(...).NVL(v, default): returnsvif set, otherwisedefault.USEDIN(v, 'Schema.Entity.Attribute'): the instances referencingvthrough that role. The functional counterpart of an INVERSE attribute.
See references/methods.md for the full ISO 10303-11 function library.
Pattern : Honour the USERDEFINED / NOTDEFINED enumeration convention
Every IFC predefined-type enumeration ends with USERDEFINED and NOTDEFINED. When an
instance's PredefinedType is .USERDEFINED., the paired free-text attribute (usually
ObjectType, inherited from IfcObject) MUST carry the actual type name. This pairing
is enforced by a WHERE rule on the entity. ALWAYS set the paired attribute when
using USERDEFINED. See ifc-syntax-data-types.
Reference Links
references/methods.md: the full EXPRESS construct reference : TYPE / ENUMERATION / SELECT / ENTITY grammar, the three attribute kinds, WHERE / UNIQUE / RULE, the four aggregations with BNF, the built-in function library, operators, and the complete EXPRESS-to-STEP mapping rules.references/examples.md: verbatim, source-verified EXPRESS snippets from IFC4.3 and IFC4 entity pages, each explained, plus the matching STEP serialization.references/anti-patterns.md: the twelve common EXPRESS misreadings, each with the reason it corrupts a file or a reading.
Official sources
- ISO 10303-11:2004 (EXPRESS Language Reference Manual) : https://www.iso.org/standard/38047.html
- IFC4.3 schema documentation : https://ifc43-docs.standards.buildingsmart.org/
- IFC4 ADD2 TC1 schema : https://standards.buildingsmart.org/IFC/RELEASE/IFC4/ADD2_TC1/HTML/
- IFC2x3 TC1 schema : https://standards.buildingsmart.org/IFC/RELEASE/IFC2x3/TC1/HTML/
Related skills
ifc-syntax-data-types: the IFC resource-layer value-type system built on EXPRESS defined types, selects, and enumerations.ifc-core-data-model: the four-layer schema architecture written in EXPRESS.ifc-syntax-step-physical-file: the STEP physical file (ISO 10303-21) encoding.ifc-core-entity-hierarchy: the IFC inheritance lattice and theIfcBuildingElementtoIfcBuiltElementrename.ifc-core-relationships: the objectified-relationship pattern built on INVERSE.