Skip to content

Examples

igor-krechetov edited this page Jun 5, 2021 · 4 revisions

Referencing states defined in an external file

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:

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

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>

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 wiki_examples_xiinclude_wrapped

Including <xi:include> directly

NOTE: SCXML files were edited manually 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>

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 wiki_examples_xiinclude_direct

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.

<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

wiki_examples_state_src_include