Skip to content

ArchiMate Converter

Converts ArchiMate Model Exchange XML (Open Group standard) to RDF.

Ontology

Types align to the published ArchiMate 3.2 Ontology (am: prefix).

Type derivation is automatic from xsi:type — no configuration needed:

  • xsi:type="BusinessActor" → am:BusinessActor
  • xsi:type="ServingRelationship" → am:Serving (suffix stripped)

Usage

# TriG output (named graphs preserved)
java -jar archimate2linkedarchi-all.jar convert \
  --input model.xml \
  --output model.trig \
  --base https://example.org/la/ \
  --model-id demo \
  --format trig

# Turtle output (flat)
java -jar archimate2linkedarchi-all.jar convert \
  --input model.xml \
  --output model.ttl \
  --base https://example.org/la/ \
  --model-id demo \
  --format ttl

# With direct relationship triples and a type mapping. Views are emitted by default.
java -jar archimate2linkedarchi-all.jar convert \
  --input model.xml \
  --output model.trig \
  --base https://example.org/la/ \
  --model-id demo \
  --format trig \
  --emit-direct-rel-triples \
  --type-mapping config/type-mapping-archimate.yml

# The model without its diagrams — elements, relationships, folders and provenance only
java -jar archimate2linkedarchi-all.jar convert \
  --input model.xml \
  --output model-only.ttl \
  --base https://example.org/la/ \
  --model-id demo \
  --format ttl \
  --no-include-views

CLI options

Option Default Description
--input, -i required ArchiMate Exchange XML file
--output, -o required Output artifact, path[:FORMAT[:PROFILE]]. Repeatable — several artifacts are written from one conversion, which is faster than re-running the converter and is what makes them share one prov:generatedAtTime. PROFILE is full (default), no-geometry, no-views or no-diagrams; see output serialization
--base required Base IRI for minting resource IRIs
--model-id filename Model identifier in minted IRIs. There is no diagram index here — one file is one whole model — so this or the filename is the only source, and neither is validated. Pass a slug explicitly for anything published; see where a model ID comes from
--format inferred Default format for any --output that names none: TRIG / TURTLE / JSONLD / RDFXML / NTRIPLES / NQUADS. A file extension such as ttl is also understood
--ns-core https://meta.linked.archi/core# Core namespace
--ns-archimate https://meta.linked.archi/archimate3/onto# ArchiMate namespace
--ns-core-vis https://meta.linked.archi/core-vis# Core-vis namespace
--type-mapping none YAML type/predicate overrides
--include-views true Emit view/diagram content. --no-include-views drops the views entirely — no arch:View, not merely no geometry
--skip-visual-triples false Keep the views and their nodes but omit geometry (bounds, points) and styles. The narrower cut: use this when a consumer needs to know what is drawn on which diagram but not where
--skip-no-element-ref false With views enabled, skip view nodes that reference no element (pure layout nodes such as labels and group frames)
--emit-direct-rel-triples false Emit {src} {pred} {tgt} shortcuts, each bridged back to its relationship with rdf:reifies
--emit-qualified-rel-triples — Deprecated and ignored. {src} {qualPred} {relNode} is now always emitted, as it is by every other converter. Still accepted so existing command lines keep working
--emit-core-triples true Emit arch:Element / arch:QualifiedRelationship and arch:source / arch:target. Also gates the qualified predicate, whose fallback arch:hasQualifiedRelationship has domain arch:ModelConcept
--strict-type-mapping false Fail on unmapped types
--skip-unmapped false Skip unmapped elements
--validate-refs true Validate relationship endpoints
--pretty-print false Human-readable output
--label-language en BCP-47 tag applied to skos:prefLabel / skos:definition when the source <name>/<documentation> has no xml:lang. An explicit xml:lang in the Exchange XML always wins

IRI path segments

The minted IRIs follow {base}{pathModel}/{modelId}/{pathX}/{id}. Each segment is configurable, and an empty string omits it.

