Apache Commons logo Commons SCXML

Data in SCXML documents

SCXML documents contain numerous expressions, such as when describing the guard conditions for <transition> elements, the expressions that are logged via the <log> element, assignments etc. The data portions in these expressions can come from a couple of sources.

The datamodel element

SCXML gives authors the ability to define a first-class data model as part of the SCXML document. A data model consists of a <datamodel> element containing one or more <data> element, each of which may contain an XML data tree (i.e. it is recommended that each <data> element contain only one child element).

Also, SCXML documents are namespace-aware. Therefore, the root of the data tree should define one or more namespaces as needed, and must not itself be in the SCXML namespace.

For example, the document level data model for a SCXML document defining the states in a travel reservation system may look like this:

     <scxml xmlns="http://www.w3.org/2005/07/scxml"
               version="1.0"
               initial="init-travel-plan">

      <datamodel>
        <data id="airlineticket">
          <!-- Note namespace declaration in line below -->
          <flight xmlns="">
            <origin/>
            <destination/>
            <!-- default values for trip and class -->
            <trip>round</trip>
            <class>economy</class>
            <meal/>
          </flight>
        </data>
        <data id="hotelbooking">
          <hotel xmlns="">
            <stay>
              <startdate/>
              <enddate/>
            </stay>
            <adults>1</adults>
            <children>0</children>
            <rooms>1</rooms>
            <rate/>
          </hotel>
        </data>
      </datamodel>

      <state id="init-travel-plan">
        <!-- content for the init-travel-plan state -->
      </state>

      <!-- and so on ... -->

     </scxml>
    

A <data> element may also contain a string literal or number, which can be considered as a degenerate XML data tree with a single leaf node:

     <data id="foo" expr='bar'" />
    

Scratch space variables

SCXML also allows document authors to define scratch space variables. These may be defined only where executable content is permissible, that is within an <onentry>, <onexit> or <transition> element. A <var> element is used for such definition, like so:

     <onentry>
      <var name="foo" expr="'bar'" />
     </onentry>
    

The difference between the use of a var element as shown above and the degenerate use of a data element (where it contains a single string literal or number, rather than an XML tree) is that the data element is part of the first class datamodel for the document (or state) but the var isn't. This subtlety manifests as different behavior when the SCXML engine is reset, whereby the scratch space variables (var) are lost or deleted, whereas the first class data model elements are restored to their initial value.

Distributing the data model

The <datamodel> element can be "distributed" through the SCXML document. It can be placed as a child element of either the <scxml> element (document root) or any <state> element. This is meant to be an authoring convenience in order to allow parts of the data model to be placed closer to the location in the document where they will be accessed (via expressions, for example).

For example, the above travel reservation datamodel may be authored as follows:

     <scxml xmlns="http://www.w3.org/2005/07/scxml"
               version="1.0"
               initial="airline-ticket">

      <state id="airline-ticket">
        <datamodel>
          <data id="airlineticket">
            <flight xmlns="">
              <origin/>
              <destination/>
              <!-- default values for trip and class -->
              <trip>round</trip>
              <class>economy</class>
              <meal/>
            </flight>
          </data>
        </datamodel>

        <!-- other content for the airline-ticket state -->

        <!-- event names on transitions arbitrarily chosen
                for illustration-->

        <transition event="done.flight.reservation" target="hotel-booking" />
      </state>

      <state id="hotel-booking">
        <datamodel>
          <data id="hotelbooking">
            <hotel xmlns="">
              <stay>
                <startdate/>
                <enddate/>
              </stay>
              <adults>1</adults>
              <children>0</children>
              <rooms>1</rooms>
              <rate/>
            </hotel>
          </data>
        </datamodel>

        <!-- other content for the hotel-booking state -->

        <transition event="done.hotel.booking" target="hotel-booking" />
      </state>

      <!-- other states ... -->

     </scxml>
    

Commons SCXML creates a new Context for each state that needs one, and each data element may be thought of as a org.w3c.dom.Node object placed in the corresponding Context. The datamodel element at the document root populates the root context. See contexts and evaluators section of this user guide for more on contexts, evaluators and root contexts.

References to data in expressions

Since the data elements contain XML data trees, the straightforward way to refer to bits inside these in expressions is to use XPath or an equivalent language. Commons SCXML currently supports expression languages such as Commons JEXL which do not have any inherent understanding of XPath. Therefore, Commons SCXML defines a Data() function for use in JEXL or other expression languages, for example:

    <var name="arrival" expr="Data(hotelbooking, 'hotel/stay/arrival')" />
   

The above expression extracts the arrival date from the hotelbooking data in the documents datamodel and stores it in a scratch space variable named "arrival". The first argument is value of the name attribute of the <data> element and the second is the String value of the XPath expression. If more than one matching nodes are found, the first one is returned.

Assignments

Assignments are done via the SCXML <assign> action, which can only be placed in an <onentry>, <onexit> or <transition> element. Based on the left hand side value (lvalue) and right hand side value (rvalue) in the assignment, Commons SCXML supports three kinds of assignments:

  1. Assigning to a scratch space variable - Here, the lvalue is a variable defined via a <var> element.

          <assign name="foo" expr="some-expression" />
        
    The expression may return a value of any type, which becomes the new value for the variable named "foo".
  2. Assigning a literal to a data subtree - In this case, the lvalue is a node in a data tree and the rvalue is a String literal or a number.

          <assign location="Data(hotelbooking, 'hotel/rooms')" expr="2" />
        
    Or more usefully, the rvalue is some expression that evaluates to the numeric constant (2). In such cases, the literal (String or number) is added as a child text node to the node the lvalue points to.
  3. Assigning a XML tree to a data subtree - Here, the lvalue is a node in a data tree and the rvalue is also a node (in a data tree or otherwise). As an illustration, consider we also had data related to car rentals in the above example, and in certain situations (probably common) the car rental reservation dates coincide with the hotel booking dates, such a data "copy" is performed as:

          <assign location="Data(carrental, 'car/dates')"
                     expr="Data(hotelbooking, 'hotel/stay')" />
    
          <!-- deletes all children of <dates> and then copies
                  over all children of <stay>, the <startdate>
                  and <enddate> in this case -->
        
    In these cases, the children of the node pointed by the expression are first cloned, and then added as children to the node the lvalue points to.