SCXML-tutorial

Contents Overview Examples Editor Forum

<datamodel>

Video version

Wrapper element which encapsulates any number of <data> elements, each of which defines a single data object. The exact nature of the data object depends on the data model language used.

<data>

The element is used to declare and populate portions of the data model.

Here is an example:

1. Lua

<datamodel>
    <data expr="true" id="VarBool"/>
    <data expr="1" id="VarInt"/>
    <data expr="'This is a string!'" id="VarString"/>
    <data expr="{ 1, 2, 3, 4, 5 }" id="VarTable"/>
</datamodel>

2. EcmaScript

<data id="VarBool" expr="true"/>
<data id="VarInt" expr="555"/>
<data id="VarFloat" expr="777.777"/>
<data id="VarString" expr="'this is a string'"/>
<data id="VarFunction" expr="function() { return 'hello from func' }"/>
<data id="VarNull" expr="null"/>
<data id="VarUndefined" expr="undefined"/>
<data id="VarComplexObject" expr="new Date()"/>

Attribute Details

NameRequiredTypeDefault ValueValid ValuesDescription
idtrueIDnoneThe name of the data item. See 3.14 IDs for details.
srcfalseURInoneGives the location from which the data object should be fetched. See 5.9.3 Legal Data Values and Value Expressions for details.
exprfalseExpressionnoneAny valid value expressionEvaluates to provide the value of the data item. See 5.9.3 Legal Data Values and Value Expressions for details.

Children

The children of the <data> element represent an in-line specification of the value of the data object. In a conformant SCXML document, a <data> element may have either a 'src' or an 'expr' attribute, but must not have both. Furthermore, if either attribute is present, the element must not have any children. Thus 'src', 'expr' and children are mutually exclusive in the <data> element.

WARNING! Some platforms (Qt, USCXML) can modify multiline expressions as space-normalized strings

It means that if you are using a valid multiline expression that successfully runs in one platform like SCION

<datamodel>
	<data expr="function() {
    var s = 'isFunction'
    return s
}" id="funcExpr"/>
</datamodel>

It can be automatically converted to a syntax-invalid single space-normalized string and fail on other platforms like Qt or USCXML. The reason is of different XML-parsers behaviour

<!-- multiline expression comes to state machine as single line -->
<data expr="function() { var s = 'isFunction' return s }" id="funcExpr"/> 

1:SyntaxError: Unexpected keyword 'return'. Expected ';' after var declaration.

Examples:

1. Different data types assigned by 'expr' attribute.

datamodel

<scxml datamodel="lua" name="Scxml" version="1.0" xmlns="http://www.w3.org/2005/07/scxml">
	<datamodel>
		<data expr="true" id="VarBool"/>
		<data expr="1" id="VarInt"/>
		<data expr="'This is a string!'" id="VarString"/>
		<data expr="{ 1, 2, 3, 4, 5 }" id="VarTable"/>
	</datamodel>
	<state id="Shape1">
		<onentry>
			<log expr="string.format('Value=[%s] Type=[%s]',tostring(VarBool),type(VarBool))" label="VarBool"/>
			<log expr="string.format('Value=[%s] Type=[%s]',tostring(VarInt),type(VarInt))" label="VarInt"/>
			<log expr="string.format('Value=[%s] Type=[%s]',VarString,type(VarString))" label="VarString"/>
			<log expr="string.format('Value=[%s] Type=[%s]',tostring(VarTable),type(VarTable))" label="VarTable"/>
		</onentry>
		<transition target="End"/>
	</state>
	<final id="End"/>
</scxml>

Output:

[Log] VarBool: "Value=[true] Type=[boolean]"

[Log] VarInt: "Value=[1] Type=[number]"

[Log] VarString: "Value=[This is a string!] Type=[string]"

[Log] VarTable: "Value=[table: 003E7790] Type=[table]"

2. Data initialized by 'src' attribute.

datamodel - data src

table1.lua

{ 
	1, 
	2, 
	3, 
	true, 
	"This a string!" 
}

datamodel - data src.scxml

<scxml datamodel="lua" name="Scxml" version="1.0" xmlns="http://www.w3.org/2005/07/scxml">
	<datamodel>
		<data id="VarTable" src="table1.lua"/>
	</datamodel>
	<state id="Shape1">
		<onentry>
			<log expr="string.format('Value=[%s] Type=[%s]',tostring(VarTable),type(VarTable))" label="VarTable"/>
			<foreach array="VarTable" index="indexTable" item="itemTable">
				<log expr="indexTable" label="indexTable"/>
				<log expr="itemTable" label="itemTable"/>
			</foreach>
		</onentry>
		<transition target="End"/>
	</state>
	<final id="End"/>
</scxml>

Output:

[Log] VarTable: "Value=[table: 0096B388] Type=[table]"
[Log] indexTable: 1
[Log] itemTable: 1
[Log] indexTable: 2
[Log] itemTable: 2
[Log] indexTable: 3
[Log] itemTable: 3
[Log] indexTable: 4
[Log] itemTable: true
[Log] indexTable: 5
[Log] itemTable: "This a string!"