Option Default Segment for
--path-model model The model resource
--path-element element Element resources
--path-relationship relationship Relationship resources
--path-view view View resources

Property and cross-model namespaces

Option Default Description
--ns-vocab none Base IRI for colon-prefixed property keys. With it set, a property named :leanixUrl becomes a direct vocab:leanixUrl predicate instead of a blank-node ext:PropertyValue. Also resolves a bare @type value
--ns-global-id none Base IRI of a cross-model graph. A property keyed @id is then emitted as owl:sameAs <nsGlobalId><value>, linking the element to its canonical IRI across notations
--archi-base-url none Base URL of a published Archi HTML report. Emits vocab:archiUrl linking each resource to its page: views to {base}index.html?view={id}, elements and relationships to {base}{xmlModelId}/elements/{id}.html

How each property key is emitted

An element, relationship or view property takes exactly one of these routes, decided by its key:

Key Emitted as Object Requires When the requirement is absent
@id owl:sameAs <nsGlobalId + value> IRI --ns-global-id schema:additionalProperty pair
@type an additional rdf:type IRI a resolvable value — see below schema:additionalProperty pair
prefix:local <namespace(prefix)>local literal prefix under namespaces: in --type-mapping schema:additionalProperty pair
:local vocab:local literal --ns-vocab schema:additionalProperty pair
anything else schema:additionalProperty pair literal — —

A value in the schema:additionalProperty form is a blank node carrying schema:name and schema:value, so the key and value both survive but are not queryable as a predicate. No property is dropped, whichever route it takes.

By default a promoted property carries a literal, which is right for a cost centre and wrong for anything that names another resource. A value that looks like a reference is still a string:

# arch:architectureState = arch:Target
arch:architectureState "arch:Target" .

That violates arch:architectureState's rdfs:range arch:ArchitectureState, and it loses the IRI join, so no query can follow it into the state vocabulary.

Declare the key under object-properties: in --type-mapping and the value is resolved to an IRI instead:

namespaces:
  arch: https://meta.linked.archi/core#

object-properties:
  - arch:architectureState
<…/relationship/id-rel> a arch:QualifiedRelationship, arch:ModelConcept, am:Realization ;
    arch:source <…/element/id-a> ;
    arch:target <…/element/id-b> ;
    arch:architectureState arch:Target .          # an IRI, not "arch:Target"

This is what lets an ArchiMate model populate a published owl:ObjectProperty — arch:architectureState, arch:approvalState, ap:atLifecycleStage — instead of forking the term into a local datatype property. It works on elements, relationships and views alike; core permits it on a relationship, since arch:architectureState declares only a range and a converted relationship is an arch:ModelConcept.

This is ArchiMate's only route to architecture state

The other notations declare it as a checked field in a diagram index, where a typo fails the run. ArchiMate has no index, and the converter promotes no property on the model, so here the value is unchecked and model level is not reachable at all. See Architecture state.

The value resolves the same three ways @type does:

Value Resolves to
https://… itself
prefix:local namespaces[prefix], falling back to --ns-vocab
local --ns-vocab

A declared prefix beats the --ns-vocab fallback, because the author's own declaration is better evidence than a default.

A value that resolves to none of those emits no link. It is kept as a schema:additionalProperty pair and reported — never emitted as a literal on the predicate, which would satisfy the shape of the triple and contradict the property's range:

[WARN] 1 value(s) of a key declared under 'object-properties:' resolve to no IRI, so no link was
emitted: arch:architectureState = Target. The value is kept as a schema:additionalProperty pair rather
than emitted as a literal, which would contradict the property's range. Write an absolute IRI, a
prefixed name whose prefix --type-mapping declares, or a bare local name with --ns-vocab set.

Keys are matched as authored. A key written :realizes is declared ':realizes'; one written arch:architectureState is declared as that. There is no normalisation, because two spellings of a key are two keys everywhere else in a type mapping.

