SCXML Format
Overview
From Wikipedia :
SCXML stands for State Chart XML: State Machine Notation for Control Abstraction. It is an XML-based markup language that provides a generic state-machine-based execution environment based on Harel statecharts.
SCXML is able to describe complex finite state machines. For example, it is possible to describe notations such as sub-states, parallel states, synchronization, or concurrency, in SCXML.
SCXML format specification can be found on W3 official website.
SCXML format was designed to describe both structure and functionality inside a single file. But since we are using it only to define structure, some of SCXML features will be ignored.
Callbacks Definition
There are 5 types of callbacks that could be defined for HSM:
on state changed:
<state id="state_1">
<invoke srcexpr="onState1"/>
</state>
on state entering:
<state id="state_1">
<onentry>
<script>onEnteringState1</script>
</onentry>
</state>
on state exiting:
<state id="state_1">
<onexit>
<script>onExitingState1</script>
</onexit>
</state>
on transition:
<state id="state_1">
<transition event="NEXT_STATE" target="state_2">
<script>onNextStateTransition</script>
</transition>
</state>
on condition check:
<state id="state_1">
<transition event="NEXT_STATE" cond="checkNextStateTransition" target="state_2"/>
</state>
Callback names should comply with C++ identifier naming rules.
Splitting SCXML files
When defining your HSM structure you might want to reuse a state or a group of states for some common logic (for example error handling). Included file must comply with SCXML format and have a root node <scxml> defined.
There are two ways to include another file inside of your scxml:
using <xi:include> tag
using “src” attribute of a state
Include using <xi:include>
This is a standard way which is compliant with W3 specification. For this tag to work additional namespace must be added to your scxml:
<scxml xmlns:xi="http://www.w3.org/2001/XInclude">
Restrictions and things to consider:
<xi:include> tag can only be a child of <scxml> or <state> nodes. It’s not allowed to put it anywhere else.
availability of initial state in included file is optional, but your HSM will usually not work without one (validation was disabled on purpose to allow importing of a single state).
it’s highly recommended to wrap <xi:include> into a <state> node which doesnt contain any other states or includes (transitions are allowed).
in this case parent state will work like a namespace altering included state names to avoid name collision (if you want to include same file multiple times);
exit transition can be defined
when using <xi:include> on the same level with other states or include keep in mid that:
code will be inserted as-is. name collisions, incorrect initial states, non existent transitions will not be resolved;
GUI editors don’t allow to define exit/enter transitions (though it’s possible to define them manually in XML you will loose ability to edit such file in GUI editor).
Using <xi:include> with a wrapper state
/examples/scxml/includes/xi_include_wrapped.scxml
<scxml initial="State0" version="1.0" xmlns="http://www.w3.org/2005/07/scxml" xmlns:xi="http://www.w3.org/2001/XInclude">
<state id="State0">
<transition event="EVENT_1" target="ImportedState"></transition>
</state>
<state id="ImportedState">
<transition event="EVENT_2" target="State2"></transition>
<xi:include href="./substates1.scxml" parse="xml"></xi:include>
</state>
<state id="State2"></state>
</scxml>
/examples/scxml/includes/substates1.scxml
<scxml initial="state_a" version="1.0" xmlns="http://www.w3.org/2005/07/scxml">
<state id="state_a">
<transition event="EVENT_B" target="state_b"></transition>
</state>
<state id="state_b">
<transition event="EVENT_C" target="state_c"></transition>
</state>
<state id="state_c">
<transition event="EVENT_B" target="state_b"></transition>
</state>
</scxml>
Result structure
Including <xi:include> directly
/examples/scxml/includes/xi_include_direct.scxml
<scxml initial="State0" version="1.0" xmlns="http://www.w3.org/2005/07/scxml" xmlns:xi="http://www.w3.org/2001/XInclude">
<state id="State0">
<transition event="EVENT_1" target="State1"></transition>
</state>
<xi:include href="state1.scxml" parse="xml"></xi:include>
<state id="State2"></state>
</scxml>
Note how we define a transition to State1 even though it’s not defined in xi_include_direct.scxml. Transition will become valid after code from state1.scxml will be included.
<transition event="EVENT_1" target="State1"></transition>
/examples/scxml/includes/state1.scxml
<scxml version="1.0" xmlns="http://www.w3.org/2005/07/scxml">
<state id="State1">
<onentry>
<script>onEnteringState1</script>
</onentry>
<onexit>
<script>onExitingState1</script>
</onexit>
<transition event="SELF_TRANSITION"></transition>
<transition event="EVENT_2" target="State2"></transition>
<invoke srcexpr="onState1"></invoke>
</state>
</scxml>
Note how we define a transition to State2 even though it’s not defined in state1.scxml:
<transition event="EVENT_2" target="State2"></transition>
Result structure
Include using “src” attribute of <state>
It’s possible to reference external scxml files by using “src” attribute of a <state>.
<state id="..." src="file path">
...
</state>
This will behave exactly same as a <xi:include> tag wrapped inside a <state>.
Keep in mind that this is not a part of W3 SCXML specification and was added only because it’s supported by scxmlgui.
/examples/scxml/includes/state_src_include.scxml
<scxml initial="State0" version="1.0" xmlns="http://www.w3.org/2005/07/scxml">
<state id="State0">
<transition event="EVENT_1" target="Substates1"></transition>
</state>
<state id="State2"></state>
<state id="Substates1" src="./substates1.scxml">
<transition event="EVENT_2" target="State2"></transition>
</state>
</scxml>
Result structure