3. Data initialized by child value.

datamodel - data child value

<scxml datamodel="lua" name="Scxml" version="1.0" xmlns="http://www.w3.org/2005/07/scxml">
	<datamodel>
		<data id="VarTable">{ 1, true, &quot;This is a string!&quot; }</data>
	</datamodel>
	<state id="Shape1">
		<onentry>
			<log expr="string.format(&quot;Value=[%s] Type=[%s]&quot;,tostring(VarTable),type(VarTable))" label="VarTable"/>
			<foreach array="VarTable" index="indexTable" item="itemTable">
				<log expr="itemTable" label="itemTable"/>
			</foreach>
		</onentry>
		<transition target="End"/>
	</state>
	<final id="End"/>
</scxml>

Output:

[Log] VarTable: "Value=[table: 0083F5E8] Type=[table]"

[Log] itemTable: 1

[Log] itemTable: true

[Log] itemTable: "This is a string!"

The ECMAScript Data Model

For each <data> element in the document, the SCXML Processor must create an ECMAScript variable object whose name is the value of the 'id' attribute of <data>. In cases where the 'src' attribute or in-line content is provided in the <data> element, then if an indication of the type of the content is available (e.g., via a Content-Type header), then the Processor should try to interpret the content according to that indication. Otherwise if the content (whether fetched or provided in-line) is JSON (and the Processor supports JSON), the SCXML Processor must create the corresponding ECMAScript object. Otherwise, if the content is a valid XML document, the Processor must create the corresponding DOM structure and assign it as the value of the variable. Otherwise the Processor must treat the content as a space-normalized string literal and assign it as the value of the variable. If no value is assigned, the SCXML Processor must assign the variable the default value ECMAScript undefined. Note that the assignment takes place at the time indicated by the 'binding' attribute on the <scxml> element.

WARNING! Be careful of assigning complex objects or functions via in-line content of data

SCXML Platforms may pass W3C IRP tests but they may use different variants of assigning in-line content.
Let's take a look at the example

ecmascript_data_assignment_dateobject

<scxml datamodel="ecmascript" name="TestDataInLine" version="1.0" xmlns="http://www.w3.org/2005/07/scxml">
	<datamodel>
		<data id="varTest">new Date()</data>
	</datamodel>
	<final id="End">
		<onentry>
			<log expr="typeof varTest" label="varTest"/>
		</onentry>
	</final>
</scxml>

Variant 1. Order of checks: is Empty -> JSON -> XML -> space-normalised string

ecmascript_data_assignment_1

For example: platforms USCXML, SCION are using such algorithm and varTest will be assigned as string.
Output: [Log] varTest: "string"

Variant 2. Order of checks: is Empty -> EcmaScript -> JSON -> XML -> space-normalised string

ecmascript_data_assignment_2

For example: platforms Qt, USCXMLClib are using such algorithm and varTest will be assigned as Date object.
Output: "varTest" : "object"

NOTICE! If you want to be sure to have the same behaviour of data on every platform, assign complex data via <script> element

W3C IRP tests

1. Test 276

The SCXML Processor MUST allow the environment to provide values for top-level data elements at instantiation time. (Top-level data elements are those that are children of the datamodel element that is a child of scxml). Specifically, the Processor MUST use the values provided at instantiation time instead of those contained in these data elements.

test276

test276sub1

2. Test 277

If the value specified for a data element (by 'src', children, or the environment) is not a legal data value, the SCXML Processor MUST raise place error.execution in the internal event queue and MUST create an empty data element in the data model with the specified id.

test277

3. Test 279

When 'binding' attribute on the <scxml> element is assigned the value "early" (the default), the SCXML Processor MUST create all data elements and assign their initial values at document initialization time.

test279

4. Test 280

When 'binding' attribute on the <scxml> element is assigned the value "late", the SCXML Processor MUST create the data elements at document initialization time, but MUST assign the specified initial value to a given data element only when the state that contains it is entered for the first time, before any onentry markup.

test280

5. Test 550

If the 'expr' attribute is present, the Platform MUST evaluate the corresponding expression at the time specified by the 'binding' attribute of <scxml> and MUST assign the resulting value as the value of the data element.

test550

6. Test 551

If child content is specified, the Platform MUST assign it as the value of the <data> element at the time specified by the 'binding' attribute of <scxml>.

test551

7. Test 552

If the 'src' attribute is present, the Platform MUST fetch the specified object at the time specified by the 'binding' attribute of <scxml> and MUST assign it as the value of the data element.

test552

test552.txt

1

8. Test 557

in the ECMA data model, test that if the child of <data> is XML, or if XML is loaded via 'src', the processor assigns it as the value of the var

test557

test557.txt

<books xmlns="">
    <book title="title1"/>
    <book title="title2"/>
</books>
TOP Contents Overview Examples Editor Forum