Why declared rather than detected. Whether a predicate is an owl:ObjectProperty is in the ontology, and this deliberately does not read it: conversion is offline — only validate fetches ontologies — so detection would make the same model convert differently depending on whether a network was reachable, it could not work for an unpublished in-house vocabulary, and it contradicts the rule every other extension route follows, that links and literals are stated, not inferred.

@id and @type remain the two reserved keys, and are not a substitute: their predicates are fixed at owl:sameAs and rdf:type, so they say "this is the same as that" and "it is also of this class", not "it realizes that capability".

When a @type value resolves

@type is the one key whose value has to resolve rather than its key. It becomes an extra rdf:type when the value is one of:

  • an absolute IRI — https://vocab.example.org/tam#RevenueSystem
  • a prefixed name whose prefix --type-mapping declares under namespaces:, falling back to --ns-vocab when the prefix is undeclared
  • a bare local name, with --ns-vocab set

A value that resolves to none of those claims no class — inventing one would put an undeclared term in the graph — and is kept as a schema:additionalProperty pair instead, so the value is not lost. The run reports it:

[WARN] 1 '@type' value(s) resolve to no class IRI, so no extra rdf:type was emitted: ManagedService.
The value is kept as a schema:additionalProperty pair. Write an absolute IRI, a prefixed name whose
prefix --type-mapping declares, or a bare local name with --ns-vocab set.

Before this release @type was the one key with no fallback: a value that resolved to nothing was discarded entirely, with no rdf:type, no pair and no message. So a model authoring @type: ManagedService and converted without --ns-vocab lost that property silently. Worth counting the @type properties in a model that has been converted without --ns-vocab, since those values were never in the graph.

What each run reports

Keys that reached the graph as pairs are reported at the end of a run, bucketed by remedy, because the three have different fixes and one message would send most readers to the wrong option:

Situation Remedy reported
a plain key, e.g. gitUrl prefix it with : and pass --ns-vocab
a prefixed key whose prefix nothing declares declare it under namespaces: in --type-mapping
a @type value that resolves to no class write it as an IRI, a declared prefixed name, or set --ns-vocab

These were previously collected into ConversionStats and read by nothing, so a property arriving as an unqueryable pair was as silent as one that had been dropped.

Architecture

ArchiMate Exchange XML
  → ExchangeParser (StAX, two-pass)
  → ExchangeModel (elements, relationships, views, folder tree)
  → LinkedArchiEmitter (streaming RDF4J Rio writer)
  → TriG / Turtle output

Validate

Runs SHACL validation on converted output. Shapes and ontologies are fetched from meta.linked.archi at runtime.

Default shapes are relationships, elements and core-shapes:

  • relationships — the source/target pairs the ArchiMate specification permits.
  • elements — the element shapes, including amelsh:ArchiMateElementShape, this notation's naming rule. Junctions are excluded from it, as connectors drawn as a dot or a bar that carry no name. This was previously reachable only through --shapes all, which left ArchiMate output with its relationship rules enforced and nothing checking the elements.
  • core-shapes — the contracts that are not notation-specific: a QualifiedRelationship having exactly one arch:source and arch:target, and arch:conceptOwner pointing at a Stakeholder.
java -jar archimate2linkedarchi.jar validate --input model.trig

# Just the permitted source/target pairs
java -jar archimate2linkedarchi.jar validate --input model.trig --shapes relationships

Shape names: relationships, elements, core-shapes, or all for every set. Run validate --list-assets to see them, along with where fetched documents are stored. The archimate3 and core ontologies are always loaded for reasoning. Switch the naming rule off for a run with --without-shape labels.

Exits 0 when the data conforms, 1 when violations are found, 2 on error.

The relationships shapes enforce the ArchiMate specification's permitted source/target pairs, so they report violations for relationships that ArchiMate does not allow between the given element types. Validate against core alone to check only the foundational Linked.Archi contract:

java -jar archimate2linkedarchi.jar validate -i model.trig --shapes core-shapes

See Validation for the shared engine, all options, shape resolution, coverage reporting and report format.