7. Saving, and converting to RDF¶
A model can be written in two forms, SysML v2 notation (.sysml, .kerml) and RDF in
Turtle (.ttl), and converted between them from the REPL, the command line or over gRPC. JSON
is not involved anywhere in this path, not even as an intermediate form.
The vocabulary each triple uses, and the constructs the mapping does not cover, are documented in reference/rdf-mapping.md.
RDF conversion is experimental. It covers model structure and the behavior written in model bodies, refuses any construct it cannot write back, and its vocabulary may change without a compatibility path. Every run that converts RDF prints a note saying so. Saving to
.sysmlor.kermlis stable and exact. See reference/rdf-mapping.md § Status.
Saving a session¶
%save writes the session out, choosing the format from the file extension: .sysml for
notation and .ttl for RDF Turtle.
sysml> package Demo { private import ScalarValues::*; part def Vehicle { attribute mass : Real = 1500.0; } }
✓ package Demo
sysml> %save my_model.sysml
saved 102 bytes of sysml to my_model.sysml
sysml> %save my_model.ttl
note: RDF conversion — Turtle and the API's JSON element form alike — is experimental: the mapping covers model structure and the behavior its bodies state, refuses what it cannot write back, and its vocabulary may change without a compatibility path; see docs/reference/rdf-mapping.md § Status
saved 5746 bytes of ttl to my_model.ttl
A leading ~ is expanded. An existing file is replaced (and the replacement is reported), and the
write is atomic, so an interrupted save leaves the previous file intact. An existing file keeps
its permissions, and a symlink is written through rather than replaced.
A session that does not fully parse is still saved as notation. The file contains the text you typed, re-indented, so the syntax errors are reported as warnings and no work is left stranded in the REPL.
sysml> package Demo {
...> part def Vehicle;
...> ???
...> }
3:3: error: expected a namespace member
???
^~
sysml> %save my_model.sysml
warning: <session>: 1 syntax error(s):
3:3: expected a namespace member
warning: the file is saved as typed; fix these and save again
saved 47 bytes of sysml to my_model.sysml
Saving to .ttl still refuses such a session, because a graph built from a tree the parser
only partly recovered would silently drop declarations. sysml -convert behaves the same way,
since in that case the source already exists on disk.
The same conversion is available without starting the REPL:
$ sysml my_model.sysml -convert ttl -o my_model.ttl # notation to RDF
$ sysml my_model.ttl -convert sysml -o back.sysml # RDF to notation
$ sysml my_model.sysml -convert ttl # to stdout
The model is given the same way as in every other use of the command, and -convert names the
target format.
Converting from the command line¶
sysml model.sysml -convert ttl -o model.ttl # notation to RDF
sysml model.ttl -convert sysml -o model.sysml # RDF to notation
sysml model.sysml -convert ttl # to stdout
The model is a positional argument, as in every other mode of the command, and -convert names
the target format. Flags can go before or after the model.
The input format is inferred from the file extension. If the extension is missing or
unrecognized, say what it is with -from:
-convert and -from accept sysml, kerml, text, ttl, turtle and rdf; -from also
accepts xmi (or uml, mdzip) for a SysML v1 model exported as OMG XMI, an Eclipse .uml
file or a zip archive holding the XMI (a MagicDraw/Cameo .mdzip project), which is migrated
to v2 on the way in — an experimental path, and every run that takes it says so on stderr;
chapter 11 walks one through, and
SysML v1 migration states the mapping. The output path
plays no part in choosing the format, so a destination without an extension, such as -o /dev/null
or a FIFO, needs no extra flags.
Converting to the same format rewrites the input: notation is reformatted, and Turtle is normalized (prefixes sorted, predicates grouped by subject).
Exit status¶
The command exits non-zero and writes nothing for any input it cannot convert faithfully, whether that is a syntax error in the notation, malformed Turtle, or an RDF construct outside the mapping. It never writes a partial model.
Converting over gRPC and from Python¶
The same conversion is available as the service method Convert, which GetServerInfo reports as
the convert capability. It accepts either a file_path that the service opens or content
passed inline, takes the same format names as -from and -to, and returns the written text
with its formats, or an error together with the diagnostics that explain it.
tolerate_syntax_errors writes notation despite syntax errors; it is rejected for any direction
that builds a graph, where an unparsed declaration would be silently dropped.
A response whose conversion used the RDF mapping sets experimental and experimental_notice,
whether it succeeded or refused, so a client can learn the status from the response rather than
from this page. The opensysml client raises this as an ExperimentalFeatureWarning, which
warnings.simplefilter can suppress:
import warnings
from opensysml import ExperimentalFeatureWarning
warnings.simplefilter("ignore", ExperimentalFeatureWarning)
From Python:
model = opensysml.load("model.sysml")
model.save("model.ttl") # SysML notation to RDF
opensysml.convert("sysml", file_path="model.ttl") # and back
The client API is documented in reference/python-api.md, and chapter 9 shows how to use it.
Round-tripping¶
notation → RDF → notation gives back an equivalent model, and
notation → RDF → notation → RDF gives back the same graph. This is the property the test
suite checks over the fixtures in tests/export/testdata/convert/.
The notation that comes out of a round trip is the source itself when the graph still carries it:
every element written to .ttl carries its lines as sysx:sourceText, comments and blank lines
included, exactly as the file spells them — tabs, odd indentation, CRLF and all — and converting
back returns them, so the file comes back byte for byte. The graph stays authoritative: an
element whose triples were edited after the export — a flag set, a value changed, a member
removed — is written back from its structure in canonical notation, and only that element's
lines change. A graph without source text, from another tool or with the text stripped, is
written entirely from its structure: a reference may then be written relative to a different
scope, and a clause written :> comes back as specializes. Both forms parse to the same model,
which the second conversion to RDF confirms. The rules are in
reference/rdf-mapping.md.
Saving to .sysml writes the source directly. It writes the session's own source through
the formatter rather than re-printing the graph, so comments, notes and spacing are preserved
whether or not the model was edited. Only the .ttl direction uses the mapping. Syntax is
checked in every direction, and notation the parser cannot read is rejected, so a save never
silently reformats a model that does not parse.
A worked example¶
examples/rdf-interop-demo.sysml is the reference model
for this chapter: a rover and its ground link, declared with packages, definitions, usages, ports,
a connection, multiplicity, values and documentation. The mapping covers all of these, so the
model converts in both directions:
$ sysml examples/rdf-interop-demo.sysml -convert ttl -o /tmp/rover.ttl
note: RDF conversion — Turtle and the API's JSON element form alike — is experimental: the mapping covers model structure and the behavior its bodies state, refuses what it cannot write back, and its vocabulary may change without a compatibility path; see docs/reference/rdf-mapping.md § Status
wrote /tmp/rover.ttl (ttl, 72765 bytes)
$ sysml /tmp/rover.ttl -convert sysml -o /tmp/rover-back.sysml
note: RDF conversion — Turtle and the API's JSON element form alike — is experimental: the mapping covers model structure and the behavior its bodies state, refuses what it cannot write back, and its vocabulary may change without a compatibility path; see docs/reference/rdf-mapping.md § Status
wrote /tmp/rover-back.sysml (sysml, 1014 bytes)
Converting the returned notation again produces a byte-identical graph, which is the round-trip
property described above. The // header comment comes back with the source text the graph
carries and is lost once that text is stripped, as explained in
reference/rdf-mapping.md; the package's doc and comment are
declarations and survive either way.
examples/semantic-layer/demo.sysml
and examples/repl-behavioral-demo.sysml
also convert, as do all of the parser_features_demo_*.kerml files. The
behavior written in a body converts too: states, regions, substates, action nodes, assignments,
transitions and the result expression a calculation ends in all have a mapping. Conversion is
refused for constructs the notation could not be rebuilt from. A refusal names the construct where
conversion stopped and says why the graph could not carry it:
$ sysml examples/parser_features_demo_action_semantics.sysml -convert ttl -o /tmp/action-semantics.ttl; echo $?
note: RDF conversion — Turtle and the API's JSON element form alike — is experimental: the mapping covers model structure and the behavior its bodies state, refuses what it cannot write back, and its vocabulary may change without a compatibility path; see docs/reference/rdf-mapping.md § Status
wrote /tmp/action-semantics.ttl (ttl, 241275 bytes)
0
Two members of one namespace sharing a name export as separate elements: the first keeps the
qualified name and each later one is identified by its position among the owner's members, the same
name an element declared unnamed takes. The duplicate is still reported as a warning when the model
is analyzed — SysML has no reopening of a declaration within a namespace, so merge the declarations
into one (or rename) rather than relying on the position. A member named '@2' is spelled
Demo::'@2', distinct from the positional identity Demo::@2.
Next: 8. Editors.