Copyright © 2014 W3C ® ( MIT , ERCIM , Keio , Beihang ), All Rights Reserved. W3C liability , trademark and document use rules apply.
This document describes SCXML, or the "State Chart extensible Markup Language". SCXML provides a generic state-machine based execution environment based on CCXML and Harel State Tables.
This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.
This
is
the
Candidate
Recommendation
third
Last
Call
Working
Draft
of
SCXML
published
on
13
March
29
May
2014
for
review
by
W3C
Members
and
other
interested
parties,
and
has
been
developed
by
the
Voice
Browser
Working
Group
as
part
of
the
W3C
Voice
Browser
Activity
.
Comments
for
this
specification
are
welcomed
to
www-voice@w3.org
(
archives
).
See
W3C
mailing
list
and
archive
usage
guidelines
.
Please
send
comments
by
the
end
of
the
Last
Call
review
period
on
26
June
2014.
There
are
only
minor
editorial
have
been
changes
from
to
the
normative
language
for
history
states
and
to
the
algorithm
for
SCXML
interpretation
since
the
previous
draft.
Candidate
Recommendation
version.
Furthermore,
the
algorithm
has
been
changed
to
informative
status.
Therefore
according
to
W3C
Process
Section
7.4.6
we
are
issuing
another
Last
Call
Working
Draft.
We
expect
to
spend
as
short
a
time
at
Last
Call
as
possible
so
that
we
can
move
back
to
the
Candidate
Recommendation
stage
again
as
quickly
as
possible.
A
diff-marked
version
of
this
document
is
also
available
for
comparison
purposes.
This
An
Implementation
Report
Plan
is
a
W3C
Candidate
Recommendation
currently
being
developed
for
review
by
W3C
Members
and
other
interested
parties.
W3C
publishes
a
technical
report
as
a
Candidate
Recommendation
to
indicate
that
the
document
is
believed
to
be
stable,
and
to
encourage
implementation
by
the
developer
community.
this
specification.
The
entrance
criteria
Working
Group
currently
expects
to
the
Proposed
Recommendation
phase
require
at
least
two
independently
developed
interoperable
implementations
of
each
feature.
Detailed
implementation
requirements
required
feature
and
the
invitation
for
participation
in
the
Implementation
Report
are
provided
each
optional
feature
that
affects
interoperability,
in
the
Implementation
Report
Plan
.
We
expect
order
to
meet
all
requirements
exit
the
next
phase
of
that
report
within
this
document,
the
Candidate
Recommendation
period
closing
on
13
May
2014.
The
phase.
To
help
the
Voice
Browser
Working
Group
will
advance
SCXML
1.0
to
Proposed
Recommendation
no
sooner
than
13
May
2014
Some
of
the
features
in
the
current
draft
specification
build
such
a
report,
reviewers
are
considered
to
be
at
risk
of
removal
due
encouraged
to
potential
lack
of
implementations.
C.3
The
XPath
Data
Model
D.3
DOM
Event
I/O
Processor
Comments
for
implement
this
specification
are
welcomed
and
to
indicate
to
www-voice@w3.org
(
archives
).
See
W3C
mailing
list
which
features
have
been
implemented,
and
archive
usage
guidelines
.
Please
check
the
disposition
of
comments
received
during
the
second
Last
Call
period.
any
problems
that
arose.
Publication
as
a
Candidate
Recommendation
Last
Call
Working
Draft
does
not
imply
endorsement
by
the
W3C
Membership.
This
is
a
draft
document
and
may
be
updated,
replaced
or
obsoleted
by
other
documents
at
any
time.
It
is
inappropriate
to
cite
this
document
as
other
than
work
in
progress.
This document was produced by a group operating under the 5 February 2004 W3C Patent Policy . W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy .
1
Terminology
2
Overview
3
Core
Constructs
3.1
Introduction
3.2
<scxml>
3.3
<state>
3.4
<parallel>
3.5
<transition>
3.6
<initial>
3.7
<final>
3.8
<onentry>
3.9
<onexit>
3.10
<history>
3.11
Legal
State
Configurations
and
Specifications
3.12
SCXML
Events
3.13
Selecting
and
Executing
Transitions
3.14
IDs
4
Executable
Content
4.1
Introduction
4.2
<raise>
4.3
<if>
4.4
<elseif>
4.5
<else>
4.6
<foreach>
4.7
<log>
4.8
Other
Executable
Content
4.9
Evaluation
of
Executable
Content
4.10
Extensibility
of
Executable
Content
5
Data
Model
and
Data
Manipulation
5.1
Introduction
5.2
<datamodel>
5.3
<data>
5.4
<assign>
5.5
<donedata>
5.6
<content>
5.7
<param>
5.8
<script>
5.9
Expressions
5.10
System
Variables
6
External
Communications
6.1
Introduction
6.2
<send>
6.3
<cancel>
6.4
<invoke>
6.5
<finalize>
A
Algorithm
for
SCXML
Interpretation
B
Conformance
B.1
A.1
Conforming
Documents
B.2
A.2
Conforming
Processors
C
B
Data
Models
C.1
B.1
The
Null
Data
Model
C.2
B.2
The
ECMAScript
Data
Model
C.3
B.3
The
XPath
Data
Model
D
C
Event
I/O
Processors
D.1
C.1
SCXML
Event
I/O
Processor
D.2
C.2
Basic
HTTP
Event
I/O
Processor
D.3
C.3
DOM
Event
I/O
Processor
D
Algorithm
for
SCXML
Interpretation
E
Schema
F
Related
Work
G
Examples
G.1
Language
Overview
G.2
Microwave
Example
G.3
Microwave
Example
(Using
parallel)
G.4
Calculator
Example
G.5
Examples
of
Invoke
and
finalize
G.6
Inline
Content
and
Namespaces
G.7
Custom
Action
Elements
H
MIME
Type
H.1
Registration
of
MIME
media
type
application/scxml+xml
H.2
Fragment
Identifiers
I
References
I.1
Normative
References
I.2
Informative
References
The key words MUST , MUST NOT , REQUIRED , SHALL , SHALL NOT , SHOULD , SHOULD NOT , RECOMMENDED , MAY , and OPTIONAL in this specification are to be interpreted as described in [RFC 2119] .
The terms base URI and relative URI are used in this specification as they are defined in [RFC 2396] .
All sections not marked as "informative" are normative.
[This section is informative.]
This document outlines State Chart XML (SCXML), which is a general-purpose event-based state machine language that combines concepts from CCXML and Harel State Tables. CCXML [CCXML 1.0] is an event-based state machine language designed to support call control features in Voice Applications (specifically including VoiceXML but not limited to it). The CCXML 1.0 specification defines both a state machine and event handing syntax and a standardized set of call control elements. Harel State Tables are a state machine notation that was developed by the mathematician David Harel [Harel and Politi] and is included in UML [UML 2.3] . They offer a clean and well-thought out semantics for sophisticated constructs such as parallel states. They have been defined as a graphical specification language, however, and hence do not have an XML representation. The goal of this document is to combine Harel semantics with an XML syntax that is a logical extension of CCXML's state and event notation.
3 Core Constructs presents the core state machine concepts, while 4 Executable Content contains an extensible set of actions that the state machine can take in response to events. 5 Data Model and Data Manipulation defines constructs for storing and modifying data, while 6 External Communications provides the capability of communicating with external entities.
[This section is informative.]
The most basic state machine concepts are 3.3 <state> , 3.5 <transition> and event ( 3.12 SCXML Events ). Each state contains a set of transitions that define how it reacts to events. Events can be generated by the state machine itself or by external entities. In a traditional state machine, the machine is always in a single state. This state is called the active state. When an event occurs, the state machine checks the transitions that are defined in the active state. If it finds one that matches the event, it moves from the active state to the state specified by the transition (called the "target" of the transition.) Thus the target state becomes the new active state.
The Harel state notation defines several extensions to these basic notions. First of all, the state machine may take actions (as defined in 4 Executable Content ) while taking transitions. Specifically, each state may contain 3.8 <onentry> and 3.9 <onexit> actions. Transitions may also contain actions. If a state machine takes transition T from state S1 to state S2, it first performs the onexit actions in S1, then the actions in T, then the onentry actions in S2. Secondly, in addition to the 'event' attribute that specifies the event(s) that can trigger it, transitions also have a 'cond' attribute. If a transition has both 'event' and 'cond' attributes, it will be selected only if an event is raised whose name matches the 'event' attribute (see 3.12.1 Event Descriptors for details) and the 'cond' condition evaluates to true. If the 'event' attribute is missing, the transition is taken whenever the 'cond' evaluates to true. If more than one transition matches, the first one in document order will be taken. Thus, in the following example, the system will transition to s1 when event e (or e.foo, etc.) occurs if x is equal to 1, but will transition to s2 if event e (or e.foo, etc.) occurs and x is not equal to 1, and will go to s3 if any other event occurs.
<state id=s"> <transition event="e" cond="x==1" target="s1"/> <transition event="e" target="s2"/> <transition event="*" target="s3"/> </state>
One of the most powerful concepts in Harel notation is the idea that states may have internal structure. In particular, a <state> element may contain nested <state> elements. Such a state is called a compound state and we speak of it as the parent state, while the nested elements are child states. The child states may themselves have nested children and the nesting may proceed to any depth. Ultimately we will reach a state that does not contain any child states. Such a state is called an atomic state. When a compound state is active, one and only one of its child states is active. Conversely, when an child state is active, its parent state must be active too. Thus at any point we have a set of active states, containing an atomic state and all of its ancestors. (We will see in the next section that multiple atomic states can be active at the same time.)
Compound states also affect how transitions are selected. When looking for transitions, the state machine first looks in the most deeply nested active state(s), i.e., in the atomic state(s) that have no substates. If no transitions match in the atomic state, the state machine will look in its parent state, then in the parent's parent, etc. Thus transitions in ancestor states serve as defaults that will be taken if no transition matches in a descendant state. If no transition matches in any state, the event is discarded.
The <parallel> element represents a state whose children execute in parallel. Like <state>, the <parallel> element contains <onentry>, <onexit>, <transition>, and <state> or <parallel> children. However, the semantics of <parallel> are different. When a <state> is active, exactly one of its children is active. When a <parallel> element is active, all of its children are active. Specifically, when the state machine enters the parent <parallel> state, it also enters each child state. The child states execute in parallel in the sense that any event that is processed is processed in each child state independently, and each child state may take a different transition in response to the event. (Similarly, one child state may take a transition in response to an event, while another child ignores it.) When all of the children reach final states, the <parallel> element itself is considered to be in a final state, and a completion event done.state. id is generated, where id is the id of the <parallel> element.
Transitions within the individual child elements operate normally. However whenever a transition is taken with a target outside the <parallel> element, the <parallel> element and all of its child elements are exited and the corresponding <onexit> handlers are executed. The handlers for the child elements execute first, in document order, followed by those of the parent <parallel> element, followed by an action expression in the <transition> element, and then the <onentry> handlers in the "target" state.
In the following example, parallel state 'p' has two children S1 and S2. Suppose a transition takes S1's child S12 as a target. (Note that this is permitted even though S12 is not the default initial state for S1 and that S11 is not, in fact, visited in the course of this example). Upon this transition, the state machine, in addition to entering S1 and S12, will also enter S1's parallel sibling S2 and its initial state S21. Once the transition has been taken, p, S1, S2, S12, and S21 will all be active. If event 'e1' occurs, it will cause S12 to transition to S1Final, and S21 to transition to S22. Entering S1Final will cause the event done.state.S1 to be generated. At this point, S1 is in a final state, but S2 is still active. Now suppose event 'e2' occurs. This will cause S22 to transition to S2Final, and the event done.state.S2 will be generated. Furthermore, since all of p's children are now in final states, the event 'done.state.p' will be generated, which will cause the transition contained in p to be triggered, exiting the entire region.
<parallel id="p"> <transition event="done.state.p" target="someOtherState"/> <state id="S1" initial="S11"> <state id="S11"> <transition event="e4" target="S12"/> </state> <state id="S12"> <transition event="e1" target="S1Final"/> </state> <final id="S1Final"/></state></state> <state id="S2" initial="S21"> <state id=S21"> <transition event="e1" target="S22"/> </state> <state id="S22"> <transition event="e2" target="S2Final/> </state> <final id="S2Final"/></state></state> </parallel>
Note
that
the
semantics
of
the
<parallel>
element
does
not
call
for
multiple
threads
or
truly
concurrent
processing.
The
children
of
<parallel>
execute
in
parallel
in
the
sense
that
they
are
all
simultaneously
active
and
each
one
independently
selects
transitions
for
any
event
that
is
received.
However,
the
parallel
children
process
the
event
in
a
defined,
serial
order,
so
no
conflicts
or
race
conditions
can
occur.
See
A
D
Algorithm
for
SCXML
Interpretation
for
a
detailed
description
of
the
semantics
of
<parallel>
and
the
rest
of
SCXML.
In the presence of compound states, transitions no longer simply move from the current active state to a new active state, but from one set of active states to another. (See 3.11 Legal State Configurations and Specifications for details.) If the target of a transition is an atomic state, the state machine will enter not only the atomic state, but also any of its ancestor states that are not already active. Conversely, a transition may take a compound state as its target. In this case, one of the compound state's children must also become active, but the transition does not specify which one. In this case we look at the target state's 3.6 <initial> child which specifies the state's default initial state, that is, the child state to enter if the transition does not specify one. (If the default initial state is itself compound, the state machine will also enter its default initial state, and so on recursively until it reaches an atomic state.) The presence of default initial states provides a form of encapsulation, since a transition may select a compound state as its target without understanding its internal substate structure.
The default initial state of a compound state may also be specified via the 'initial' attribute. The only difference between the <initial> element and the 'initial' attribute is that the <initial> element contains a <transition> element which may in turn contain executable content which will be executed before the default state is entered. If the 'initial' attribute is specified instead, the specified state will be entered, but no executable content will be executed. (If neither the <initial> child or the 'initial' element is specified, the default initial state is the first child state in document order.) As an example, suppose that parent state S contains child states S1 and S2 in that order. If S specifies S1 as its default initial state via the 'initial' attribute (or fails to specify any initial state), then any transition that specifies S as its target will result in the state machine entering S1 as well as S. In this case, the result is exactly the same as if the transition had taken S1 as its target. If, on the other hand, S specifies S1 as its default initial state via an <initial> element containing a <transition> with S1 as its target, the <transition> can contain executable content which will execute before the default entry into S1. In this case, there is a difference between a transition that takes S as its target and one that takes S1 as its target. In the former case, but not in the latter, the executable content inside the <initial> transition will be executed.
A compound state may also have final and history states as children. 3.7 <final> is used to signify that the parent state is in some sense "done" with its processing. When a state machine enters a <final> substate of a compound state, the parent state remains active, but the event "done.state. id " is generated, where id is the state id of the parent state. This event can trigger a transition in any ancestor state (including the parent). If the transition takes a target outside the parent state, the "done.state. id " event in effect serves as a signal that it is time to leave the parent state. 3.10 <history> allows for pause and resume semantics in compound states. Before the state machine exits a compound state, it records the state's active descendants. If the 'type' attribute of the <history> state is set to "deep", the state machine saves the state's full active descendant configuration, down to the atomic descendant(s). If 'type' is set to "shallow", the state machine remembers only which immediate child was active. After that, if a transition takes a <history> child of the state as its target, the state machine re-enters not only the parent compound state but also the state(s) in the saved configuration. Thus a transition with a deep history state as its target returns to exactly where the state was when it was last exited, while a transition with a shallow history state as a target re-enters the previously active child state, but will enter the child's default initial state (if the child is itself compound.)
In the case of a transition located in a compound state, the 'type' attribute is significant. The behavior of a transition with 'type' of "external" (the default) is defined in terms of the transition's source state (which is the state that contains the transition), the transition's target state(or states), and the Least Common Compound Ancestor (LCCA) of the source and target states (which is the closest compound state that is an ancestor of all the source and target states). When a transition is taken, the state machine will exit all active states that are proper descendants of the LCCA, starting with the innermost one(s) and working up to the immediate descendant(s) of the LCCA. (A 'proper descendant' of a state is a child, or a child of a child, or a child of a child of a child, etc.) Then the state machine enters the target state(s), plus any states that are between it and the LCCA, starting with the outermost one (i.e., the immediate descendant of the LCCA) and working down to the target state(s). As states are exited, their <onexit> handlers are executed. Then the executable content in the transition is executed, followed by the <onentry> handlers of the states that are entered. If the target state(s) of the transition is not atomic, the state machine will enter their default initial states recursively until it reaches an atomic state(s).
In
the
example
below,
assume
that
state
s11
is
active
when
event
'e'
occurs.
The
source
of
the
transition
is
state
s1,
its
target
is
state
s21,
and
the
LCCA
is
state
S.
When
the
transition
is
taken,
first
state
S11
is
exited,
then
state
s1,
then
state
s2
is
entered,
then
state
s21.
Note
that
the
LCCA
S
is
neither
entered
nor
exited.
For
more
details
see
3.13
Selecting
and
Executing
Transitions
and
A
D
Algorithm
for
SCXML
Interpretation
.
<state id="S" initial="s1"> <state id="s1" initial="s11"> <onexit> <log expr="'leaving s1'"/> </onexit><state id="s11"> <onexit> <log expr="'leaving s11'"/> </onexit> </state><transition event="e" target="s21"> <log expr="'executing transition'"/> </transition> </state><state id="s2" initial="s21"> <state id="s21"> <onentry> <log expr="'entering s21'"/> </onentry> </state> <onentry> <log expr="'entering s2'"/> </onentry> </state> <onentry> <log expr="'entering S'"/><onentry><onentry> <onexit> <log expr="'leaving S'"/> <onexit> </state> ==== log output will be ======> leaving s11 leaving s1 executing transition entering s2 entering s21
The behavior of transitions with 'type' of "internal" is identical, except in the case of a transition whose source state is a compound state and whose target(s) is a descendant of the source. In such a case, an internal transition will not exit and re-enter its source state, while an external one will, as shown in the example below.
<state id="S" initial="s1"> <state id="s1" initial="s11"> <onentry> <log expr="entering S1"/> </onentry> <onexit> <log expr="'leaving s1'"/> </onexit><state id="s11"> <onentry> <log expr="entering s11"/> </onentry> <onexit> <log expr="'leaving s11'"/> </onexit> </state><transition event="e" target="s11" type="internal"> <log expr="'executing transition'"/> </transition> </state>==== log output will be ======> leaving s11 executing transition entering s11 === if transition were external, log output would be ====> leaving s11 leaving s1 executing transition entering s1 entering s11
If the 'target' on a <transition> is omitted, then the value of 'type' does not have any effect and taking the transition does not change the state configuration but does invoke the executable content that is included in the transition. Note that this is different from a <transition> whose 'target' is its source state. In the latter case, the state is exited and reentered, triggering execution of its <onentry> and <onexit> executable content.
[This section is normative.]
The top-level wrapper element, which carries version information. The actual state machine consists of its children. Note that only one of the children is active at any one time. See 3.11 Legal State Configurations and Specifications for details.
Name | Required | Attribute Constraints | Type | Default Value | Valid Values | Description |
---|---|---|---|---|---|---|
initial | false | none | IDREFS | none | A legal state specification. See 3.11 Legal State Configurations and Specifications for details. | The id of the initial state(s) for the document. If not specified, the default initial state is the first child state in document order. |
name | false | none | NMTOKEN | none | Any valid NMTOKEN | The name of this state machine. It is for purely informational purposes. |
xmlns | true | none | URI | none | The value MUST be "http://www.w3.org/2005/07/scxml". | |
version | true | none | decimal | none | The value MUST be "1.0" | |
datamodel | false | none | NMTOKEN | platform-specific | "null", "ecmascript", "xpath" or other platform-defined values. |
The
datamodel
that
this
document
requires.
"null"
denotes
the
Null
datamodel,
"ecmascript"
the
ECMAScript
datamodel,
and
"xpath"
the
XPath
datamodel,
as
defined
in
|
binding | false | none | enum | "early" | "early", "late" | The data binding to use. See 5.3.3 Data Binding for details. |
A conformant SCXML document MUST have at least one <state>, <parallel> or <final> child. At system initialization time, the SCXML Processor MUST enter the states specified by the 'initial' attribute, if it is present. If it is not present, the Processor MUST enter the first state in document order. Platforms SHOULD document their default data model.
[This section is normative.]
Holds the representation of a state.
Name | Required | Attribute Constraints | Type | Default Value | Valid Values | Description |
---|---|---|---|---|---|---|
id | false | none | ID | none | A valid id as defined in [XML Schema] | The identifier for this state. See 3.14 IDs for details. |
initial | false | MUST NOT be specified in conjunction with the <initial> element. MUST NOT occur in atomic states. | IDREFS | none | A legal state specification. See 3.11 Legal State Configurations and Specifications for details. | The id of the default initial state (or states) for this state. |
[ Definition : An atomic state is a <state> that has no <state>, <parallel> or <final> children.]
[ Definition : A compound state is a <state> that has <state>, <parallel>, or <final> children (or a combination of these).]
[ Definition : The default initial state(s) of a compound state are those specified by the 'initial' attribute or <initial> element, if either is present. Otherwise it is the state's first child state in document order. ]
In a conformant SCXML document, a compound state MAY specify either an "initial" attribute or an <initial> element, but not both. See 3.6 <initial> for a discussion of the difference between the two notations.
[This section is normative.]
The <parallel> element encapsulates a set of child states which are simultaneously active when the parent element is active.
Name | Required | Attribute Constraints | Type | Default Value | Valid Values | Description |
---|---|---|---|---|---|---|
id | false | ID | none | A valid id as defined in [XML Schema] | The identifier for this state. See 3.14 IDs for details. |
[This section is normative.]
Transitions between states are triggered by events and conditionalized via guard conditions. They may contain executable content, which is executed when the transition is taken.
Name | Required | Attribute Constraints | Type | Default Value | Valid Values | Description |
---|---|---|---|---|---|---|
event | false | EventsTypes.datatype. | none | A space-separated list of event descriptors. See 3.12.1 Event Descriptors for details. |
A
list
of
designators
of
events
that
trigger
this
transition.
See
3.13
Selecting
and
Executing
Transitions
|
|
cond | false | Boolean expression | 'true' | Any boolean expression. See 5.9.1 Conditional Expressions for details. |
The
guard
condition
for
this
transition.
See
3.13
Selecting
and
Executing
Transitions
|
|
target | false | . | IDREFS | none | A legal state specification. See 3.11 Legal State Configurations and Specifications for details. |
The
identifier(s)
of
the
state
or
parallel
region
to
transition
to.
See
3.13
Selecting
and
Executing
Transitions
|
type | false | enum | "external" | "internal" "external" | Determines whether the source state is exited in transitions whose target state is a descendant of the source state. See 3.13 Selecting and Executing Transitions for details. |
A conformant SCXML document MUST specify at least one of 'event', 'cond' or 'target'. 3.13 Selecting and Executing Transitions contains more detail on the semantics of transitions.
[This section is normative.]
This element represents the default initial state for a complex <state> element (i.e. one containing child <state> or <parallel> elements.
[This section is normative.]
<final> represents a final state of an <scxml> or compound <state> element.
Name | Required | Attribute Constraints | Type | Default Value | Valid Values | Description |
---|---|---|---|---|---|---|
id | false | ID | none | A valid id as defined in [XML Schema] | The identifier for this state. See 3.14 IDs for details. |
When the state machine enters the <final> child of a <state> element, the SCXML Processor MUST generate the event done.state. id after completion of the <onentry> elements, where id is the id of the parent state. Immediately thereafter, if the parent <state> is a child of a <parallel> element, and all of the <parallel>'s other children are also in final states, the Processor MUST generate the event done.state. id where id is the id of the <parallel> element.
When
the
state
machine
reaches
the
<final>
child
of
an
<scxml>
element,
it
MUST
terminate.
See
A
D
Algorithm
for
SCXML
Interpretation
for
details.
If
the
SCXML
session
was
triggered
as
the
result
by
an
<invoke>
element
in
another
session,
the
SCXML
processor
MUST
generate
the
event
done.invoke.
id
after
termination
and
return
it
to
the
other
session,
where
id
is
the
unique
identifier
generated
when
the
<invoke>
element
was
executed.
See
6.4
<invoke>
for
details.
[This section is normative.]
A wrapper element containing executable content to be executed when the state is entered.
The children of the <onentry> handler consist of executable content as defined in 4 Executable Content .
The
SCXML
processor
MUST
execute
the
<onentry>
handlers
of
a
state
in
document
order
when
the
state
is
entered.
In
doing
so,
it
MUST
treat
each
handler
as
a
separate
block
of
executable
content.
See
A
Algorithm
for
SCXML
Interpretation
for
details.
[This section is normative.]
A wrapper element containing executable content to be executed when the state is exited.
The children of the <onexit> handler consist of executable content as defined in 4 Executable Content .
The
SCXML
processor
MUST
execute
the
<onexit>
handlers
of
a
state
in
document
order
when
the
state
is
exited.
In
doing
so,
it
MUST
treat
each
handler
as
a
separate
block
of
executable
content.
See
A
Algorithm
for
SCXML
Interpretation
for
details.
The <history> pseudo-state allows a state machine to remember its state configuration. A <transition> taking the <history> state as its target will return the state machine to this recorded configuration.
Name | Required | Attribute Constraints | Type | Default Value | Valid Values | Description |
---|---|---|---|---|---|---|
id | false | ID | none | A valid id as defined in [XML Schema] | Identifier for this pseudo-state. See 3.14 IDs for details. | |
type | false | enum | "shallow" | "deep" or "shallow" | Determines whether the active atomic substate(s) of the current state or only its immediate active substate(s) are recorded. |
If
the
'type'
of
a
<history>
element
is
"shallow",
the
SCXML
processor
MUST
record
the
immediately
active
children
of
its
parent
before
taking
any
transition
that
exits
the
parent.
If
the
'type'
of
a
<history>
element
is
"deep",
the
SCXML
processor
MUST
record
the
active
atomic
descendants
of
the
parent
before
taking
any
transition
that
exits
the
parent.
After
the
parent
state
has
been
visited
for
the
first
time,
for
each
<history>
element,
we
define
the
set
of
states
that
the
processor
has
recorded
to
be
the
'stored
state
configuration'
for
that
history
state.
We
also
define
the
states
specified
by
the
'target'
of
the
<history>
element's
<transition>
child
to
be
the
'default
stored
state
configuration'
for
that
element.
If
a
transition
is
executed
that
takes
the
<history>
state
as
its
target,
the
behavior
depends
on
whether
the
parent
state
has
been
visited
before.
If
it
has,
the
SCXML
processor
MUST
behave
as
if
the
transition
had
taken
the
stored
state
configuration
for
that
history
state
as
its
target.
If
it
has
not,
the
SCXML
processor
MUST
behave
as
if
the
transition
had
taken
the
default
stored
state
configuration
for
that
history
state
as
its
target.(Note
target.
The
Process
MUST
execute
any
executable
content
in
the
transition
after
the
parent
state's
onentry
handlers,
and,
in
the
case
where
the
history
pseudo-state
is
the
target
of
an
<initial>
transition,
the
executable
content
inside
the
<initial>
transition.
(Note
that
in
a
conformant
SCXML
document,
a
<state>
or
<parallel>
element
MAY
have
both
"deep"
and
"shallow"
<history>
children.)
[This section is normative.]
[ Definition : A <state> or <parallel> element is active if it has been entered by a transition and has not subsequently been exited.]
[ Definition : The state configuration of a state machine is the set of currently active states. ]
An SCXML document places the state machine in an initial state configuration at initialization time (via the 'initial' attribute of the <scxml> element). Each transition that the state machine takes thereafter places the state machine in another state configuration (which need not be distinct from the former one.) A conformant SCXML document MUST place the state machine only in legal state configurations, where a legal state configuration is one that meets the following conditions:
It follows from this definition that if a state machine is in more than one atomic state, the atomic states can be traced back through a chain of <state> or <parallel> ancestors to a single <parallel> ancestor.
The 'target' attribute of a <transition> (or the 'initial' attribute of a <state> or <scxml> element) do not in the general case specify a full legal state configuration since 1) they can contain <parallel> or non-atomic <state> elements 2) they do not contain the ancestors of the states in the list. We therefore define a legal state specification to be a set of states such that 1) no state is an ancestor of any other state on the list, and 2) a full legal state configuration results when all ancestors and default initial descendants have been added. (Note that the process of adding default initial descendants is recursive, since the 'initial' value may itself be non-atomic.) In a conformant SCXML document, the value of an 'initial' attribute or the 'target' of a <transition> MUST either be empty or contain a legal state specification.
In a conformant SCXML document, there is an additional requirement on the value of the 'initial' attribute of a <state> and on the 'target' of a <transition> inside an <initial> element: or <history> pseudo-state; all the states MUST be descendants of the containing <state> or <parallel> element.
[This section is normative.]
Events are one of the basic concepts in SCXML since they drive most transitions. The internal structure of events is platform-specific as long as the following external interface is observed:
For the most part, the set of events raised during the execution of an SCXML document is application-specific and generated under author control by use of the <raise> and <send> elements. However, certain events are mandatory and generated automatically by the interpreter. These are described in 3.12.3 List of Errors and Events . Platforms MAY extend the names of these automatically generated events by adding a suffix. For example, a platform could extend done.state. id with a timestamp suffix and generate done.state. id.timestamp instead. Because any prefix of done.state. id is also a prefix of done.state. id.timestamp , any transition that matches the former event will also match the latter.
Like an event name, an event descriptor is a series of alphanumeric characters segmented into tokens by the "." character. The 'event' attribute of a transition consists of one or more such event descriptors separated by spaces.
[ Definition : A transition matches an event if at least one of its event descriptors matches the event's name. ]
[ Definition : An event descriptor matches an event name if its string of tokens is an exact match or a prefix of the set of tokens in the event's name. In all cases, the token matching is case sensitive. ]
For example, a transition with an 'event' attribute of "error foo" will match event names "error", "error.send", "error.send.failed", etc. (or "foo", "foo.bar" etc.) but would not match events named "errors.my.custom", "errorhandler.mistake","errOr.send" or "foobar".
For compatibility with CCXML, and to make the prefix matching possibly more clear to a reader of the SCXML document, an event descriptor MAY also end with the wildcard '.*', which matches zero or more tokens at the end of the processed event's name. Note that a transition with 'event' of "error", one with "error.", and one with "error.*" are functionally equivalent since they are token prefixes of exactly the same set of event names.
An
event
designator
consisting
solely
of
"*"
can
be
used
as
a
wildcard
matching
any
sequence
of
tokens,
and
thus
any
event.
Note
that
this
is
different
from
a
transition
lacking
the
'event'
attribute
altogether.
Such
an
eventless
transition
does
not
match
any
event,
but
will
be
taken
whenever
its
'cond'
attribute
evaluates
to
'true'.
As
shown
in
A
D
Algorithm
for
SCXML
Interpretation
,
the
SCXML
interpreter
will
check
for
such
eventless
transitions
when
it
first
enters
a
state,
before
it
looks
for
transitions
driven
by
internal
or
external
events.
Once the SCXML processor has begun executing a well-formed SCXML document, it MUST signal any errors that occur by raising SCXML events whose names begin with 'error.'. the processor MUST place these events in the internal event queue and MUST process them like any other event. (Note in particular, they are not processed immediately if there are other events in the queue and they are ignored if no transition is found that matches them.) Two error events are defined in this specification: 'error.communication' and 'error.execution'. The former cover errors occurring while trying to communicate with external entities, such as those arising from <send> and <invoke>, while the latter category consists of errors internal to the execution of the document, such as those arising from expression evaluation.
The set of error events may be extended in future versions of this specification. However, the set of names beginning with 'error.platform' is reserved for platform- and application-specific errors. Therefore applications and platforms MAY extend the set of errors defined in this specification in two ways. First by adding a suffix to an error name defined in this specification, and second by using 'error.platform' with or without a suffix. In addition, platforms MAY include additional information about the nature of the error in the 'data' field of the event. See 5.10 System Variables for details.
Note however that authors can arrange for otherwise unhandled errors to cause the interpreter to exit by creating a transition with "event" attribute of 'error' and a target of any top-level final state (i.e. one that is a child of <scxml>). If such a transition T is placed in a state S, it will cause the state machine to terminate on any error that is raised in S or one of its substates and is not handled by another transition that is placed in a substate of S or in S and preceding T in document order.
The following events are generated automatically by the SCXML implementation under conditions defined elsewhere in this document.
Name | Description | Defined in | See also |
---|---|---|---|
done.state. id | Indicates that the state machine has entered a final substate of state id . | 3.7 <final> | 3.1 Introduction |
done.invoke. id | Indicates that the invoked process with invokeid id has completed processing. | 6.4 <invoke> |
3.7
<final>
,
exitInterpreter
procedure
in
|
error.communication | Indicates that an error has occurred while trying to communicate with an external entity. | 3.12.2 Errors |
6.2
<send>
,
|
error.execution | Indicates that an error internal to the execution of the document has occurred, such as one arising from expression evaluation. | 3.12.2 Errors |
4.6
<foreach>
,
5.4
<assign>
,
5.7
<param>
,
5.9.1
Conditional
Expressions
,
5.9.2
Location
Expressions
,
5.9.3
Legal
Data
Values
and
Value
Expressions
,
5.9.4
Errors
in
Expressions
,
5.10
System
Variables
,
6.2
<send>
,
|
error.platform | Indicates that a platform- or application-specific error has occurred. | 3.12.2 Errors |
[This section is normative.]
To simplify the following definitions, we introduce the event NULL. NULL has no name and is used only in these definitions. It never occurs in the event queues of an SCXML Processor. All other events have names and are distinct from NULL. (In effect, NULL is a pseudo-event that is used in these definitions as a trigger for eventless transitions.)
[ Definition : A transition T is enabled by named event E in atomic state S if a) T's source state is S or an ancestor of S, b) T matches E's name (see 3.12.1 Event Descriptors ) c) T lacks a 'cond' attribute or its 'cond' attribute evaluates to "true". A transition is enabled by NULL in atomic state S if a) T lacks an 'event' attribute b) T's source state is S or an ancestor of S c) T lacks an 'cond' attribute or its 'cond' attribute evaluates to "true". (Note that such a transition can never be enabled by any named event.)]
[
Definition
:
The
source
state
of
a
transition
is
the
<state>
or
<parallel>
element
that
it
occurs
in.
The
effective
target
state(s)
of
the
transition
is
the
state
or
set
of
states
specified
by
its
'target'
attribute.
attribute,
with
any
history
states
being
replaced
by
the
corresponding
stored
state
configuration
or
default
stored
state
configuration.
The
complete
target
set
of
a
transition
consists
of
all
the
states
that
will
be
active
after
the
transition
is
taken.
It
contains
the
effective
target
states
of
the
transition
plus
all
their
ancestors,
expanded
by
the
recursive
application
of
the
following
two
operations:
1)
if
any
<parallel>
element
is
a
member
of
the
set,
any
of
its
children
that
are
not
members
of
the
set
must
be
added
2)
if
any
compound
<state>
is
in
the
set
and
none
of
its
children
is
in
the
set,
its
default
initial
state(s)
are
added
to
the
set.
Any
state
whose
child(ren)
are
added
to
the
complete
target
set
by
clause
2
is
called
a
default
entry
state
.
]
[ Definition : The exit set of a transition in configuration C is the set of states that are exited when the transition is taken when the state machine is in C. If the transition does not contain a 'target', its exit set is empty. Otherwise (i.e., if the transition contains a 'target'), if its 'type' is "external", its exit set consists of all active states in C that are proper descendants of the Least Common Compound Ancestor (LCCA) of the source and target states. Otherwise, if the transition has 'type' "internal", its source state is a compound state, and all its target states are proper descendants of its source state, the exit set consists of all active states in C that are proper descendants of its source state. (If a transition has 'type' of "internal", but its source state is not compound or its target states are not all proper descendants of its source state, its exit set is defined as if it had 'type' of "external". The exit set of a set of transitions is the union of the exit sets of the individual transitions. ]
[
Definition
:
The
entry
set
of
a
transition
in
configuration
C
is
the
set
of
states
that
are
entered
when
the
transition
is
taken.
If
a
transition
does
not
contain
a
'target',
its
entry
set
is
empty.
Otherwise,
it
consists
of
all
members
of
the
transition's
complete
target
set
that
that
are
not
currently
active.
active
or
are
in
the
exit
set.
(Thus
the
entry
set
consists
of
all
members
of
the
transition's
complete
target
set
that
will
not
be
active
once
the
states
in
the
exit
set
have
been
exited.)
The
entry
set
of
a
set
of
transitions
is
the
union
of
the
transition
entry
sets
of
the
individual
transitions.]
[ Definition : A transition T is optimally enabled by event E in atomic state S if a) T is enabled by E in S and b) no transition that precedes T in document order in T's source state is enabled by E in S and c) no transition is enabled by E in S in any descendant of T's source state.]
[ Definition : Two transitions T1 and T2 conflict in state configuration C if their exit sets in C have a non-null intersection.]
N.B. If two transitions conflict, then taking them both may lead to an illegal configuration. Hence, only one of the transitions may safely be taken. In order to resolve conflicts between transitions, we assign priorities to transitions as follows: let transitions T1 and T2 conflict, where T1 is optimally enabled in atomic state S1, and T2 is optimally enabled in atomic state S2, where S1 and S2 are both active. We say that T1 has a higher priority than T2 if a) T1's source state is a descendant of T2's source state, or b) S1 precedes S2 in document order.
[ Definition : The optimal transition set enabled by event E in state configuration C is the largest set of transitions such that a) each transition in the set is optimally enabled by E in an atomic state in C b) no transition conflicts with another transition in the set c) there is no optimally enabled transition outside the set that has a higher priority than some member of the set. ]
[ Definition : A microstep consists of the execution of the transitions in an optimal enabled transition set.]
[ Definition : A macrostep is a series of one or more microsteps ending in a configuration where the internal event queue is empty and no transitions are enabled by NULL. ]
To execute a microstep, the SCXML Processor MUST execute the transitions in the corresponding optimal enabled transition set. To execute a set of transitions, the SCXML Processor MUST first exit all the states in the transitions' exit set in exit order . It MUST then execute the executable content contained in the transitions in document order. It MUST then enter the states in the transitions' entry set in entry order .
To exit a state, the SCXML Processor MUST execute the executable content in the state's <onexit> handler. Then it MUST cancel any ongoing invocations that were triggered by that state. Finally, the Processor MUST remove the state from the active state's list.
To enter a state, the SCXML Processor MUST add the state to the active state's list. Then it MUST execute the executable content in the state's <onentry> handler. If the state is a default entry state and has an <initial> child, the SCXML Processor MUST then execute the executable content in the <initial> child's <transition>.
At startup, the SCXML Processor MUST place the state machine in the configuration specified by the 'initial' attribute of the <scxml> element.
After entering the initial configuration, and after executing each microstep, the SCXML Processor MUST check the state configuration for <final> states that it has entered during the microstep. If it has entered a <final> state that is a child of <scxml>, it MUST halt processing. If it has entered a <final> state that is a child of a compound state, it MUST generate the event done.state. id , where id is the id of the compound state. If the compound state is itself the child of a <parallel> element, and all the <parallel> element's other children are in final states, the Processor MUST generate the event done.state. id , where id is the id of the <parallel> elements.
After checking the state configuration, the Processor MUST select the optimal transition set enabled by NULL in the current configuration. If the set is not empty, it MUST execute it as a microstep. If the set is empty, the Processor MUST remove events from the internal event queue until the queue is empty or it finds an event that enables a non-empty optimal transition set in the current configuration. If it finds such a set, the processor MUST then execute it as a microstep. (Otherwise the internal event queue is empty and the Processor has completed a macrostep.)
After completing a macrostep, the SCXML Processor MUST execute in document order the <invoke> handlers in all states that have been entered since the completion of the last macrostep. Then the Processor MUST remove events from the external event queue, waiting till events appear if necessary, until it finds one that enables a non-empty optimal transition set in the current configuration. The Processor MUST then execute that set as a microstep.
[This section is normative.]
In a conformant SCXML document, the values of all attributes of type "id" MUST be unique within the session. When such an attribute is defined to be optional and the author omits it, then, for elements other than <send> and <invoke>, the SCXML processor MUST generate a unique id automatically at document load time. (Note that Such system generated IDs cannot normally be referenced elsewhere in the document because they are not known to the author. In particular, a state with a system generated ID cannot be the target of a transition.) The ids for <send> and <invoke> are subtly different. In a conformant SCXML document, they MUST be unique within the session, but in the case where the author does not provide them, the processor MUST generate a new unique ID not at load time but each time the element is executed . Furthermore the attribute 'idlocation' can be used to capture this automatically generated id. Finally note that the automatically generated id for <invoke> has a special format. See 6.4.1 Attribute Details for details. The SCXML processor MAY generate all other ids in any format, as long as they are unique.
[This section is informative.]
Executable
content
allows
the
state
machine
to
do
things.
It
provides
the
hooks
that
allow
an
SCXML
session
to
modify
its
data
model
and
interact
with
external
entities.
Executable
content
consists
of
actions
that
are
performed
as
part
of
taking
transitions.
In
particular,
executable
content
occurs
inside
<onentry>
and
<onexit>
elements
as
well
as
inside
transitions.
When
the
state
machine
takes
a
transition,
it
executes
the
<onexit>
executable
content
in
the
states
it
is
leaving,
followed
by
the
content
in
the
transition,
followed
by
the
<onentry>
content
in
the
states
it
is
entering.
See
A
Algorithm
for
SCXML
Interpretation
for
details.
This standard defines elements of executable content which can raise events 4.2 <raise> , communicate with external entities 6.2 <send> , log information 4.7 <log> execute scripts 5.8 <script> and modify the data model 5.4 <assign> , as well as control constructs to conditionalize execution 4.3 <if> and to iterate over the items in a collection 4.6 <foreach> . In addition, SCXML implementations are allowed to define their own, platform-specific executable content (see 4.10 Extensibility of Executable Content ).
[This section is normative.]
The
<raise>
element
raises
an
event
in
the
current
SCXML
session.
Note
that
the
event
will
not
be
processed
until
the
current
block
of
executable
content
has
completed
and
all
events
that
are
already
in
the
internal
event
queue
have
been
processed.
For
example,
suppose
the
<raise>
element
occurs
first
in
the
<onentry>
handler
of
state
S
followed
by
executable
content
elements
ec1
and
ec2.
If
event
e1
is
already
in
the
internal
event
queue
when
S
is
entered,
the
event
generated
by
<raise>
will
not
be
processed
until
ec1
and
ec2
have
finished
execution
and
e1
has
been
processed.
For
details
of
event
processing,
see
A
Algorithm
for
SCXML
Interpretation
.
Name | Required | Attribute Constraints | Type | Default Value | Valid Values | Description |
---|---|---|---|---|---|---|
event | true | NMTOKEN | none | Specifies the name of the event. This will be matched against the 'event' attribute of transitions. |
The SCXML processor MUST place the event that is generated at the rear of the session's internal event queue.
[This section is normative.]
<if> is a container for conditionally executed elements.
Name | Required | Attribute Constraints | Type | Default Value | Valid Values | Description |
---|---|---|---|---|---|---|
cond | true | Conditional expression | none | A valid conditional expression | A boolean expression. See 5.9.1 Conditional Expressions for details. |
The behavior of <if> is defined in terms of partitions of executable content. The first partition consists of the executable content between the <if> and the first <elseif>, <else> or </if> tag. Each <elseif> tag defines a partition that extends from it to the next <elseif>, <else> or </if> tag. The <else> tag defines a partition that extends from it to the closing </if> tag. In a conformant SCXML document, a partition MAY be empty. In a conformant SCXML document, <else> MUST occur after all <elseif> tags.
When the <if> element is executed, the SCXML processor MUST execute the first partition in document order that is defined by a tag whose 'cond' attribute evaluates to true, if there is one. Otherwise, it MUST execute the partition defined by the <else> tag, if there is one. Otherwise it MUST NOT execute any of the executable content.
Here is an example:
<if cond="cond1"> <!-- selected when "cond1" is true --> <elseif cond="cond2"/> <!-- selected when "cond1" is false and "cond2" is true --> <elseif cond="cond3"/> <!-- selected when "cond1" and "cond2" are false and "cond3" is true --> <else/> <!-- selected when "cond1", "cond2", and "cond3" are false --> </if>
[This section is normative.]
[This section is normative.]
The <foreach> element allows an SCXML application to iterate through a collection in the data model and to execute the actions contained within it for each item in the collection.
Name | Required | Attribute Constraints | Type | Default Value | Valid Values | Description |
---|---|---|---|---|---|---|
array | true | Value expression | none | A value expression that evaluates to an iterable collection. | The <foreach> element will iterate over a shallow copy of this collection. | |
item | true | xsd:string | none | Any variable name that is valid in the specified data model. | A variable that stores a different item of the collection in each iteration of the loop. | |
index | false | xsd:string | none | Any variable name that is valid in the specified data model. | A variable that stores the current iteration index upon each iteration of the foreach loop. |
The children of <foreach> consist of one or more items of executable content. (Note that they are considered to be part of the same block of executable content as the parent <foreach> element.)
The SCXML processor MUST declare a new variable if the one specified by 'item' is not already defined. If 'index' is present, the SCXML processor MUST declare a new variable if the one specified by 'index' is not already defined. If 'array' does not evaluate to a legal iterable collection, or if 'item' does not specify a legal variable name, the SCXML processor MUST terminate execution of the <foreach> element and the block that contains it, and place the error error.execution on the internal event queue.
The SCXML processor MUST act as if it has made a shallow copy of the collection produced by the evaluation of 'array'. Specifically, modifications to the collection during the execution of <foreach> MUST NOT affect the iteration behavior. The SCXML processor MUST start with the first item in the collection and proceed to the last item in the iteration order that is defined for the collection. (This order depends on the data model in use. ) For each item in turn, the processor MUST assign it to the item variable. (Note that the assigned value MAY be null or undefined if the collection contains a null or undefined item.) After making the assignment, the SCXML processor MUST evaluate its child executable content. It MUST then proceed to the next item in iteration order. If the evaluation of any child element causes an error, the processor MUST cease execution of the <foreach> element and the block that contains it. (Note that SCXML does not provide break functionality to interrupt <foreach>, however targetless and/or eventless transitions can provide sophisticated iterative behavior within the SCXML application itself.)
[This section is normative.]
Name | Required | Attribute Constraints | Type | Default Value | Valid Values | Description |
---|---|---|---|---|---|---|
label | false | string | empty string | A character string with an implementation-dependent interpretation. It is intended to provide meta-data about the log string specified by 'expr'. | ||
expr | false | Value expression | none | An expression returning the value to be logged. See 5.9.3 Legal Data Values and Value Expressions for details. The nature of the logging mechanism is implementation-dependent. For example, the SCXML processor may convert this value to a convenient format before logging it. |
The manner in which the message is displayed or logged is platform-dependent. The SCXML processor MUST ensure that <log> has no side-effects on document interpretation.
[This section is normative.]
The following elements of executable content are defined elsewhere in this specification. They MAY occur wherever executable content is allowed and MUST NOT occur anyplace else.
[This section is normative.]
Wherever executable content is permitted, an arbitrary number of elements MAY occur. Such a sequence of elements of executable content is called a block. For example, if transition t takes the state machine from atomic state S1 to atomic state S2, there are three blocks of executable content executed: the one in the <onexit> handler of S1, the one inside t, and the one inside the <onentry> handler of S2. The SCXML processor MUST execute the elements of a block in document order. If the processing of an element causes an error to be raised, the processor MUST NOT process the remaining elements of the block. (The execution of other blocks of executable content is not affected.)
Events
raised
during
the
processing
of
executable
content
are
treated
like
any
other
events.
Note
in
particular,
that
error
events
will
not
be
removed
from
the
queue
and
processed
until
all
events
preceding
them
in
the
queue
have
been
processed.
See
3.12.2
Errors
and
A
Algorithm
for
SCXML
Interpretation
.
for
details.
[This section is normative.]
Implementations MAY provide additional executable content corresponding to special features of their implementations. The functionality of such platform-specific content is not restricted, except that it MUST NOT cause transitions or any form of change of state (except indirectly, by raising events that trigger transitions). Note that SCXML treats the executable content triggered by a transition as a single blocking operation and that no events are processed until all the executable content has completed. For example, when taking a transition into state S, the SCXML processor will not process any events or take any transitions until all <onentry> handlers in S have finished. It is thus important that all executable content, including platform-specific extensions, execute swiftly.
In a conformant SCXML document any extensions to executable content MUST NOT be defined the 'scxml' namespace. (Note that the schema E Schema allows elements from arbitrary namespaces inside blocks of executable content.) The following example shows the incorporation of CCXML functionality (see [CCXML 1.0] ) into SCXML. In particular an <accept> element in the 'ccxml' namespace is invoked as executable content inside a transition.
<transition event="ccxml:connection.alerting"> <ccxml:accept connectionid="_event.data.connectionid"/> </transition>
This
markup
is
legal
on
any
SCXML
interpreter,
but
the
behavior
of
<accept>
element
is
platform-dependent.
See
B.2
A.2
Conforming
Processors
for
details.
A general method for implementing extensions using the <send> element is presented in G.7 Custom Action Elements .
[This section is informative.]
The Data Model offers the capability of storing, reading, and modifying a set of data that is internal to the state machine. This specification does not mandate any specific data model, but instead defines a set of abstract capabilities that can be realized by various languages, such as ECMAScript or XML/XPath. Implementations may choose the set of data models that they support. In addition to the underlying data structure, the data model defines a set of expressions as described in 5.9 Expressions . These expressions are used to refer to specific locations in the data model, to compute values to assign to those locations, and to evaluate boolean conditions. Finally, the data model includes a set of system variables, as defined in 5.10 System Variables , which are automatically maintained by the SCXML processor.
The data model is defined via the 5.2 <datamodel> element, which contains zero or more 5.3 <data> elements, each of which defines a single data element and assigns an initial value to it. These values may be specified in-line or loaded from an external source. They can then be updated via the 5.4 <assign> element. The 5.5 <donedata> , 5.6 <content> , and 5.7 <param> elements can be used to incorporate data into communications with external entities. Finally, the 5.8 <script> element permits the incorporation of a scripting language.
The
interpretation
of
these
elements
depends
on
the
data
model
in
question,
and
not
all
elements
are
supported
in
all
data
models.
For
the
details
of
specific
data
models,
see
C
B
Data
Models
.
[This section is normative.]
<datamodel> is a 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.
[This section is normative.]
The <data> element is used to declare and populate portions of the data model.
Name | Required | Attribute Constraints | Type | Default Value | Valid Values | Description |
---|---|---|---|---|---|---|
id | true | ID | none | The name of the data item. See 3.14 IDs for details. | ||
src | false | URI | none | Gives the location from which the data object should be fetched. See 5.9.3 Legal Data Values and Value Expressions for details. | ||
expr | false | Expression | none | Any valid value expression | Evaluates to provide the value of the data item. See 5.9.3 Legal Data Values and Value Expressions for details. |
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.
The SCXML Processor MUST use any values provided by the environment at instantiation time in place of those contained in the top-level <data> elements. (Top-level data elements are those that are children of the <datamodel > element that is a child of <scxml>). The manner in which the environment specifies these overriding values is platform-dependent.
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.
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.
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>.
Note
that
in
the
latter
two
cases,
the
interpretation
of
the
object
or
content
will
depend
on
the
data
model.
See
C
B
Data
Models
for
details.
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.
Implementations MAY predeclare and predefine variables in the data model. However, conformant SCXML implementations SHOULD NOT assume the existence of any predeclared or predefined variables (i.e., ones not explicitly defined by <data>).
Note that this specification does not define any way to modify the data model except by<assign>, <finalize>, and possibly platform-specific elements of executable content. In particular, no means is defined for external entities to modify the data model. In this sense the data model is local to the SCXML session and the SCXML Processor checks for eventless transitions (i.e. ones that are triggered based only on the state of the data model) only after entering a state or processing an event. However in some deployments it may be possible for external entities to modify the data model. For example, if SCXML is implemented in JavaScript in a browser, the scope of a document's data model is always accessible through the main window object and thus JavaScript code elsewhere in the window can modify the data model independent of the SCXML interpretation algorithm. Such a situation can lead to race conditions and unpredictable behavior
Authors control when the initial values are assigned to the data elements by means of the 'binding' attribute on the <scxml> element. When 'binding' is assigned the value "early" (the default), the SCXML Processor MUST create all data elements and assign their initial values at document initialization time. When 'binding' 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. (The value of the data element between the time it is created and the time its parent state is first entered will depend on the data language chosen. The initial value specified by 'expr', 'src' or in-line content will be assigned to the data element even if the element already has a non-null value when the parent state is first entered.)
[This section is normative.]
The <assign> element is used to modify the data model.
Name | Required | Attribute Constraints | Type | Default Value | Valid Values | Description |
---|---|---|---|---|---|---|
location | true | path expression | none | Any valid location expression. | The location in the data model into which to insert the new value. See 5.9.2 Location Expressions for details. | |
expr | false | This attribute must not occur in an <assign> element that has children. | value expression | none | Any valid value expression | An expression returning the value to be assigned. See 5.9.3 Legal Data Values and Value Expressions for details. |
The children of the <assign>element provide an in-line specification of the legal data value (see 5.9.3 Legal Data Values and Value Expressions ) to be inserted into the data model at the specified location.
A conformant SCXML document MUST specify either "expr" or children of <assign>, but not both.
Assignment
to
a
data
model
is
done
by
using
a
location
expression
to
denote
the
part
of
the
data
model
where
the
insertion
is
to
be
made.
If
the
location
expression
does
not
denote
a
valid
location
in
the
data
model
or
if
the
value
specified
(by
'expr'
or
children)
is
not
a
legal
value
for
the
location
specified,
the
SCXML
Processor
MUST
place
the
error
'error.execution'
in
the
internal
event
queue.
Otherwise,
the
SCXML
Processor
MUST
place
the
specified
value
at
the
specified
location.
Note
that
the
nature
of
the
insertion
and
the
definition
of
a
legal
value
depends
on
the
data
model
language
used.
Note
also
that
data
models
MAY
support
additional
attributes
for
<assign>
beyond
those
specified
here.
See
C
B
Data
Models
for
details.
[This section is normative.]
A wrapper element holding data to be returned when a <final> state is entered.
A conformant SCXML document MUST specify either a single <content> element or one or more <param> elements as children of <donedata>, but not both.
In
cases
where
the
SCXML
Processor
generates
a
'done'
event
upon
entry
into
the
final
state,
it
MUST
evaluate
the
<donedata>
elements
<param>
or
<content>
children
and
place
the
resulting
data
in
the
_event.data
field.
The
exact
format
of
that
data
will
be
determined
by
the
data
model
(see
C
B
Data
Models
for
details).
In
other
cases
(namely
when
the
<final>
element
is
a
child
of
<scxml>
and
the
state
machine
has
not
been
triggered
by
<invoke>),
the
SCXML
Processor
SHOULD
return
the
data
to
the
environment
in
an
implementation-dependent
manner.
[This section is normative.]
A container element holding data to be passed to an external service.
Name | Required | Attribute Constraints | Type | Default Value | Valid Values | Description |
---|---|---|---|---|---|---|
expr | false | must not occur with child content | Value expression | none | Any valid value expression | A value expression. See 5.9.3 Legal Data Values and Value Expressions for details. |
A conformant SCXML document MUST NOT specify both the 'expr' attribute and child content. When present, the children of <content> MAY consist of text, XML from any namespace, or a mixture of both.
The
use
of
the
<content>
element
depends
on
the
context
in
which
it
occurs.
See
5.5
<donedata>
,
6.2
<send>
and
6.4
<invoke>
for
details.
When
the
SCXML
Processor
evaluates
the
<content>
element,
if
the
'expr'
value
expression
is
present,
the
Processor
MUST
evaluate
it
and
use
the
result
as
the
output
of
the
<content>
element.
If
the
evaluation
of
'expr'
produces
an
error,
the
Processor
MUST
place
error.execution
in
the
internal
event
queue
and
use
the
empty
string
as
the
value
of
the
<content>
element.
If
the
'expr'
attribute
is
not
present,
the
Processor
MUST
use
the
children
of
<content>
as
the
output.
The
interpretation
of
the
output
of
the
<content>
element
depends
on
the
data
model.
See
C
B
Data
Models
for
details.
For
the
use
of
namespaces
inside
<content>,
see
G.6
Inline
Content
and
Namespaces
.
[This section is normative.]
The <param> tag provides a general way of identifying a key and a dynamically calculated value which can be passed to an external service or included in an event.
Name | Required | Attribute Constraints | Type | Default Value | Valid Values | Description |
---|---|---|---|---|---|---|
name | true | NMTOKEN | none | A string literal | The name of the key. | |
expr | false | May not occur with 'location' | value expression | none | Valid value expression | A value expression (see 5.9.3 Legal Data Values and Value Expressions ) that is evaluated to provide the value. |
location | false | May not occur with 'expr' | location expression | none | Valid location expression | A location expression (see 5.9.2 Location Expressions ) that specifies the location in the datamodel to use as the value. |
A conformant SCXML document MUST specify either the 'expr' attribute of <param> or the 'location' attribute, but MUST NOT specify both. If the 'location' attribute does not refer to a valid location in the data model, or if the evaluation of the 'expr' produces an error, the SCXML Processor MUST place the error 'error.execution' on the internal event queue and MUST ignore the name and value. Otherwise the use of the name and value depends on the context in which the <param> element occurs. See 5.5 <donedata> , 6.2 <send> and 6.4 <invoke> for details.
[This section is normative.]
The <script> element adds scripting capability to the state machine.
Name | Required | Attribute Constraints | Type | Default Value | Valid Values | Description |
---|---|---|---|---|---|---|
src | false | May not occur if the element has children. | none | A valid URI | Gives the location from which the script should be downloaded. |
A conformant SCXML document MUST specify either the 'src' attribute or child content, but not both. If 'src' is specified, the SCXML Processor MUST download the script from the specified location at load time. If the script can not be downloaded within a platform-specific timeout interval, the document is considered non-conformant, and the platform MUST reject it.
The SCXML Processor MUST evaluate any <script> element that is a child of <scxml> at document load time. It MUST evaluate all other <script> elements as part of normal executable content evaluation.
In a conformant SCXML document, the name of any script variable MAY be used as a location expression (see 5.9.2 Location Expressions ).
For
an
example
of
a
data
model
incorporating
scripting,
see
C.2
B.2
The
ECMAScript
Data
Model
.
[This section is normative.]
SCXML contains three types of expressions, as described below. Different data models will support different languages for these expression types, but certain properties of the expressions are constant across languages and are defined here.
When "late" data binding is used, accessing data substructure in expressions before the corresponding <data> element is loaded MUST yield the same execution-time behavior as accessing non-existent data substructure in a loaded <data> instance. Such behavior is defined by the data expression language in use.
Conditional expressions are used inside the 'cond' attribute of <transition>, <if> and <elseif>. If a conditional expression cannot be evaluated as a boolean value ('true' or 'false') or if its evaluation causes an error, the SCXML Processor MUST treat the expression as if it evaluated to 'false' and MUST place the error 'error.execution' in the internal event queue. The set of operators in conditional expressions varies depending on the data model, but all data models MUST support the 'In()' predicate, which takes a state ID as its argument and returns true if the state machine is in that state. This predicate allows coordination among parallel regions. Conditional expressions in conformant SCXML documents SHOULD NOT have side effects.
Location
expressions
are
used
to
specify
a
location
in
the
data
model
as
part
of
the
<assign>element.
The
exact
nature
of
a
location
depends
on
the
data
model.
For
example,
in
the
XPath
data
model
(
C.3
B.3
The
XPath
Data
Model
),
the
underlying
data
structure
is
an
XML
document
consisting
of
a
root
node
and
children
which
are
specified
by
individual
<data>
elements.
The
set
of
valid
locations
consists
of
the
nodes
and
nodesets
in
this
document.
If
a
location
expression
cannot
be
evaluated
to
yield
a
valid
location,
the
SCXML
processor
MUST
place
the
error
'error.execution'
in
the
internal
event
queue.
A
data
model
definition
contains
a
specification
of
the
underlying
data
structure.
For
example,
the
XPath
data
model
(
C.3
B.3
The
XPath
Data
Model
)
defines
the
data
structure
to
be
an
XML
document.
Such
a
specification
of
the
data
structure
implicitly
defines
a
set
of
"legal
data
values",
namely
the
objects
that
can
be
part
of
such
a
data
structure.
For
an
XML
data
model,
the
set
of
legal
data
values
consists
of
XML
data
nodes
and
descendants,
plus
strings
(as
values
of
attributes
or
text
children).
In
conjunction
with
this,
the
data
model
definition
specifies
a
set
of
value
expressions
which
can
be
evaluated
at
runtime
to
return
legal
data
values.
If
a
value
expression
does
not
return
a
legal
data
value,
the
SCXML
Processor
MUST
place
the
error
'error.execution'
in
the
internal
event
queue.
The
SCXML
Processor
MAY
reject
documents
containing
syntactically
ill-formed
expressions
at
document
load
time,
or
it
MAY
wait
and
place
'error.execution'
in
the
internal
event
queue
at
runtime
when
the
expressions
are
evaluated.
If
the
processor
waits
until
it
evaluates
the
expressions
at
runtime
to
raise
errors,
it
MUST
raise
errors
caused
by
expressions
returning
illegal
values
at
the
points
at
which
A
Algorithm
for
SCXML
Interpretation
indicates
that
the
expressions
are
to
be
evaluated.
Note
that
this
requirement
holds
even
if
the
implementation
is
optimizing
expression
evaluation.
[This section is normative.]
The SCXML Processor MUST maintain a protected portion of the data model containing information that can be useful to applications. We refer to the items in this special part of the data model as 'system variables'. Implementations MUST provide the following system variables, and MAY support others.
The set of system variables may be expanded in future versions of this specification. Variable names beginning with '_' are reserved for system use. A conformant SCXML document MUST NOT contain ids beginning with '_' in the <data> element. Platforms MUST place all platform-specific system variables under the '_x' root.
The
concrete
realization
of
these
variables
in
a
specific
data
model
depends
on
the
language
used.
For
the
exact
location
of
these
variables
in
an
XML
data
model,
see
C.3
B.3
The
XPath
Data
Model
.
The
Processor
MUST
cause
any
attempt
to
change
the
value
of
a
system
variable
to
fail
and
MUST
place
the
error
'error.execution'
on
the
internal
event
queue
when
such
an
attempt
is
made.
Events have an internal structure which is reflected in the _event variable. This variable can be accessed to condition transitions (via boolean expressions in the 'cond' attribute) or to update the data model (via <assign>), etc.
The SCXML Processor MUST ensure that the following fields are present in all events, whether internal or external.
[This section is informative.]
The External Communications capability allows an SCXML session to send and receive events from external entities, and to invoke external services. 6.2 <send> provides "fire and forget" capability to deliver events and data to any destination, including other SCXML sessions. The 'delay' attribute allows for deferred event delivery and can be used to implement a timer. The details of event transport as well as the format of the event and data are determined by the Event I/O Processor selected. Each implementation will support one or more such processor, and the author of the SCXML markup can choose the one that is appropriate for the type of endpoint he is trying to reach.
6.4 <invoke> offers a more tightly coupled form of communication, specifically the ability to trigger a platform-defined service and pass data to it. It and its child <finalize> are useful in states that model the behavior of an external service. The <invoke> element is executed after the state's <onentry> element and causes an instance of the external service to be created. The <param> and <content> elements and the 'namelist' attribute can be used to pass data to the service. Any events that are received by the state machine from the invoked component during the invocation are preprocessed by the <finalize> handler before transitions are selected. The <finalize> code is used to normalize the form of the returned data and to update the data model before the transitions' "event" and "cond" clauses are evaluated.
When parallel states invoke the same external service concurrently, separate instances of the external service will be started. They can be distinguished by ids which are associated with them. Similarly, the ids contained in the events returned from the external services can be used to determine which events are responses to which invocation. Each event that is returned will be processed only by the <finalize> in the state that invoked it, but that event is then processed like any other event that the state machine receives. The finalize code can thus be thought of as a preprocessing stage that applies before the event is added to the event queue. Note that the event will be passed to all parallel states to check for transitions.
Since
an
invocation
will
be
canceled
when
the
state
machine
leaves
the
invoking
state,
it
does
not
make
sense
to
start
an
invocation
in
a
state
that
will
be
exited
immediately.
Therefore
the
<invoke>
element
is
executed
upon
entry
into
the
state,
but
only
after
checking
for
eventless
transitions
and
transitions
driven
by
pending
internal
events.
If
any
such
enabled
transition
is
found
,
it
is
taken
and
the
state
is
exited
immediately,
without
triggering
the
invocation.
Thus
invocations
are
triggered
only
when
the
state
machine
has
reached
a
stable
configuration,
i.e.,
one
that
it
will
be
staying
in
while
it
waits
for
external
events.
(See
A
Algorithm
for
SCXML
Interpretation
for
details.)
[This section is normative.]
<send> is used to send events and data to external systems, including external SCXML Interpreters, or to raise events in the current SCXML session.
Name | Required | Attribute Constraints | Type | Default Value | Valid Values | Description |
---|---|---|---|---|---|---|
event | false | Must not occur with 'eventexpr'. If the type is http://www.w3.org/TR/scxml/#SCXMLEventProcessor, either this attribute or 'eventexpr' must be present. | EventType.datatype | none | A string indicating the name of message being generated. See E Schema for details on the data type. | |
eventexpr | false | Must not occur with 'event'. If the type is http://www.w3.org/TR/scxml/#SCXMLEventProcessor, either this attribute or 'event' must be present. | Value expression | none | A dynamic alternative to 'event'. If this attribute is present, the SCXML Processor MUST evaluate it when the parent <send> element is evaluated and treat the result as if it had been entered as the value of 'event'. | |
target | false | Must not occur with 'targetexpr' | URI | none | A valid target URI | The unique identifier of the message target that the platform should send the event to. See 6.2.4 The Target of Send for details. |
targetexpr | false | Must not occur with 'target' | Value expression | none | An expression evaluating to a valid target URI | A dynamic alternative to 'target'. If this attribute is present, the SCXML Processor MUST evaluate it when the parent <send> element is evaluated and treat the result as if it had been entered as the value of 'target'. |
type | false | Must not occur with 'typeexpr' | URI | none | The URI that identifies the transport mechanism for the message. See 6.2.5 The Type of Send for details. | |
typeexpr | false | Must not occur with 'type' | value expression | none | A dynamic alternative to 'type'. If this attribute is present, the SCXML Processor MUST evaluate it when the parent <send> element is evaluated and treat the result as if it had been entered as the value of 'type'. | |
id | false | Must not occur with 'idlocation'. | xml:ID | none | Any valid token | A string literal to be used as the identifier for this instance of <send>. See 3.14 IDs for details. |
idlocation | false | Must not occur with 'id'. | Location expression | none | Any valid location expression | Any location expression evaluating to a data model location in which a system-generated id can be stored. See below for details. |
delay | false | Must not occur with 'delayexpr' or when the attribute 'target' has the value "_internal". | Duration.datatype | None | A time designation as defined in CSS2 [CSS2] format | Indicates how long the processor should wait before dispatching the message. See E Schema for details on the data type. |
delayexpr | false | Must not occur with 'delay' or when the attribute 'target' has the value "_internal". | Value expression | None | A value expression which returns a time designation as defined in CSS2 [CSS2] format | A dynamic alternative to 'delay'. If this attribute is present, the SCXML Processor MUST evaluate it when the parent <send> element is evaluated and treat the result as if it had been entered as the value of 'delay'. |
namelist | false | Must not be specified in conjunction with <content> element. | List of location expressions | none | List of data model locations | A space-separated list of one or more data model locations to be included as attribute/value pairs with the message. (The name of the location is the attribute and the value stored at the location is the value.) See 5.9.2 Location Expressions for details. |
A conformant SCXML document MUST specify exactly one of 'event', 'eventexpr' and <content>. A conformant document MUST NOT specify "namelist" or <param> with <content>.
The SCXML Processor MUST include all attributes and values provided by <param> or 'namelist' even if duplicates occur.
If 'idlocation' is present, the SCXML Processor MUST generate an id when the parent <send> element is evaluated and store it in this location. See 3.14 IDs for details.
If
a
delay
is
specified
via
'delay'
or
'delayexpr',
the
SCXML
Processor
MUST
interpret
the
character
string
as
a
time
interval.
It
MUST
dispatch
the
message
only
when
the
delay
interval
elapses.
(Note
that
the
evaluation
of
the
send
tag
will
return
immediately.)
The
Processor
MUST
evaluate
all
arguments
to
<send>
when
the
<send>
element
is
evaluated,
and
not
when
the
message
is
actually
dispatched.
If
the
evaluation
of
<send>'s
arguments
produces
an
error,
the
Processor
MUST
discard
the
message
without
attempting
to
deliver
it.
If
the
SCXML
session
terminates
before
the
delay
interval
has
elapsed,
the
SCXML
Processor
MUST
discard
the
message
without
attempting
to
deliver
it.
The target of the <send> operation specifies the destination of the event. The target is defined by either the 'target' or the 'targetexpr' attribute. In most cases, the format of the target depends on the type of the target (for example a SIP URL for SIP-INFO messages or a HTTP URL for Web Services). If the value of the 'target' or 'targetexpr' attribute is not supported or invalid, the Processor MUST place the error error.execution on the internal event queue. If it is unable to dispatch the message, the Processor MUST place the error error.communication on the internal event queue.
The type of the <send> operation specifies the method that the SCXML processor MUST use to deliver the message to its target. A conformant SCXML document MAY use either the 'type' or the 'typeexpr' attribute to define the type. If neither the 'type' nor the 'typeexpr' is defined, the SCXML Processor MUST assume the default value of http://www.w3.org/TR/scxml/#SCXMLEventProcessor. If the SCXML Processor does not support the type that is specified, it MUST place the event error.execution on the internal event queue.
SCXML Processors MUST support the following type:
Value | Details |
---|---|
http://www.w3.org/TR/scxml/#SCXMLEventProcessor | Target is an SCXML session. The transport mechanism is platform-specific. |
For
details
on
the
http://www.w3.org/TR/scxml/#SCXMLEventProcessor
type,
see
D.1
C.1
SCXML
Event
I/O
Processor
.
Support for HTTP POST is optional, however Processors that support it must use the following value for the "type" attribute:
Value | Details |
---|---|
http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor | Target is a URL. Data is sent via HTTP POST |
For
details
on
the
http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor
type,
see
D.2
C.2
Basic
HTTP
Event
I/O
Processor
.
Support for DOM event delivery is optional, however Processors that support it must use the following value for the "type" attribute:
Value | Details |
---|---|
http://www.w3.org/TR/scxml/#DOMEventProcessor | Target is a node in the current document, which may contain markup from multiple namespaces. A DOM event will be targeted at that node. |
For
details
on
the
http://www.w3.org/TR/scxml/#DOMEventProcessor
type,
see
D.3
C.3
DOM
Event
I/O
Processor
.
Processors MAY support other types such as web-services, SIP or basic HTTP GET. When they do so, they SHOULD assign such types the URI of the description of the relevant Event I/O Processor. Processors MAY define short form notations as an authoring convenience (e.g., "scxml" as equivalent to http://www.w3.org/TR/scxml/#SCXMLEventProcessor).
The sending SCXML Interpreter MUST not alter the content of the <send> and MUST include it in the message that it sends to the destination specified in the target attribute of <send>.
Note that the document author can specify the message content in one of two mutually exclusive ways:
<datamodel> <data id="target" expr="'tel:+18005551212'"/> <data id="content" expr="'http://www.example.com/mycontent.txt'"/> </datamodel> ... <send target="target" type="x-messaging" event="fax.SEND" namelist="content"/>
<send target="csta://csta-server.example.com/" type="x-csta"> <content> <csta:MakeCall> <csta:callingDevice>22343</callingDevice> <csta:calledDirectoryNumber>18005551212</csta:calledDirectoryNumber> </csta:MakeCall> </content> </send>
Note that the absence of any error events does not mean that the event was successfully delivered to its target, but only that the platform was able to dispatch the event.
[This section is normative.]
The <cancel> element is used to cancel a delayed <send> event. The SCXML Processor MUST NOT allow <cancel> to affect events that were not raised in the same session. The Processor SHOULD make its best attempt to cancel all delayed events with the specified id. Note, however, that it can not be guaranteed to succeed, for example if the event has already been delivered by the time the <cancel> tag executes.
Name | Required | Attribute Constraints | Type | Default Value | Valid Values | Description |
---|---|---|---|---|---|---|
sendid | false | Must not occur with sendidexpr. | IDREF | none | The sendid of a delayed event | The ID of the event(s) to be cancelled. If multiple delayed events have this sendid, the Processor will cancel them all. |
sendidexpr | false | Must not occur with sendid. | Value Expression | none | Any expression that evaluates to the ID of a delayed event | A dynamic alternative to 'sendid'. If this attribute is present, the SCXML Processor MUST evaluate it when the parent <cancel> element is evaluated and treat the result as if it had been entered as the value of 'sendid'. |
A conformant SCXML document MUST specify exactly one of sendid or sendidexpr.
[This section is normative.]
The <invoke> element is used to create an instance of an external service.
Name | Required | Attribute Constraints | Type | Default Value | Valid Values | Description |
---|---|---|---|---|---|---|
type | false | Must not occur with the 'typeexpr' attribute. | URI | none | http://www.w3.org/TR/scxml/, http://www.w3.org/TR/ccxml/, http://www.w3.org/TR/voicexml30/, http://www.w3.org/TR/voicexml21/ plus other platform-specific values. | A URI specifying the type of the external service. See below for details. |
typeexpr | false | Must not occur with the 'type' attribute. | value expression | none | Any value expression that evaluates to a URI that would be a valid value for 'type'. | A dynamic alternative to 'type'. If this attribute is present, the SCXML Processor MUST evaluate it when the parent <invoke> element is evaluated and treat the result as if it had been entered as the value of 'type'. |
src | false | Must not occur with the 'srcexpr' attribute or the <content> element. | URI | None | Any URI. | A URI to be passed to the external service. See below for details. |
srcexpr | false | Must not occur with the 'src' attribute or the <content> element. | Value expression | None | Any expression evaluating to a valid URI. | A dynamic alternative to 'src'. If this attribute is present, the SCXML Processor MUST evaluate it when the parent <invoke> element is evaluated and treat the result as if it had been entered as the value of 'src'. |
id | false | Must not occur with the 'idlocation' attribute. | ID | none | Any valid token | A string literal to be used as the identifier for this instance of <invoke>. See 3.14 IDs for details. |
idlocation | false | Must not occur with the 'id' attribute. | Location expression | none | Any valid location expression | Any data model expression evaluating to a data model location. See 5.9.2 Location Expressions for details. |
namelist | false | Must not occur with the <param> element. | List of location expressions | none | List of data model locations | A space-separated list of one or more data model locations to be included as attribute/value pairs with the message. (The name of the location is the attribute and the value stored at the location is the value.) See 6.4.4 Data Sharing and 5.9.2 Location Expressions for details. |
autoforward | false | boolean | false | true or false | A flag indicating whether to forward events to the invoked process. See below for details. |
Platforms MUST support http://www.w3.org/TR/scxml/ as a value for the 'type' attribute. Platforms MAY support http://www.w3.org/TR/voicexml21/, which indicates a VoiceXML 2.1 interpreter, http://www.w3.org/TR/voicexml30/, which indicates a VoiceXML 3.x interpreter, and http://www.w3.org/TR/ccxml/, which indicates a CCXML 1.0 interpreter. Platforms MAY support additional values, but they SHOULD assign them the URI of a description of the relevant service. Processors MAY define short form notations as an authoring convenience (e.g., "scxml" as equivalent to http://www.w3.org/TR/scxml/).
A conformant SCXML document MAY specify either the 'id' or 'idlocation' attribute, but MUST NOT specify both. If the 'idlocation' attribute is present, the SCXML Processor MUST generate an id automatically when the <invoke> element is evaluated and store it in the location specified by 'idlocation'. (In the rest of this document, we will refer to this identifier as the "invokeid", regardless of whether it is specified by the author or generated by the platform). The automatically generated identifier MUST have the form stateid.platformid , where stateid is the id of the state containing this element and platformid is automatically generated. platformid MUST be unique within the current session.
When the <invoke> element is executed, if the evaluation of its arguments produces an error, the SCXML Processor MUST terminate the processing of the element without further action. Otherwise the Processor MUST start a new logical instance of the external service specified in 'type' or 'typeexpr', passing it the URL specified by 'src' or the data specified by <content>, or <param>. The service instance MAY be local or remote. In addition to the explicit arguments, the Processor MUST keep track of the unique invokeid and ensure that it is included in all events that the invoked service returns to the invoking session.
When
the
'autoforward'
attribute
is
set
to
true,
the
SCXML
Processor
MUST
send
an
exact
copy
of
every
external
event
it
receives
to
the
invoked
process.
All
the
fields
specified
in
5.10.1
The
Internal
Structure
of
Events
MUST
have
the
same
values
in
the
forwarded
copy
of
the
event.
The
SCXML
Processor
MUST
forward
the
event
at
the
point
at
which
it
removes
it
from
the
external
event
queue
of
the
invoking
session
for
processing.
See
A
Algorithm
for
SCXML
Interpretation
for
details.
The external service MAY return multiple events while it is processing. If there is a <finalize> handler in the instance of <invoke> that created the service that generated the event, the SCXML Processor MUST execute the code in that <finalize> handler right before it removes the event from the event queue for processing. It MUST NOT execute the <finalize> handler in any other instance of <invoke>. Once the external service has finished processing it MUST return a special event 'done.invoke. id ' to the external event queue of the invoking process, where id is the invokeid for the corresponding <invoke> element. The external service MUST NOT generate any other events after this done event. If the invoking session takes a transition out of the state containing the <invoke> before it receives the 'done.invoke. id ' event, the SCXML Processor MUST automatically cancel the invoked component and stop its processing. The cancel operation MUST act as if it were the final <onexit> handler in the invoking state.
Invoked services of type http://www.w3.org/TR/scxml/, http://www.w3.org/TR/ccxml/, http://www.w3.org/TR/voicexml30/, or http://www.w3.org/TR/voicexml21/ MUST interpret values specified by the <content> element or 'src' attribute as markup to be executed. Similarly, they MUST interpret values specified by <param> element or 'namelist' attribute as values that are to be injected into their data models. For targets of other invoked service types, the interpretation of <param> and <content> elements and the 'src' and 'namelist' attributes is platform-specific. However, these services MUST treat values specified by <param> and namelist identically. They MUST also treat values specified by 'src' and <content> identically.
The implementation of <invoke>, including communication between parent and child processes, is platform-specific, but the following requirements hold in the case where the invoked process is itself an SCXML session:
[This section is informative.]
The invoked external resource is logically separate from the state machine that invokes it and does not share data with it unless the author explicitly requests this with the <param> or <content> elements and/or the 'src' and 'namelist' attributes.
The invoked and invoking process can also communicate via events. In addition to automatic forwarding specified by the 'autoforward' attribute. SCXML scripts can also use the <send> tag to send messages to the child process on an ad-hoc basis. The 'type' attribute of <send> is set to the same value as was used in the original <invoke>, while the target has the special form #_ invokeid , where invokeid is the identifier corresponding to the original <invoke> tag. For example, in a document using ECMAScript as the data model, the following code would invoke a VoiceXML session:
<invoke type="http://www.w3.org/TR/voicexml21/" idlocation="myInvoke"/>
In this case, the unique invoke identifier has been stored in the data model location MyInvoke. Since the target attribute is an expression which is evaluated, the following code will extract that identifier and send a message to the invoked VoiceXML session:
<send type="http://www.w3.org/TR/voicexml21/" targetexpr="'#_' + myInvoke"/>
Finally, in the case where the invoked external service is an SCXML session, it can use <send> with the special target '_parent' and type 'scxml' to send events, possibly containing data, to the invoking session.
[This section is normative.]
The <finalize> element enables an invoking session to update its data model with data contained in events returned by the invoked session. <finalize> contains executable content that is executed whenever the external service returns an event after the <invoke> has been executed. This content is applied before the system looks for transitions that match the event. Within the executable content, the system variable '_event' can be used to refer to the data contained in the event which is being processed.In the case of parallel states, only the finalize code in the original invoking state is executed.
In a conformant SCXML document, the executable content inside <finalize> MUST NOT raise events or invoke external actions. In particular, the <send> and <raise> elements MUST NOT occur.
If one or more elements of executable content is specified, the SCXML Processor MUST execute them each time an event is received from the child process that was created by the parent <invoke> element. The Processor MUST execute them right before the event is pulled off the external event queue for processing. The Processor MUST NOT execute them at any other time or in response to any other events.
If no executable content is specified, the SCXML Processor MUST update the data model each time an event is received from the child process that was created by the parent <invoke> element. Specifically if the parent <invoke> element contains a 'namelist' attribute or one or more <param> children containing 'location' attributes, then for each item in the 'namelist' attribute and each such <param> element, the Processor MUST update the corresponding location with any return value that has a name that matches the name of the 'namelist' item or the 'name' of the <param> element. Thus the effect of an <invoke> with an empty <finalize> element and either a 'namelist' attribute or a <param> element with a 'location' attribute is first to send the part of the data model specified by 'namelist' or 'location' to the invoked component and then to update that part of the data model with any returned values that have the same name. Note that the automatic update does not take place if the <finalize> element is absent as opposed to empty.
In the example below, a state machine using an ECMAScript data model invokes a clock object that returns the current time in a ping event with an XML payload that includes the currentSecond, currentMinute, currentHour (1-12), and an isAm flag. <finalize> maps this data into an ECMAScript date object that is used in the condition of a transition. Thus <finalize> normalizes the data before the conditions on transitions are evaluated.
<scxml version="1.0" datamodel="ecmascript"> .... <state id="getTime"> <transition event="ping" cond="time.getHours() > 17 || time.getHours() < 9" target="storeClosed"/> <transition event="ping" target="takeOrder"/> <datamodel> <data id="time" expr="new Date()"/> </datamodel> <invoke id="timer" type="x-clock" src="clock.pl"> <finalize> <script> time.setSeconds(_event.data.currentSecond); time.setMinutes(_event.data.currentMinute); time.setHours(_event.data.currentHour + (_event.isAm ? 0 : 12) - 1); </script> </finalize> </invoke> </state> ....
[This section is normative.]
The following conformance requirements hold for all SCXML documents.
A SCXML 1.0 processor is a user agent that can parse and process Conforming SCXML 1.0 documents.
In a Conforming SCXML 1.0 Processor, the XML parser MUST be able to parse and process all well-formed XML constructs defined within [XML] and [XMLNames] . It is not required that a Conforming SCXML 1.0 processor use a validating parser.
A
Conforming
SCXML
1.0
Processor
MUST
support
the
syntax
and
semantics
of
all
mandatory
SCXML
elements
described
in
this
document.
A
Conforming
SCXML
1.0
Processor
MAY
support
the
syntax
and
semantics
of
any
optional
SCXML
elements
described
in
this
document.
A
Conforming
SCXML
1.0
Processor
MUST
behave
as
if
it
were
executing
the
algorithm
specified
in
A
Algorithm
for
SCXML
Interpretation
.
When a Conforming SCXML 1.0 Processor encounters a non-conformant document, or one containing non-SCXML elements or attributes which are proprietary, or defined in a non-SCXML namespace, its behavior is undefined.
There is no conformance requirement with respect to performance characteristics of the SCXML 1.0 Processor.
[This section is normative.]
The 'datamodel' attribute on <scxml> defines the data model that the document uses. The data model includes the underlying data structure plus languages for boolean expressions, location expressions, value expressions, and scripting. A conformant SCXML document MAY specify the data model it uses. Conformant SCXML processors MUST support the null data model, and MAY support other data models, including the ECMAScript and XPath data models. The ECMAScript and XPath model definitions given here are normative in the sense that they define how implementations that support one of these languages MUST behave. The intent is to ensure interoperability among all processors that support ECMAScript, and all those that support XPath, without requiring all implementations to support either of those data model languages.
The definition of a data model MUST :
The value "null" for the 'datamodel' attribute results in an absent or empty data model. In particular:
The boolean expression language consists of the In predicate only . It has the form 'In( id )', where id is the id of a state in the enclosing state machine. The predicate MUST return 'true' if and only if that state is in the current state configuration.
The <foreach> element and the elements defined in 5 Data Model and Data Manipulation are not supported in the Null Data Model.
The value 'ecmascript' for the 'datamodel' attribute results in an ECMAScript data model. Implementations that support this value MUST support the third edition of ECMAScript [ECMASCRIPT-262] . Implementations MAY support JSON [RFC 4627] or ECMAScript for XML (E4X) [E4X] .
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.
<scxml version="1.0" xmlns="http://www.w3.org/2005/07/scxml" datamodel="ecmascript"> <datamodel> <data id="employees" src="http://example.com/employees.json"/> <data id="year" expr="2008"/> <data id="CEO" expr="'Mr Big'"/> <data id="profitable" expr="true"/> </datamodel> </scxml>
The Processor MUST place all variables in a single global ECMAScript scope. Specifically, the SCXML Processor MUST allow any data element to be accessed from any state. Ordering dependencies between <data> elements are not permitted. In the case of early binding, the SCXML Processor MUST evaluate all <data> elements at initialization time but MAY do so in any order it chooses. When late binding is selected, the SCXML Processor MUST create data model elements at initialization time but MAY do so in any order it chooses. Similarly, the processor MUST assign the specified initial values to data elements only when the state containing them is first entered, but MAY do so in any order it chooses.
The Processor MUST convert ECMAScript expressions used in conditional expressions into their effective boolean value using the ToBoolean operator as described in Section 9.2 of [ECMASCRIPT-262] .
The following example illustrates this usage.
<state id="errorSwitch"> <datamodel> <data id="time"/> </datamodel><onentry> <assign location="time" expr="currentDateTime()"/> </onentry><transition cond="yearFromDatetime(time) > 2009" target="newBehavior"/><transition target="currentBehavior"/> </state>
The SCXML processor MUST define an ECMAScript function named 'In()' that takes a stateID as its argument and returns 'true' if and only if that state is in the current state configuration, as described in 5.9.1 Conditional Expressions . Here is an example of its use, taken from G.3 Microwave Example (Using parallel) below:
<transition cond="In('closed')" target="cooking"/>
The SCXML Processor MUST accept any ECMAScript left-hand-side expression as a location expression. The following example illustrates this usage. (Note that the example assumes that the data loaded from http://example.com/employees.json creates the necessary data structure, so that employees.employee[12].salary exists when <assign> is evaluated. If it didn't, the Processor would raise error.execution and the <assign> would have no effect.)
The SCXML Processor MUST accept any ECMAScript expression as a value expression.
When
<content>
is
a
child
of
<donedata>,
the
Processor
MUST
interpret
its
value
as
defined
in
C.2.8.1
B.2.8.1
_event.data
.
When
<content>
is
a
child
of
<send>,
the
interpretation
of
its
value
depends
on
the
Event
I/O
Processor.
When
<content>
is
a
child
of
<invoke>,
the
interpretation
of
its
value
is
platform-specific.
When evaluating an <assign> element in the ECMAScript data model, the SCXML Processor MUST replace the existing value at 'location' with the value produced by evaluating 'expr'. If it is unable to do so (for example, if the <assign> element attempts to assign to a read-only attribute), it MUST place the error error.execution on the internal event queue.
The
SCXML
Processor
MUST
define
an
ECMAScript
read-only
variable
for
each
system
variable
defined
in
5.10
System
Variables
.
The
_sessionid
and
_name
system
variables
are
defined
as
variables
with
ECMAScript
String
values.
The
_event
system
variable
is
defined
as
an
object
with
properties
for
each
of
the
fields
defined
in
5.10.1
The
Internal
Structure
of
Events
:
name
,
type
,
sendid
,
origin
,
origintype
,
and
invokeid
are
String
values,
while
data
can
be
of
any
type.
In
cases
where
this
specification
does
not
specify
a
value
for
one
of
these
fields
or
states
that
the
field
is
empty
or
has
no
value,
the
Processor
MUST
set
the
value
to
ECMAScript
undefined.
As
the
value
of
the
_ioprocessors
system
variable
the
Processor
MUST
create
an
object
with
a
named
property
for
each
Event
I/O
processor
that
it
supports,
where
the
name
of
the
property
is
the
same
as
that
of
the
I/O
processor
and
the
value
of
the
property
is
an
object
that
represents
the
I/O
processor.
For
the
SCXML
and
BasicHTTP
Event
I/O
processors,
the
Processor
MUST
create
a
"location"
property
under
that
object,
assigning
the
access
URI
as
its
String
value.
For
example,
in
systems
that
support
the
BasicHTTP
Event
I/O
Processor,
the
access
URI
of
the
BasicHTTP
Event
I/O
processor
can
be
accessed
as
_ioprocessors['http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor'].location.
_event.data is populated with content provided by an external event or by <param> or <content>. In some circumstances, the entity that generated the event may have indicated how the data is to be interpreted. In such cases, the Processor SHOULD try to format the data according to those indications. Otherwise, if the SCXML Processsor can interpret the content as key-value pairs, then for each unique key, the Processor MUST create a property of _event.data whose name is the name of the key-value pair and whose value is the value of the key-value pair. In the case of duplicate keys, the behavior is platform-specific. (Note that content specified by <param> or delivered as POST parameters via the BasicHTTP Event I/O Processor consists unambiguously of key-value pairs.) Otherwise (i.e., if the content does not consist of key-value pairs), if the Processor supports JSON and it can interpret the content as JSON, it MUST create the corresponding ECMAScript object(s) as the value of _event.data. Otherwise, if the Processor can interpret the content as a valid XML document, it MUST create the corresponding DOM structure and assign it as the value _event.data. Otherwise, the Processor MUST treat the content as a space-normalized string literal and assign it as the value of _event.data.
Suppose as part of executing a state machine named "myName" with a platform-assigned sessionid "12345", we are processing an event with the name "foo.bar" and the following object payload:
{ "answer" : 42 }
Then the underlying ECMAScript data model would have the following form:
{ // The four properties below are automatically populated by the system "_name" : "myName" , "_sessionid" : "12345" , "_event" : { "name" : "foo.bar" , "data" : { "answer" : 42 } } , "_ioprocessors" : { "http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor" : { "location" : "http://example.com/scxml-http/12345" } "http://www.w3.org/TR/scxml/#SCXMLEventProcessor" : { "location" : "http://example.com/scxml-http/23456" }} ,} , // Rest of the application / developer-authored data model goes here }
As
an
example,
here
is
a
sample
transition
that
accesses
the
_event
variable
in
that
data
model.
In certain circumstances, e.g. when including data in events sent via the BasicHTTP Event I/O Processor, the SCXML Processor is required to serialize data from the ECMAScript data model for transmission to a remote entity. In such cases, if the Processor supports JSON, and is able to serialize the data in sufficient detail to allow its reconstruction, the Processor MUST serialize the data to JSON. Otherwise, the Processor MAY use platform-specific methods (including JSON despite the loss of information) to serialize the data. The Processor SHOULD provide a warning if the serialization entails loss of information or if it is unable to serialize at all.
The SCXML Processor MUST accept any ECMAScript program as defined in Section 14 of [ECMASCRIPT-262] as the content of a <script> element.
In
the
ECMAScript
data
model,
the
SCXML
Processor
MUST
support
iteration
over
objects
that
satisfy
instanceof(Array)
in
ECMAScript.
It
MAY
support
iteration
over
other
types
of
objects.
The
legal
values
for
the
'item'
attribute
are
legal
ECMAScript
variable
names.
In
cases
where
ECMAScript
specification
defines
the
iteration
order
for
the
object,
the
Processor
MUST
follow
that
ordering.
(For
arrays
and
strings,
this
goes
from
0
to
length-1.)
In
cases
where
the
ECMAScript
specification
does
not
define
the
iteration
order,
the
Processor
MAY
follow
any
order
that
it
chooses
as
long
as
1)
it
iterates
over
the
object's
own
enumberable
enumerable
properties
only
2)
it
visits
each
such
property
once
and
only
once.
Note
that
since
the
Processor
is
required
to
behave
as
if
it
has
made
a
shallow
copy,
in
the
case
of
an
array
<foreach>
assignment
is
equivalent
to
item
=
array_name[index]
in
ECMAScript.
Note
also
that
the
assigned
value
could
be
undefined
for
a
sparse
array.
The value "xpath" for the 'datamodel' attribute results in an XML data model with XPath used as the expression language. Implementations that support this data model MUST support [XPath 1.0] .
The underlying structure of the XPath data model follows the document syntax closely. In particular, the SCXML Processor MUST maintain the XPath data model as an XML document with a root element called <datamodel>. For each <data> element in the document, the SCXML Processor MUST create a child of <datamodel> called <data> with an 'id' attribute whose value is the same as that of the 'id' attribute of the document <data> element. The Processor MUST insert the value of the document <data> element as the child(ren) of the datamodel <data> element. The Processor MUST also bind an XPath variable of the same name to that datamodel <data> element.
If either the 'src' attribute or in-line content is provided in the document <data> element, then if the content (whether fetched or provided in-line) is an XML document or node set, the SCXML Processor MUST insert the XML as the child of the datamodel <data> element. Otherwise the Processor MUST treat the content as a space-normalized string literal and insert it as the child of the datamodel <data> element. If no value is assigned, the SCXML Processor MUST leave the datamodel <data> element empty, as follows:
<data xmlns=""></data>
The Processor MUST place all variables in a single global XPath scope. Specifically, the SCXML Processor MUST allow any data element to be accessed from any state. Ordering dependencies between <data> elements are not permitted. In the case of early binding, the SCXML Processor MUST evaluate all <data> elements at initialization time but MAY do so in any order it chooses. When late binding is selected, the SCXML Processor MUST create data model elements at initialization time but MAY do so in any order it chooses. Similarly, the processor MUST assign the specified initial values to data elements only when the state containing them is first entered, but MAY do so in any order it chooses.
<scxml version="1.0" datamodel="xpath"> <datamodel> <data id="company"> <about xmlns=""> <name>Example company</name> <website>example.com</website> <CEO>John Doe</CEO> </about> </data> <data id="employees" src="http://example.com/employees.xml"/> <data id="defaultdata"/> </datamodel> </scxml>
The SCXML Processor MUST accept any XPath expression as a conditional expression and MUST convert it into its effective boolean value as described in section 2.4.3 of the [XPath 2.0] specification. The following example illustrates this usage.
<state id="errorSwitch" xmlns:fn="http://www.w3.org/2005/xpath-functions"> <datamodel> <data id="time"/> </datamodel><onentry> <assign location="$time" expr="fn:current-dateTime()"/> </onentry><transition cond="fn:year-from-dateTime($time) > 2009" target="newBehavior"/> <transition target="currentBehavior"/> </state>
The SCXML processor MUST define an XPath function 'In()' that takes a stateID as its argument and returns 'true' if and only if that state is in the current state configuration, as described in 5.9.1 Conditional Expressions . For examples of the use of this predicate (but in an ECMAScript context), see G.3 Microwave Example (Using parallel) .
Function
signature:
In($stateID
as
xs:string?)
as
xs:boolean
Returns
an
xs:boolean
indicating
whether
or
not
the
state
with
ID
$stateID
is
one
of
the
currently
active
states.
The SCXML Processor MUST accept any XPath expression as a location expression. The following example illustrates this usage:
<state id="errorSwitch"> <datamodel> <data id="cities"> <list xmlns=""> <city id="nyc" count="0">New York</city> <city id="bos" count="0">Boston</city> </list> </data> </datamodel> <onentry> <assign location="$cities/list/city[@id='nyc']/@count" expr="1"/> </onentry> </state>
The SCXML Processor MUST allow any XPath expression to be used as a value expression. If the result of the value expression is a node-set, the Processor MUST make a deep copy of the subtree rooted at each node. The Processor MAY convert the expression result to a string In contexts where a string is expected.
When
<content>
is
a
child
of
<donedata>,
the
Processor
MUST
interpret
its
value
as
defined
in
C.3.7.1
B.3.7.1
_event.data
.
When
<content>
is
a
child
of
<send>,
the
interpretation
of
its
value
depends
on
the
Event
I/O
Processor.
When
<content>
is
a
child
of
<invoke>,
the
interpretation
of
its
value
is
platform-specific.
Implementations supporting the XPath data model MUST support the following additional attributes for the <assign> element.
Name | Required | Attribute Constraints | Type | Default Value | Valid Values | Description |
---|---|---|---|---|---|---|
type | false | enum | replacechildren | replacechildren, firstchild, lastchild, previoussibling, nextsibling, replace, delete, addattribute | Defines the nature of the insertion to be performed. See below for details. | |
attr | false | This attribute must be present if and only if 'type' is 'addattribute'. | NMTOKEN | none | The attribute name to add at the specified location. |
The SCXML Processor MUST modify the data model as directed by the 'type' attribute as described below. If it is unable to do so, it MUST place the error error.execution on the internal event queue:
If the specified location contains a node set, the Processor MUST perform the assignment to each node in the set. It MAY do so in any order it chooses, and MUST evaluate 'expr' only once.
Note that in the case of an XML data model, it is not required to assign to the root of a tree (i.e., the "name" value in a <data> tag), since the path expression can reach down into the tree to assign a new value to an internal node. The following examples show various aspects of assignment in the XPath data model. Suppose we have a data model of the following form:
<data id="cart"> <myCart xmlns=""> <books> <book> <title>The Zen Mind</title> </book> <book> <title>Freakonomics</title> </book> </books> <cds> <cd name="Something"/> </cds> </myCart> </data>
Here is an example of assignment of a string to an element node.
<assign location="$cart/myCart/books/book[1]/title" expr="'My favorite book'"/>
results in
<data id="cart"> <myCart xmlns=""> <books> <book> <title>My favorite book</title> </book> <book> <title>Freakonomics</title> </book> ... </data>
Now suppose we assign an XML structure to an element node. The following assignment statement would have the effect of replacing the children of the element "$cart/myCart/books/book[1]" by the XML tree rooted in <bookinfo>.
<assign location="$cart/myCart/books/book[1]"> <bookinfo xmlns=""> <isdn>12334455</isdn> <author>some author</author> </bookinfo> </assign>
results in
<data id="cart"> <myCart xmlns=""> <books> <book> <bookinfo> <isdn>12334455</isdn> <author>some author</author> </bookinfo> </book> <book> <title>Freakonomics</title> </book> ... </data>
Here are examples of legal and illegal assignment to an attribute:
<!-- Legal assignment: --> <assign location="$cart/myCart/cds/cd/@name" expr"'Something Else'"/> <!-- Illegal assignment: --> <assign location="$cart/myCart/cds/cd/@name" > <foo> <bar/> </foo> </assign>
Now suppose we assign a string to a nodeset. The following assignment statement would have the effect of replacing the children of each node in the nodeset $cart/myCart/books/book with the string "The Zen Mind":
<assign location="$cart/myCart/books/book" expr="'The Zen Mind'"/>
results in
<data id="cart"> <myCart xmlns=""> <books> <book>The Zen Mind</book> <book>The Zen Mind</book> </books> ... </data>
Finally suppose we assign a structure to a nodeset. The following statement would iterate over the elements in the nodeset of <book> elements and replace their children with the <price> structure:
<assign location="$cart/myCart/books/book"> <price>20.0</price> </assign>
results in
<data id="cart"> <myCart xmlns=""> <books> <book> <price>20.0</price> </book> <book> <price>20.0</price> </book> </books> ... </data>
If the evaluation of any of the expressions in an <assign> element causes an error to be raised, evaluation of the element terminates immediately and the <assign> has no effect. For example, the following assignment statement would raise an error because the sample data model we are using does not have an <ISBN> node as a child of <book>:
<assign location="$cart/myCart/books/book[1]/ISBN" expr="'....'"/>
For each system variable defined in 5.10 System Variables , the SCXML Processor MUST create a data model <data> element with an 'id' attribute whose value is the name of the system variable. The Processor also MUST bind an XPath variable whose name is the name of the system variable to this element. For the _event system variable (i.e., the <data id="_event"> child of <datamodel>), for each of the fields defined in 5.10.1 The Internal Structure of Events , the Processor also MUST create an child element whose name is the name of the field. For the _ioprocessors system variable the Processor MUST create an child <processor> element for each Event I/O processor that it supports, with a 'name' attribute whose value is the name of the I/O processor. For the SCXML and BasicHTTP Event I/O processors, the Processor MUST create a <location> child under the child element, assigning the access URI as its text child. For example, in systems that support the BasicHTTP Event I/O Processor, the access URI of the BasicHTTP Event I/O processor can be a accessed as $_ioprocessors/processor[@name="/http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor/"]/location/text().
The _event variable's <data> child is populated with content provided by an external event or by <param> or <content>. In some circumstances, the entity that generated the event may have indicated how the data is to be interpreted. In such cases, the Processor SHOULD try to format the data according to those indications. Otherwise, if the SCXML Processor can interpret the content as key-value pairs, then for each unique key, the Processor MUST create a <data> element as a child of _event's <data> child with an 'id' attribute whose value is the name of the key. The Processor MUST insert the value of the key-value pair as the content of this element. In the case of duplicate keys, the behavior is platform-specific. (Note that content specified by <param> or delivered as POST parameters via the BasicHTTP Event I/O Processor consists unambiguously of key-value pairs.) Otherwise (i.e., if the content does not consist of key-value pairs), if the Processor can interpret the content is a valid XML document, the it MUST insert the XML structure as the content of _event's <data> child. Otherwise, the Processor MUST treat the content as a space-normalized string literal and insert it as the content of _event's <data> child.
Suppose as part of executing a state machine named "myName" with a platform-assigned sessionid "12345", we are processing an event with the name "foo.bar" and the following XML payload:
<payload xmlns=""> <answer>42</answer> </payload>
Then the underlying XML data model would have the following form (not all the fields of the event are shown):
<datamodel> <!-- The four data elements below are automatically populated by the system --> <data id="_name">myName</data> <data id="_sessionid">12345</data> <data id="_event"> <name xmlns="">foo.bar</name> <data xmlns=""> <payload> <answer>42</answer> </payload> </data> </data> <data id="_ioprocessors"> <processor name="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor"> <location>http://example.com/scxml-http/12345</location> </processor> <processor name="http://www.w3.org/TR/scxml/#SCXMLEventProcessor"> <location/> </processor> </data> <!-- Rest of the application / developer-authored data model goes here --> </datamodel>
As
an
example,
here
is
a
sample
transition
that
accesses
the
$_sessionid
variable
in
that
data
model.
<state id="checkSessionid"> <transition cond="$_sessionid = '12345'" target="nextState"/> ... </state>
In certain circumstances, e.g. when including data in events sent via the BasicHTTP Event I/O Processor, the SCXML Processor is required to serialize data from the XPath data model for transmission to a remote entity. In such cases, the Processor MUST serialize the data as a string.
In the XPath data model, the legal iterable collections are Node-Sets. The legal values for the 'item' attribute are legal XPath variable names. The iteration order is the order of the underlying Node-set, and goes from an index of 1 by increments of one to an index of count(node-set).
5.8 <script> is not supported in the XPath Data Model.
[This section is normative.]
The SCXML Event I/O Processor is intended to transport messages between SCXML sessions. This specification defines the mapping between the parameters in the sending session and the event that is raised in the receiving session, but the transport mechanism is platform-specific.
The sending and receiving SCXML Processors MUST maintain the following mappings:
When using the SCXML Event I/O Processor, SCXML Processors MUST support the following special targets for <send>:
If neither the 'target' nor the 'targetexpr' attribute is specified, the SCXML Processor MUST add the event to the external event queue of the sending session.
If the sending SCXML session specifies a session that does not exist or is inaccessible, the SCXML Processor MUST place the error error.communication on the internal event queue of the sending session. If the receiving Processor cannot handle the data format contained in the message, the receiving Processor MUST place the error error.communication in internal queue of the session for which the message was intended and MUST ignore the message. The Processor SHOULD also notify the sending processor of the error. If no errors occur, the receiving Processor MUST convert the message into an SCXML event, using the mapping defined above, and insert the event into the appropriate queue, as defined in 6.2.4 The Target of Send
SCXML Processors MUST maintain a 'http://www.w3.org/TR/scxml/#SCXMLEventProcessor' entry in the _ioprocessors system variable. The Processor MUST maintain a 'location' field inside this entry whose value holds an address that external entities can use to communicate with this SCXML session using the SCXML Event I/O Processor.
Here are some examples of SCXML messages sent between SCXML sessions. Each example shows the original <send> element and a transition handling the resulting event in the receiving SCXML session.
EXAMPLE 1: First, here is a message with an XML payload generated by <send> with a 'namelist':
SESSION1 : SENDING SESSION Pattern: "event" attribute with an optional "namelist" <datamodel> <data id="email" expr="'mailto:recipient@example.com'"/> <data id="content" expr="'http://www.example.com/mycontent.txt'"/> <data id="xmlcontent"> <headers xmlns="http://www.example.com/headers"> <cc>archive@example.com</cc> <subject>Example email</subject> </headers> </data> </datamodel> ... <send id="send-123" target="http://scxml-processors.example.com/session2" type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" event="email.send" namelist="email content xmlcontent"/>
Here is sample SCXML code to process that event in the receiving SCXML session. In this example <my:email> is platform-specific executable content that sends an email:
SESSION2 : RECEIVING SESSION Pattern: "event" attribute with an optional "namelist" <scxml:transition event="email.send"> <my:email to="data('_event')/scxml:property[@name='email']" cc="data('_event')/scxml:property[@name='xmlcontent']/h:headers/h:cc" subject="data('_event')/scxml:property[@name='xmlcontent']/h:headers/h:subject" content="data('_event')/scxml:property[@name='content']"/> </scxml:transition>
EXAMPLE 2: The next example shows <send> using inline XML content:
SESSION1 : SENDING SESSION Pattern: "xmlns" attribute with explicit inline content <send id="send-123" target="http://scxml-processors.example.com/session2" type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" xmlns:csta="http://www.ecma.ch/standards/ecma-323/csta"> <content> <csta:MakeCall> <csta:callingDevice>22343</csta:callingDevice> <csta:calledDirectoryNumber>18005551212</csta:calledDirectoryNumber> </csta:MakeCall> </content> </send>
Here is sample SCXML code to process the resulting event in the receiving SCXML session. It uses the special executable content <csta:makecall> to generate a telephone call:
SESSION2 : RECEIVING SESSION Pattern: "xmlns" attribute with explicit inline content <scxml:transition event="external.event"> <csta:makecall callingDevice="data('_event')/csta:MakeCall/csta:callingDevice" callingDirectoryNumber="data('_event')/csta:MakeCall/csta:callingDirectoryNumber"/> </scxml:transition>
EXAMPLE 3: Finally, here is an example generated by <send> using both 'event' and 'namelist' attributes and using JSON content:
SESSION1 : SENDING SESSION Pattern: "event" attribute with an optional "namelist" <datamodel> <data id="email" expr="'mailto:recipient@example.com'"/> <data id="content" expr="'http://www.example.com/mycontent.txt'"/> <data id="jsoncontent" src="http://www.example.com/headers.json"/> </datamodel> ... <send sendid="send-123" target="'http://scxml-processors.example.com/session2'" type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor" event="'email.send'" namelist="email content jsoncontent"/>
Here is sample SCXML code to process the resulting event in the receiving SCXML session. In this example, <my:email> is special executable content as in the first example.
SESSION2 : RECEIVING SESSION Pattern: "event" attribute with an optional "namelist" <scxml:transition event="email.send"> <my:email to="_event.email" cc="_event.jsoncontent.headers.cc" subject="_event.jsoncontent.headers.subject" content="_event.content"/> </scxml:transition>
The Basic HTTP Event I/O Processor is intended as a minimal interoperable mechanism for sending and receiving events to and from external components and SCXML 1.0 implementations. Support for the Basic HTTP Event I/O Processor is optional.
An SCXML Processor that supports the Basic HTTP Event I/O Processor MUST accept messages at the access URI as HTTP POST requests (see [RFC 2616] ). The SCXML Processor MUST validate the message it receives and then MUST build the appropriate SCXML event and MUST add it to the external event queue.
If
a
single
instance
of
the
parameter
'_scxmleventname'
is
present,
the
SCXML
Processor
MUST
use
its
value
as
the
name
of
the
SCXML
event
that
it
raises.
If
multiple
instances
of
the
parameter
are
present,
the
behavior
is
platform-specific.
If
the
parameter
'_scxmleventname'
is
not
present,
the
SCXML
Processor
MUST
use
the
name
of
the
HTTP
method
that
was
used
to
deliver
the
message
as
the
name
of
the
event
that
it
raises.
The
processor
MUST
use
any
message
content
other
than
'_scxmleventname'
to
populate
_event.data.
See
C
B
Data
Models
for
details.
After it adds the received message to the appropriate event queue, the SCXML Processor MUST then indicate the result to the external component via a success response code 2XX. Note that this response is sent before the event is removed from the queue and processed. In the cases where the message cannot be formed into an SCXML event, the Processor MUST return an HTTP error code as defined in [RFC 2616] .
An SCXML implementation can send events with the Basic HTTP Event I/O Processor using the <send> element (see 6.2 <send> ) with the type attribute set to "http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor" and the target attribute set to the access URI of the target. If neither the 'target' nor the 'targetexpr' attribute is specified, the SCXML Processor MUST add the event error.communication to the internal event queue of the sending session.
The SCXML Processor MUST attempt to deliver the message using HTTP method "POST" and with parameter values encoded by default in an application/x-www-form-urlencoded body (POST method). An SCXML Processor MAY support other encodings, and allow them to be specified in a platform-specific way.
If the 'event' parameter of <send> is defined, the SCXML Processor MUST use its value as the value of the HTTP POST parameter _scxmleventname. If the namelist attribute is defined, the SCXML Processor MUST map its variable names and values to HTTP POST parameters. If one or more <param> children are present, the SCXML Processor MUST map their names (i.e. name attributes) and values to HTTP POST parameters. If a <content> child is present, the SCXML Processor MUST use its value as the body of the message.
SCXML Processors that support the BasicHTTP Event I/O Processor MUST maintain a 'http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor' entry in the _ioprocessors system variable. The Processor MUST maintain a 'location' field inside this entry whose value holds an address that external entities can use to communicate with this SCXML session using the Basic HTTP Event I/O Processor.
The DOM Event I/O processor handles communication between SCXML Interpreters and nodes in documents that implement the DOM. An example of this would be a document containing both SCXML and HTML markup. In such a case, each language retains its own context and its own independent semantics. (Note that the syntax and semantics of SCXML make no reference to the DOM, so that SCXML's event processing algorithm is not affected by the fact that there is HTML markup elsewhere in the document.) It is however useful for the two languages to be able to communicate by sending events back and forth, so that the User Agent can notify SCXML when the user clicks on a button, and the SCXML markup can notify the appropriate element when it is time to place a certain field in focus, etc. The DOM Event I/O processor handles this communication by means of DOM Events [DOMEvents] , which are a general means for information propagation in XML documents. Note that we do not require that the SCXML document be represented in the other markup's DOM (though it may be).
The SCXML Processor MUST support sending DOM events to any node in the document by selecting the DOM Event I/O processor (type="http://www.w3.org/TR/scxml/#DOMEventProcessor") and specifying the node as the target. Processors MUST support CSS notation [CSS2] for specifying the node, and MAY support XPath [XPath 1.0] or other notations. The SCXML Processor MUST support sending events that implement the CustomEvent interface. The Processor MAY support sending events that implement other interfaces. In this case, the Processor MUST support an additional attribute on <send>, called 'interface', that allows the author to specify the interface to use. The default value of this attribute MUST be 'CustomEvent'.
The Processor MUST use the value of the 'event' attribute as the type of the DOM event. The Processor MUST support two additional attributes on <send>, called 'cancelable' and 'bubbles', which can be used to set the corresponding properties of the event. The default value for 'cancelable' MUST be 'false'. The default value of 'bubbles' MUST be 'true'. The Processor MUST populate any other initializable attributes of the event with the values of any matching keys specified via "namelist" or <param>. If the specified DOM event type has a 'detail' attribute, the Processor MUST populate it with any remaining data (i.e., values specified by 'namelist', <param> or <content> that are not used to populate the event's initializable attributes.) If the specified event is not a legal DOM event or if the specified node cannot be reached, the SCXML Processor MUST place the error error.communication in the internal event queue.
The DOM Event I/O Processor implementation MUST add a function to the DOM scripting environment that takes a DOM event as its argument and adds a corresponding event to the SCXML Processor's external event queue. The function MUST use the type of the DOM event as the name of the SCXML event and MUST place a shallow copy of the DOM event in _event.data.
[This section is informative.]
This section contains an illustrative algorithm for the interpretation of an SCXML document. It is intended as a guide for implementers only. Implementations are free to implement SCXML interpreters in any way they choose.
The following definitions and highlevel principles and constraint are intended to provide a background to the algorithm, and to serve as a guide for the proper understanding of it.
We state here some principles and constraints, on the level of semantics, that SCXML adheres to:
Note that the algorithm assumes a Lisp-like semantics in which the empty Set null is equivalent to boolean 'false' and all other entities are equivalent to 'true'.
These are the abstract datatypes that are used in the algorithm.
datatype Listfunction
head() // Returns the head of the listfunction
tail() // Returns the tail of the list (i.e., the rest of the list once the head is removed)function
append(l) // Returns the list appended with lfunction
filter(f) // Returns the list of elements that satisfy the predicate ffunction
some(f) // Returns true if some element in the list satisfies the predicate ffunction
every(f) // Returns true if every element in the list satisfies the predicate f The notation [...] is used as a list constructor, so that '[t]' denotes a list whose only member is the object t. datatype OrderedSetprocedure
add(e) // Adds e to the set if it is not already a memberprocedure
delete(e) // Deletes e from the setprocedure
union(s) // Adds all members of s that are not already members of the set (s must also be an OrderedSet)function
isMember(e) // Is e a member of set?function
hasIntersection(s) // Returns true if this set and set s have at least one member in commonfunction
isEmpty() // Is the set empty?procedure
clear() // Remove all elements from the set (make it empty)function
toList() // Converts the set to a list that reflects the order in which elements were originally added // In the case of sets created by intersection, the order of the first set (the one on which the method was called) is used // In the case of sets created by union, the members of the first set (the one on which union was called) retain their original ordering // while any members belonging to the second set only are placed after, retaining their ordering in their original set. datatype Queueprocedure
enqueue(e) // Puts e last in the queuefunction
dequeue() // Removes and returns first element in queuefunction
isEmpty() // Is the queue empty? datatype BlockingQueueprocedure
enqueue(e) // Puts e last in the queuefunction
dequeue() // Removes and returns first element in queue, blocks if queue is empty datatype HashTable // table[foo] returns the value associated with foo. table[foo] = bar sets the value associated with foo to be bar.
The following variables are global from the point of view of the algorithm. Their values will be set in the procedure interpret().
global configuration global statesToInvoke global datamodel global internalQueue global externalQueue global historyValue global running global binding
The following binary predicates are used for determining the order in which states are entered and exited.
name="entryOrder">entryOrder
// Ancestors precede descendants, with document order being used to break ties (Note:since ancestors precede descendants, this is equivalent to document order.)name="exitOrder">exitOrder
// Descendants precede ancestors, with reverse document order being used to break ties (Note: since descendants follow ancestors, this is equivalent to reverse document order.)
This section defines the procedures and functions that make up the core of the SCXML interpreter. N.B. in the code below, the keyword 'continue' has its traditional meaning in languages like C: break off the current iteration of the loop and proceed to the next iteration.
procedure
interpret(scxml,id)
The purpose of this procedure is to initialize the interpreter and to start processing.
In order to interpret an SCXML document, first (optionally) perform [xinclude] processing and (optionally) validate the document, throwing an exception if validation fails. Then convert initial attributes to <initial> container children with transitions to the state specified by the attribute. (This step is done purely to simplify the statement of the algorithm and has no effect on the system's behavior. Such transitions will not contain any executable content). Initialize the global data structures, including the data model. If binding is set to 'early', initialize the data model. Then execute the global <script> element, if any. Finally call enterStates on the initial configuration, set the global running variable to true and start the interpreter's event loop.
procedure interpret(doc): if not valid(doc): failWithError() expandScxmlSource(doc) configuration = new OrderedSet() statesToInvoke = new OrderedSet() internalQueue = new Queue() externalQueue = new BlockingQueue() historyValue = new HashTable() datamodel = new Datamodel(doc) if doc.binding == "early": initializeDatamodel(datamodel, doc) running = true executeGlobalScriptElement(doc) enterStates([doc.initial.transition]) mainEventLoop()
procedure
mainEventLoop()
This loop runs until we enter a top-level final state or an external entity cancels processing. In either case 'running' will be set to false (see EnterStates, below, for termination by entering a top-level final state.)
At the top of the loop, we have either just entered the state machine, or we have just processed an external event. Each iteration through the loop consists of four main steps: 1)Complete the macrostep by repeatedly taking any internally enabled transitions, namely those that don't require an event or that are triggered by an internal event. After each such transition/microstep, check to see if we have reached a final state. 2) When there are no more internally enabled transitions available, the macrostep is done. Execute any <invoke> tags for states that we entered on the last iteration through the loop 3) If any internal events have been generated by the invokes, repeat step 1 to handle any errors raised by the <invoke> elements. 4) When the internal event queue is empty, wait for an external event and then execute any transitions that it triggers. However special preliminary processing is applied to the event if the state has executed any <invoke> elements. First, if this event was generated by an invoked process, apply <finalize> processing to it. Secondly, if any <invoke> elements have autoforwarding set, forward the event to them. These steps apply before the transitions are taken.
This event loop thus enforces run-to-completion semantics, in which the system process an external event and then takes all the 'follow-up' transitions that the processing has enabled before looking for another external event. For example, suppose that the external event queue contains events ext1 and ext2 and the machine is in state s1. If processing ext1 takes the machine to s2 and generates internal event int1, and s2 contains a transition t triggered by int1, the system is guaranteed to take t, no matter what transitions s2 or other states have that would be triggered by ext2. Note that this is true even though ext2 was already in the external event queue when int1 was generated. In effect, the algorithm treats the processing of int1 as finishing up the processing of ext1.
procedure mainEventLoop(): while running: enabledTransitions = null macrostepDone = false # Here we handle eventless transitions and transitions # triggered by internal events until macrostep is complete while running and not macrostepDone: enabledTransitions = selectEventlessTransitions() if enabledTransitions.isEmpty(): if internalQueue.isEmpty(): macrostepDone = true else: internalEvent = internalQueue.dequeue() datamodel["_event"] = internalEvent enabledTransitions = selectTransitions(internalEvent) if not enabledTransitions.isEmpty(): microstep(enabledTransitions.toList()) # either we're in a final state, and we break out of the loop if not running: break; # or we've completed a macrostep, so we start a new macrostep by waiting for an external event # Here we invoke whatever needs to be invoked. The implementation of 'invoke' is platform-specific for state in statesToInvoke: for inv in state.invoke: invoke(inv) statesToInvoke.clear() # Invoking may have raised internal error events and we iterate to handle them if not internalQueue.isEmpty(): continue # A blocking wait for an external event. Alternatively, if we have been invoked # our parent session also might cancel us. The mechanism for this is platform specific, # but here we assume it's a special event we receive externalEvent = externalQueue.dequeue() if isCancelEvent(externalEvent): running = false continue datamodel["_event"] = externalEvent for state in configuration: for inv in state.invoke: if inv.invokeid == externalEvent.invokeid: applyFinalize(inv, externalEvent) if inv.autoforward: send(inv.id, externalEvent) enabledTransitions = selectTransitions(externalEvent) if not enabledTransitions.isEmpty(): microstep(enabledTransitions.toList()) # End of outer while running loop. If we get here, we have reached a top-level final state or have been cancelled exitInterpreter()
procedure
exitInterpreter()
The purpose of this procedure is to exit the current SCXML process by exiting all active states. If the machine is in a top-level final state, a Done event is generated. (Note that in this case, the final state will be the only active state.) The implementation of returnDoneEvent is platform-dependent, but if this session is the result of an <invoke> in another SCXML session, returnDoneEvent will cause the event done.invoke.<id> to be placed in the external event queue of that session, where <id> is the id generated in that session when the <invoke> was executed.
procedure exitInterpreter(): statesToExit = configuration.toList().sort(exitOrder) for s in statesToExit: for content in s.onexit: executeContent(content) for inv in s.invoke: cancelInvoke(inv) configuration.delete(s) if isFinalState(s) and isScxmlState(s.parent): returnDoneEvent(s.donedata)
function
selectEventlessTransitions()
This
function
selects
all
transitions
that
are
enabled
in
the
current
configuration
that
do
not
require
an
event
trigger.
First
find
a
transition
with
no
'event'
attribute
whose
condition
evaluates
to
true
.
If
multiple
matching
transitions
are
present,
take
the
first
in
document
order.
If
none
are
present,
search
in
the
state's
ancestors
in
ancestry
order
until
one
is
found.
As
soon
as
such
a
transition
is
found,
add
it
to
enabledTransitions,
and
proceed
to
the
next
atomic
state
in
the
configuration.
If
no
such
transition
is
found
in
the
state
or
its
ancestors,
proceed
to
the
next
state
in
the
configuration.
When
all
atomic
states
have
been
visited
and
transitions
selected,
filter
the
set
of
enabled
transitions,
removing
any
that
are
preempted
by
other
transitions,
then
return
the
resulting
set.
function selectEventlessTransitions(): enabledTransitions = new OrderedSet() atomicStates = configuration.toList().filter(isAtomicState).sort(documentOrder) for state in atomicStates: loop: for s in [state].append(getProperAncestors(state, null)): for t in s.transition: if not t.event and conditionMatch(t): enabledTransitions.add(t) break loop enabledTransitions = removeConflictingTransitions(enabledTransitions) return enabledTransitions
function
selectTransitions(event)
The purpose of the selectTransitions()procedure is to collect the transitions that are enabled by this event in the current configuration.
Create
an
empty
set
of
enabledTransitions
.
For
each
atomic
state
,
find
a
transition
whose
'event'
attribute
matches
event
and
whose
condition
evaluates
to
true
.
If
multiple
matching
transitions
are
present,
take
the
first
in
document
order.
If
none
are
present,
search
in
the
state's
ancestors
in
ancestry
order
until
one
is
found.
As
soon
as
such
a
transition
is
found,
add
it
to
enabledTransitions,
and
proceed
to
the
next
atomic
state
in
the
configuration.
If
no
such
transition
is
found
in
the
state
or
its
ancestors,
proceed
to
the
next
state
in
the
configuration.
When
all
atomic
states
have
been
visited
and
transitions
selected,
filter
out
any
preempted
transitions
and
return
the
resulting
set.
function selectTransitions(event): enabledTransitions = new OrderedSet() atomicStates = configuration.toList().filter(isAtomicState).sort(documentOrder) for state in atomicStates: loop: for s in [state].append(getProperAncestors(state, null)): for t in s.transition: if t.event and nameMatch(t.event, event.name) and conditionMatch(t): enabledTransitions.add(t) break loop enabledTransitions = removeConflictingTransitions(enabledTransitions) return enabledTransitions
function
removeConflictingTransitions(enabledTransitions)
enabledTransitions will contain multiple transitions only if a parallel state is active. In that case, we may have one transition selected for each of its children. These transitions may conflict with each other in the sense that they have incompatible target states. Loosely speaking, transitions are compatible when each one is contained within a single <state> child of the <parallel> element. Transitions that aren't contained within a single child force the state machine to leave the <parallel> ancestor (even if they reenter it later). Such transitions conflict with each other, and with transitions that remain within a single <state> child, in that they may have targets that cannot be simultaneously active. The test that transitions have non-intersecting exit sets captures this requirement. (If the intersection is null, the source and targets of the two transitions are contained in separate <state> descendants of <parallel>. If intersection is non-null, then at least one of the transitions is exiting the <parallel>). When such a conflict occurs, then if the source state of one of the transitions is a descendant of the source state of the other, we select the transition in the descendant. Otherwise we prefer the transition that was selected by the earlier state in document order and discard the other transition. Note that targetless transitions have empty exit sets and thus do not conflict with any other transitions.
We start with a list of enabledTransitions and produce a conflict-free list of filteredTransitions. For each t1 in enabledTransitions, we test it against all t2 that are already selected in filteredTransitions. If there is a conflict, then if t1's source state is a descendant of t2's source state, we prefer t1 and say that it preempts t2 (so we we make a note to remove t2 from filteredTransitions). Otherwise, we prefer t2 since it was selected in an earlier state in document order, so we say that it preempts t1. (There's no need to do anything in this case since t2 is already in filteredTransitions. Furthermore, once one transition preempts t1, there is no need to test t1 against any other transitions.) Finally, if t1 isn't preempted by any transition in filteredTransitions, remove any transitions that it preempts and add it to that list.
function removeConflictingTransitions(enabledTransitions): filteredTransitions = new OrderedSet() // toList sorts the transitions in the order of the states that selected them for t1 in enabledTransitions.toList(): t1Preempted = false; transitionsToRemove = new OrderedSet() for t2 in filteredTransitions.toList(): if computeExitSet([t1]).hasIntersection(computeExitSet([t2])): if isDescendant(t1.source, t2.source): transitionsToRemove.add(t2) else: t1Preempted = true break if not t1Preempted: for t3 in transitionsToRemove.toList(): filteredTransitions.delete(t3) filteredTransitions.add(t1) return filteredTransitions
procedure
microstep(enabledTransitions)
The
purpose
of
the
microstep
procedure
is
to
process
a
single
set
of
transitions.
These
may
have
been
enabled
by
an
external
event,
an
internal
event,
or
by
the
presence
or
absence
of
certain
values
in
the
data
model
at
the
current
point
in
time.
The
processing
of
the
enabled
transitions
must
be
done
in
parallel
('lock
step')
in
the
sense
that
their
source
states
must
first
be
exited,
then
their
actions
must
be
executed,
and
finally
their
target
states
entered.
If a single atomic state is active, then enabledTransitions will contain only a single transition. If multiple states are active (i.e., we are in a parallel region), then there may be multiple transitions, one per active atomic state (though some states may not select a transition.) In this case, the transitions are taken in the document order of the atomic states that selected them.
procedure microstep(enabledTransitions): exitStates(enabledTransitions) executeTransitionContent(enabledTransitions) enterStates(enabledTransitions)
procedure
exitStates(enabledTransitions)
Compute the set of states to exit. Then remove all the states on statesToExit from the set of states that will have invoke processing done at the start of the next macrostep. (Suppose macrostep M1 consists of microsteps m11 and m12. We may enter state s in m11 and exit it in m12. We will add s to statesToInvoke in m11, and must remove it in m12. In the subsequent macrostep M2, we will apply invoke processing to all states that were entered, and not exited, in M1.) Then convert statesToExit to a list and sort it in exitOrder.
For each state s in the list, if s has a deep history state h, set the history value of h to be the list of all atomic descendants of s that are members in the current configuration, else set its value to be the list of all immediate children of s that are members of the current configuration. Again for each state s in the list, first execute any onexit handlers, then cancel any ongoing invocations, and finally remove s from the current configuration.
procedure exitStates(enabledTransitions): statesToExit = computeExitSet(enabledTransitions) for s in statesToExit: statesToInvoke.delete(s) statesToExit = statesToExit.toList().sort(exitOrder) for s in statesToExit: for h in s.history: if h.type == "deep": f = lambda s0: isAtomicState(s0) and isDescendant(s0,s) else: f = lambda s0: s0.parent == s historyValue[h.id] = configuration.toList().filter(f) for s in statesToExit: for content in s.onexit: executeContent(content) for inv in s.invoke: cancelInvoke(inv) configuration.delete(s)
procedure
computeExitSet(enabledTransitions)
For each transition t in enabledTransitions, if t is targetless then do nothing, else compute the transition's domain. (This will be the source state in the case of internal transitions) or the least common compound ancestor state of the source state and target states of t (in the case of external transitions. Add to the statesToExit set all states in the configuration that are descendants of the domain.
function computeExitSet(transitions) statesToExit = new OrderedSet for t in transitions: if(t.target): domain = getTransitionDomain(t) for s in configuration: if isDescendant(s,domain): statesToExit.add(s) return statesToExit
procedure
executeTransitionContent(enabledTransitions)
For
each
transition
in
the
list
of
enabledTransitions
,
execute
its
executable
content.
procedure executeTransitionContent(enabledTransitions): for t in enabledTransitions: executeContent(t)
procedure
enterStates(enabledTransitions)
First, compute the list of all the states that will be entered as a result of taking the transitions in enabledTransitions. Add them to statesToInvoke so that invoke processing can be done at the start of the next macrostep. Convert statesToEnter to a list and sort it in entryOrder. For each state s in the list, first add s to the current configuration. Then if we are using late binding, and this is the first time we have entered s, initialize its data model. Then execute any onentry handlers. If s's initial state is being entered by default, execute any executable content in the initial transition. If a history state in s was the target of a transition, and s has not been entered before, execute the content inside the history state's default transition. Finally, if s is a final state, generate relevant Done events. If we have reached a top-level final state, set running to false as a signal to stop processing.
procedure enterStates(enabledTransitions): statesToEnter = new OrderedSet() statesForDefaultEntry = new OrderedSet() // initialize the temporary table for default content in history states defaultHistoryContent = new HashTable() computeEntrySet(enabledTransitions, statesToEnter, statesForDefaultEntry, defaultHistoryContent) for s in statesToEnter.toList().sort(entryOrder): configuration.add(s) statesToInvoke.add(s) if binding == "late" and s.isFirstEntry: initializeDataModel(datamodel.s,doc.s) s.isFirstEntry = false for content in s.onentry: executeContent(content) if statesForDefaultEntry.isMember(s): executeContent(s.initial.transition) if defaultHistoryContent[s.id]: executeContent(defaultHistoryContent[s.id]) if isFinalState(s): if isSCXMLElement(s.parent): running = false else: parent = s.parent grandparent = parent.parent internalQueue.enqueue(new Event("done.state." + parent.id, s.donedata)) if isParallelState(grandparent): if getChildStates(grandparent).every(isInFinalState): internalQueue.enqueue(new Event("done.state." + grandparent.id))
procedure
computeEntrySet(transitions,
statesToEnter,
statesForDefaultEntry,
defaultHistoryContent)
Compute the complete set of states that will be entered as a result of taking 'transitions'. This value will be returned in 'statesToEnter' (which is modified by this procedure). Also place in 'statesForDefaultEntry' the set of all states whose default initial states were entered. First gather up all the target states in 'transitions'. Then add them and, for all that are not atomic states, add all of their (default) descendants until we reach one or more atomic states. Then add any ancestors that will be entered within the domain of the transition. (Ancestors outside of the domain of the transition will not have been exited.)
procedure computeEntrySet(transitions, statesToEnter, statesForDefaultEntry, defaultHistoryContent) for t in transitions: for s in t.target: addDescendantStatesToEnter(s,statesToEnter,statesForDefaultEntry, defaultHistoryContent) ancestor = getTransitionDomain(t) for s in getEffectiveTargetStates(t)): addAncestorStatesToEnter(s, ancestor, statesToEnter, statesForDefaultEntry, defaultHistoryContent)
procedure
addDescendantStatesToEnter(state,statesToEnter,statesForDefaultEntry,
defaultHistoryContent)
The purpose of this procedure is to add to statesToEnter 'state' and any of its descendants that the state machine will end up entering when it enters 'state'. (N.B. If 'state' is a history pseudo-state, we dereference it and add the history value instead.) Note that this procedure permanently modifies both statesToEnter and statesForDefaultEntry.
First, If state is a history state then add either the history values associated with state or state's default target to statesToEnter. Then (since the history value may not be an immediate descendant of 'state's parent) add any ancestors between the history value and state's parent. Else (if state is not a history state), add state to statesToEnter. Then if state is a compound state, add state to statesForDefaultEntry and recursively call addStatesToEnter on its default initial state(s). Then, since the default initial states may not be children of 'state', add any ancestors between the default initial states and 'state'. Otherwise, if state is a parallel state, recursively call addStatesToEnter on any of its child states that don't already have a descendant on statesToEnter.
procedure addDescendantStatesToEnter(state,statesToEnter,statesForDefaultEntry, defaultHistoryContent): if isHistoryState(state): if historyValue[state.id]: for s in historyValue[state.id]: addDescendantStatesToEnter(s,statesToEnter,statesForDefaultEntry, defaultHistoryContent) addAncestorStatesToEnter(s, state.parent, statesToEnter, statesForDefaultEntry, defaultHistoryContent) else: defaultHistoryContent[state.parent.id] = state.transition.content for s in state.transition.target: addDescendantStatesToEnter(s,statesToEnter,statesForDefaultEntry, defaultHistoryContent) addAncestorStatesToEnter(s, state.parent, statesToEnter, statesForDefaultEntry, defaultHistoryContent) else: statesToEnter.add(state) if isCompoundState(state): statesForDefaultEntry.add(state) for s in getEffectiveTargetStates(state.initial.transition): addDescendantStatesToEnter(s,statesToEnter,statesForDefaultEntry, defaultHistoryContent) addAncestorStatesToEnter(s, state, statesToEnter, statesForDefaultEntry, defaultHistoryContent) else: if isParallelState(state): for child in getChildStates(state): if not statesToEnter.some(lambda s: isDescendant(s,child)): addDescendantStatesToEnter(child,statesToEnter,statesForDefaultEntry, defaultHistoryContent)
procedure
addAncestorStatesToEnter(state,
ancestor,
statesToEnter,
statesForDefaultEntry,
defaultHistoryContent)
Add to statesToEnter any ancestors of 'state' up to, but not including, 'ancestor' that must be entered in order to enter 'state'. If any of these ancestor states is a parallel state, we must fill in its descendants as well.
procedure addAncestorStatesToEnter(state, ancestor, statesToEnter, statesForDefaultEntry, defaultHistoryContent) for anc in getProperAncestors(state,ancestor): statesToEnter.add(anc) if isParallelState(anc): for child in getChildStates(anc): if not statesToEnter.some(lambda s: isDescendant(s,child)): addDescendantStatesToEnter(child,statesToEnter,statesForDefaultEntry, defaultHistoryContent)
procedure
isInFinalState(s)
Return true if s is a compound <state> and one of its children is an active <final> state (i.e. is a member of the current configuration), or if s is a <parallel> state and isInFinalState is true of all its children.
function isInFinalState(s): if isCompoundState(s): return getChildStates(s).some(lambda s: isFinalState(s) and configuration.isMember(s)) elif isParallelState(s): return getChildStates(s).every(isInFinalState) else: return false
function
getTransitionDomain(transition)
Return the compound state such that 1) all states that are exited or entered as a result of taking 'transition' are descendants of it 2) no descendant of it has this property.
function getTransitionDomain(t) tstates = getEffectiveTargetStates(t) if not tstates: return null elif t.type == "internal" and isCompoundState(t.source) and tstates.every(lambda s: isDescendant(s,t.source)): return t.source else: return findLCCA([t.source].append(tstates))
function
findLCCA(stateList)
The Least Common Compound Ancestor is the <state> or <scxml> element s such that s is a proper ancestor of all states on stateList and no descendant of s has this property. Note that there is guaranteed to be such an element since the <scxml> wrapper element is a common ancestor of all states. Note also that since we are speaking of proper ancestor (parent or parent of a parent, etc.) the LCCA is never a member of stateList.
function findLCCA(stateList): for anc in getProperAncestors(stateList.head(),null).filter(isCompoundStateOrScxmlElement): if stateList.tail().every(lambda s: isDescendant(s,anc)): return anc
function
getEffectiveTargetStates(transition)
Returns the states that will be the target when 'transition' is taken, dereferencing any history states.
function getEffectiveTargetStates(transition) targets = new OrderedSet() for s in transition.target if isHistoryState(s): if historyValue[s.id]: targets.union(historyValue[s.id]) else: targets.union(getEffectiveTargetStates(s.transition)) else: targets.add(s) return targets
function
getProperAncestors(state1,
state2)
If state2 is null, returns the set of all ancestors of state1 in ancestry order (state1's parent followed by the parent's parent, etc. up to an including the <scxml> element). If state2 is non-null, returns in ancestry order the set of all ancestors of state1, up to but not including state2. (A "proper ancestor" of a state is its parent, or the parent's parent, or the parent's parent's parent, etc.))If state2 is state1's parent, or equal to state1, or a descendant of state1, this returns the empty set.
function
isDescendant(state1,
state2)
Returns 'true' if state1 is a descendant of state2 (a child, or a child of a child, or a child of a child of a child, etc.) Otherwise returns 'false'.
function
getChildStates(state1)
Returns a list containing all <state>, <final>, and <parallel> children of state1.
[This section is informative.]
Schemas for SCXML can be found in www.w3.org/2011/04/SCXML . Two sets of schemas are available. One uses Schema 1.0 and is relatively loose, in the sense that it does not enforce all the restrictions contained in this specification. Its master schema is http://www.w3.org/2011/04/SCXML/scxml.xsd . The other set of schemas uses Schema 1.1, in particular the <assert> element, and is stricter. Its master schema is http://www.w3.org/2011/04/SCXML/scxml-strict.xsd .
[This section is informative.]
A number of other XML-based state machine notations have been developed, but none serves the same purpose as SCXML. XMI [UML XMI] is a notation developed for representing UML diagrams, including Harel statecharts. However it is intended as a machine interchange format and is not readily authorable by humans. ebXML [ebXML] is a language for business process specification intended to support B2B e-commerce applications. It contains a state machine language that is in some ways similar to the one presented here, but its syntax and semantics are closely tied to its intended use in e-commerce. It is therefore not suitable as a general-purpose state machine language. XTND [XTND] , also called XML Transition Network Definition, is a notation for simple finite state machines but lacks Harel's notions of hierarchical and parallel states and are thus not suitable for a general-purpose state machine that is semantically equivalent to Harel state charts.
[This section is informative.]
This SCXML document gives an overview of the SCXML language and shows the use of its state machine transition flows:
<?xml version="1.0" encoding="us-ascii"?> <!-- A wrapper state that contains all other states in this file- it represents the complete state machine -->- it represents the complete state machine --> <scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:xi="http://www.w3.org/2001/XInclude" version="1.0" initial="Main" datamodel="ecmascript"> <state id="Main"> <!-- its initial state is Test1 --> <initial> <transition target="Test1"/> </initial> <!-- Really simple state showing the basic syntax. --> <state id="Test1"> <initial> <transition target="Test1Sub1"/> </initial> <!-- Runs before we go into the substate --><onentry><onentry> <log expr="'Inside Test1'"/> </onentry> <!-- Here is our first substate --> <state id="Test1Sub1"> <onentry> <log expr="'Inside Test1Sub1.'"/> </onentry> <onexit> <log expr="'Leaving Test1Sub1'"/> </onexit> <!-- Go to Sub2 on Event1 --> <transition event="Event1" target="Test1Sub2"/> </state><!-- Here is the second substate<!-- Here is the second substate It is final, so Test1 is done when we get here --> <final id="Test1Sub2"/> <!-- We get this event when we reach Test1Sub2. --> <transition event="Test1.done" target="Test2"/> <!-- We run this on the way out of Test1 --> <onexit> <log expr="'Leaving Test1...'"/> </onexit> </state> <state id="Test2" xmlns:xi="http://www.w3.org/2001/XInclude"> <initial> <transition target="Test2Sub1"/> </initial><!-- This time we reference a state<!-- This time we reference a state defined in an external file. --> <xi:include href="SCXMLExamples/Test2Sub1.xml" parse="text"/><final id="Test2Sub2"/> <!-- Test2Sub2 is defined as final, so this event is generated when we reach it --> <transition event="done.state.Test2" next="Test3"/> </state> <state id="Test3"> <initial> <transition target="Test3Sub1"/> </initial> <state id="Test3Sub1"> <onentry> <log expr="'Inside Test3Sub1...'"/> <!-- Send our self an event in 5s --> <send event="Timer" delay="5s"/> </onentry> <!-- Transition on to Test4. This will exit both us and our parent. --> <transition event="Timer" target="Test4"/> <onexit> <log expr="'Leaving Test3Sub1...'"/> </onexit> </state> <onexit> <log expr="'Leaving Test3...'"/> </onexit> </state><state id="Test4"> <onentry> <log expr="'Inside Test4...'"/> </onentry> <initial> <transition target="Test4Sub1"/> </initial> <state id="Test4Sub1"> <onexit> <log expr="'Leaving Test4Sub1...'"/> </onexit> <!-- This transition causes the state to exit immediately after entering Test4Sub1. The transition has no event or guard so it is always active --> <transition target="Test5"/> </state> </state><state id="Test5"> <onentry> <log expr="'Inside Test5...'"/> </onentry> <initial> <transition target="Test5P"/> </initial> <!-- Fire off parallel states. In a more realistic example the parallel substates Test5PSub1 and Test5PSub2 would themselves have substates and would do some real work before transitioning to final substates --> <parallel id="Test5P"> <state id="Test5PSub1" initial="Test5PSub1Final"> <final id="Test5PSub1Final"/> </state> <state id="Test5PSub2" initial="Test5PSub2Final"> <final id="Test5PSub2Final"/> </state> <onexit> <log expr="'all parallel states done'"/> </onexit> </parallel> <!-- The parallel states immediately transition to final substates, so this event is generated immediately. --> <transition event="done.state.Test5P" target="Test6"/> </state><!--<!-- - This state shows invocation of an external component.- We will use CCXML + VoiceXML actions as an example - as it is a good smoke test to show how it all - fits together. - Note: In a real app you would likely - split this over several states but we - are trying to keep it simple here.- We will use CCXML + VoiceXML actions as an example - as it is a good smoke test to show how it all - fits together. - Note: In a real app you would likely - split this over several states but we - are trying to keep it simple here. --> <state id="Test6" xmlns:ccxml="http://www.w3.org/2002/09/ccxml" xmlns:v3="http://www.w3.org/2005/07/vxml3"> <datamodel> <data id="ccxmlid" expr="32459"/> <data id="v3id" expr="17620"/> <data id="dest" expr="'tel:+18315552020'"/> <data id="src" expr="'helloworld2.vxml'"/> <data id="id" expr="'HelloWorld'"/> </datamodel> <onentry> <!-- Use <send> a message to a CCXML Processor asking it to run createcall --> <send target="ccxmlid" type="http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor" event="ccxml:createcall" namelist="dest"/> </onentry><transition event="ccxml:connection.connected"> <!-- Here as a platform-specific extension we use example V3 Custom Action Elements instead of send. The implementation of this logic<transition event="ccxml:connection.connected"> <!-- Here as a platform-specific extension we use example V3 Custom Action Elements instead of send. The implementation of this logic would be platform-dependent. --> <v3:form id="HelloWorld"><v3:block><v3:prompt>Hello World!</v3:prompt></v3:block><v3:block><v3:prompt>Hello World!</v3:prompt></v3:block> </v3:form> </transition> <transition event="v3:HelloWorld.done"><!-- Here we are using the low level <send> element to run a v3 form. Note that the event "v3:HelloWorld.done" is assumed either to be set/sent explicitly by the v3:form code or<!-- Here we are using the low level <send> element to run a v3 form. Note that the event "v3:HelloWorld.done" is assumed either to be set/sent explicitly by the v3:form code or implicitly by some process outside of the v3:form --> <send target="v3id" type="http://www.w3.org/TR/scxml/#BasicEventProcessor" event="v3:formstart" namelist="src id"/> </transition> <transition event="v3:HelloWorld2.done"> <!-- we use _event.data to access data in the event we're processing. Again we assume the v3:HelloWorld2.done is set/sent from outside this document --><ccxml:disconnect connectionid="_event.data.connectionid"/><ccxml:disconnect connectionid="_event.data.connectionid"/> </transition> <transition event="ccxml:connection.disconnected" target="Done"/><transition event="send.failed" target="Done"><!-- If we get an error event we move to the Done state that<!-- If we get an error event we move to the Done state that is a final state. --> <log expr="'Sending to and External component failed'"/> </transition> <onexit> <log expr="'Finished with external component'"/> </onexit> </state> <!-- This final state is an immediate child of Main - when we get here, Main.done is generated. --> <final id="Done"/> <!-- End of Main > --> </state> </scxml>
The example below shows the implementation of a simple microwave oven using SCXML.
<?xml version="1.0"?> <scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" datamodel="ecmascript" initial="off"> <!-- trivial 5 second microwave oven example --> <datamodel> <data id="cook_time" expr="5"/> <data id="door_closed" expr="true"/> <data id="timer" expr="0"/> </datamodel> <state id="off"> <!-- off state --> <transition event="turn.on" target="on"/> </state> <state id="on"> <initial> <transition target="idle"/> </initial> <!-- on/pause state --> <transition event="turn.off" target="off"/> <transition cond="timer >= cook_time" target="off"/> <state id="idle"> <!-- default immediate transition if door is shut --> <transition cond="door_closed" target="cooking"/> <transition event="door.close" target="cooking"> <assign location="door_closed" expr="true"/> <!-- start cooking --> </transition> </state> <state id="cooking"> <transition event="door.open" target="idle"> <assign location="door_closed" expr="false"/> </transition> <!-- a 'time' event is seen once a second --> <transition event="time"> <assign location="timer" expr="timer + 1"/> </transition> </state> </state> </scxml>
The example below shows the implementation of a simple microwave oven using <parallel> and the SCXML In() predicate.
<?xml version="1.0"?> <scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" datamodel="ecmascript"initial="oven">initial="oven"> <!-- trivial 5 second microwave oven example --> <!-- using parallel and In() predicate --> <datamodel> <data id="cook_time" expr="5"/> <data id="door_closed" expr="true"/> <data id="timer" expr="0"/> </datamodel> <parallel id="oven"> <!-- this region tracks the microwave state and timer --> <state id="engine"> <initial> <transition target="off"/> </initial> <state id="off"> <!-- off state --> <transition event="turn.on" target="on"/> </state><state id="on"> <initial> <transition target="idle"/> </initial><!-- on/pause state --><transition event="turn.off" target="off"/> <transition cond="timer >= cook_time" target="off"/><state id="idle"> <transition cond="In('closed')" target="cooking"/> </state><state id="cooking"> <transition cond="In('open')" target="idle"/> <!-- a 'time' event is seen once a second --> <transition event="time"> <assign location="timer" expr="timer + 1"/> </transition> </state> </state> </state> <!-- this region tracks the microwave door state --> <state id="door"> <initial> <transition target="closed"/> </initial> <state id="closed"> <transition event="door.open" target="open"/> </state> <state id="open"> <transition event="door.close" target="closed"/> </state> </state> </parallel> </scxml>
The example below shows the implementation of a simple calculator in SCXML.
<?xml version="1.0" ?> <scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="on" datamodel="ecmascript" name="calc"> <datamodel> <data id="long_expr" /> <data id="short_expr" expr="0" /> <data id="res" /> </datamodel> <state id="wrapper" initial="on"> <state id="on" initial="ready"> <onentry> <send event="DISPLAY.UPDATE" /> </onentry> <state id="ready" initial="begin"> <state id="begin"> <transition event="OPER.MINUS" target="negated1" /> <onentry> <send event="DISPLAY.UPDATE" /> </onentry> </state> <state id="result"> </state> <transition event="OPER" target="opEntered" /> <transition event="DIGIT.0" target="zero1"> <assign location="short_expr" expr="''" /> </transition> <transition event="DIGIT" target="int1"> <assign location="short_expr" expr="''" /> </transition> <transition event="POINT" target="frac1"> <assign location="short_expr" expr="''" /> </transition> </state> <state id="negated1"> <onentry> <assign location="short_expr" expr="'-'" /> <send event="DISPLAY.UPDATE" /> </onentry> <transition event="DIGIT.0" target="zero1" /> <transition event="DIGIT" target="int1" /> <transition event="POINT" target="frac1" /> </state> <state id="operand1"> <state id="zero1"> <transition event="DIGIT" cond="_event.name != 'DIGIT.0'" target="int1" /> <transition event="POINT" target="frac1" /> </state> <state id="int1"> <transition event="POINT" target="frac1" /> <transition event="DIGIT"> <assign location="short_expr" expr="short_expr+_event.name.substr(_event.name.lastIndexOf('.')+1)" /> <send event="DISPLAY.UPDATE" /> </transition> <onentry> <assign location="short_expr" expr="short_expr+_event.name.substr(_event.name.lastIndexOf('.')+1)" /> <send event="DISPLAY.UPDATE" /> </onentry> </state> <state id="frac1"> <onentry> <assign location="short_expr" expr="short_expr+'.'" /> <send event="DISPLAY.UPDATE" /> </onentry> <transition event="DIGIT"> <assign location="short_expr" expr="short_expr+_event.name.substr(_event.name.lastIndexOf('.')+1)" /> <send event="DISPLAY.UPDATE" /> </transition> </state> <transition event="OPER" target="opEntered" /> </state> <state id="opEntered"> <transition event="OPER.MINUS" target="negated2" /> <transition event="POINT" target="frac2" /> <transition event="DIGIT.0" target="zero2" /> <transition event="DIGIT" target="int2" /> <onentry> <raise event="CALC.SUB" /> <send target="_internal" event="OP.INSERT"> <param name="operator" expr="_event.name" /> </send> </onentry> </state> <state id="negated2"> <onentry> <assign location="short_expr" expr="'-'" /> <send event="DISPLAY.UPDATE" /> </onentry> <transition event="DIGIT.0" target="zero2" /> <transition event="DIGIT" target="int2" /> <transition event="POINT" target="frac2" /> </state> <state id="operand2"> <state id="zero2"> <transition event="DIGIT" cond="_event.name != 'DIGIT.0'" target="int2" /> <transition event="POINT" target="frac2" /> </state> <state id="int2"> <transition event="DIGIT"> <assign location="short_expr" expr="short_expr+_event.name.substr(_event.name.lastIndexOf('.')+1)" /> <send event="DISPLAY.UPDATE" /> </transition> <onentry> <assign location="short_expr" expr="short_expr+_event.name.substr(_event.name.lastIndexOf('.')+1)" /> <send event="DISPLAY.UPDATE" /> </onentry> <transition event="POINT" target="frac2" /> </state> <state id="frac2"> <onentry> <assign location="short_expr" expr="short_expr +'.'" /> <send event="DISPLAY.UPDATE" /> </onentry> <transition event="DIGIT"> <assign location="short_expr" expr="short_expr +_event.name.substr(_event.name.lastIndexOf('.')+1)" /> <send event="DISPLAY.UPDATE" /> </transition> </state> <transition event="OPER" target="opEntered"> <raise event="CALC.SUB" /> <raise event="OP.INSERT" /> </transition> <transition event="EQUALS" target="result"> <raise event="CALC.SUB" /> <raise event="CALC.DO" /> </transition> </state> <transition event="C" target="on" /> </state> <transition event="CALC.DO"> <assign location="short_expr" expr="''+ res" /> <assign location="long_expr" expr="''" /> <assign location="res" expr="0" /> </transition> <transition event="CALC.SUB"> <if cond="short_expr!=''"> <assign location="long_expr" expr="long_expr+'('+short_expr+')'" /> </if> <assign location="res" expr="eval(long_expr)" /> <assign location="short_expr" expr="''" /> <send event="DISPLAY.UPDATE" /> </transition> <transition event="DISPLAY.UPDATE"> <log level="0" label="'result'" expr=".short_expr==''?res:short_expr" /> </transition> <transition event="OP.INSERT"> <log level="0" expr="_event.data[0]" /> <if cond="_event.data[0] == 'OPER.PLUS'"> <assign location="long_expr" expr="long_expr+'+'" /> <elseif cond="_event.data[0]=='OPER.MINUS'" /> <assign location="long_expr" expr="long_expr+'-'" /> <elseif cond="_event.data[0]=='OPER.STAR'" /> <assign location="long_expr" expr="long_expr+'*'" /> <elseif cond="_event.data[0]=='OPER.DIV'" /> <assign location="long_expr" expr="long_expr+'/'" /> </if> </transition> </state> </scxml>
The following two SCXML documents demonstrate the use of Invoke and finalize. The first example shows the control flow for a voice portal offering traffic reports.
<?xml version="1.0"?> <?access-control allow="*"?> <scxml version="1.0" initial="Intro" datamodel="ecmascript"> <state id="Intro"> <invoke src="dialog.vxml#Intro" type="vxml2"/> <transition event="success" cond="sessionChrome.playAds" target="PlayAds"/><transition event="success" cond="!sessionChrome.playAds && ANIQuality"<transition event="success" cond="!sessionChrome.playAds && ANIQuality" target="ShouldGoBack"/><transition event="success" cond="!sessionChrome.playAds && !ANIQuality"<transition event="success" cond="!sessionChrome.playAds && !ANIQuality" target="StartOver"/> </state> <state id="PlayAds"> <invoke src="dialog.vxml#PlayAds" type="vxml2"/> <transition event="success" cond="ANIQuality" target="ShouldGoBack"/> <transition event="success" cond="!ANIQuality" target="StartOver"/> </state> <state id="StartOver"> <onenter> <script>enterStartOver();</script> </onenter> <invoke src="dialog.vxml#StartOver" type="vxml2"> <param name="gotItFromANI" expr="gotItFromANI"/> <finalize> <script>finalizeStartOver();</script> </finalize> </invoke> <transition event="success" target="ShouldGoBack"/> <transition event="doOver" target="StartOver"/> <transition event="restart" target="Intro"/> <!-- bail out to caller --> </state> <state id="ShouldGoBack"> <invoke src="dialog.vxml#ShouldGoBack" type="vxml2"> <param name="cityState" expr="cityState"/> <param name="gotItFromANI" expr="gotItFromANI"/> <finalize> <script>finalizeShouldGoBack();</script> </finalize> </invoke> <transition event="highWay" target="HighwayReport"/> <transition event="go_back" target="StartOver"/> <transition event="doOver" target="ShouldGoBack"/> <transition event="restart" target="Intro"/> </state> <state id="HighwayReport"> <invoke src="dialog.vxml#HighwayReport" type="vxml2"> <param name="cityState" expr="cityState"/> <param name="gotItFromANI" expr="gotItFromANI"/> <param name="playHRPrompt" expr="playHRPrompt"/> <param name="metroArea" expr="metroArea"/> <finalize> <script>finalizeHighwayReport();</script> </finalize> </invoke> <transition event="highway" target="PlayHighway"/> <transition event="go_back" target="StartOver"/> <transition event="doOver" target="HighwayReport"/> <transition event="fullreport" target="FullReport"/> <transition event="restart" target="Intro"/> </state> <state id="FullReport"> <invoke src="dialog.vxml#FullReport" type="vxml2"> <param name="cityState" expr="cityState"/> <param name="metroArea" expr="metroArea"/> <finalize> <script>finalizeFullReport();</script> </finalize> </invoke> <transition event="go_back" target="HighwayReport"/> <transition event="new_city" target="StartOver"/> </state> <state id="PlayHighway"> <invoke src="dialog.vxml#PlayHighway" type="vxml2"> <param name="cityState" expr="cityState"/> <param name="curHighway" expr="curHighway"/> <finalize> <script>finalizePlayHighway();</script> </finalize> </invoke> <transition event="go_back" target="HighwayReport"/> </state> </scxml>
The following example shows a the control flow for a blackjack game.
<?xml version="1.0"?> <?access-control allow="*"?> <scxml version="1.0" datamodel="ecmascript" initial="master"> <state id="master"> <initial id="init1"> <transition target="_home"/> </initial> <transition event="new_dealer" target="NewDealer"/> <transition event="mumble" target="_home"/> <!-- bail out to caller --> <transition event="silence" target="_home"/> <!-- bail out to caller --> <state id="_home"> <onenter> <script> _data = {}; </script> </onenter> <invoke src="datamodel.v3#InitDataModel" type="vxml3"> <finalize> <script> var n; for (n in event) { _data[n] = event[n]; } </script> </finalize> </invoke> <transition event="success" target="Welcome"/> </state> <state id="Welcome"> <invoke src="dialog.vxml#Welcome" type="vxml3"> <param name="skinpath" expr="skinpath"/> </invoke> <transition event="success" target="Intro2"/> </state> <state id="Intro2"> <invoke src="dialog.vxml#Intro2" type="vxml3"> <param name="skinpath" expr="skinpath"/> </invoke> <transition event="success" target="EvalDeal"/> </state> <state id="EvalDeal"> <onenter> <script>enterEvalDeal();</script> </onenter> <invoke src="dialog.vxml#EvalDeal" type="vxml3"> <param name="skinpath" expr="skinpath"/> <param name="playercard1" expr="playercard1"/> <param name="playercard2" expr="playercard2"/> <param name="playertotal" expr="blackjack.GetTotalOf('caller').toString()"/> <param name="dealercardshowing" expr="dealercardshowing"/> </invoke> <transition event="success" target="AskHit"/> </state> <state id="AskHit"> <invoke src="dialog.vxml#AskHit" type="vxml3"> <param name="skinpath" expr="skinpath"/> <finalize> <script>finalizeAskHit();</script> </finalize> </invoke> <transition event="hit" target="PlayNewCard"/> <transition event="stand" target="PlayDone"/> </state> <state id="PlayNewCard"> <invoke src="dialog.vxml#PlayNewCard" type="vxml3"> <param name="skinpath" expr="skinpath"/> <param name="playernewcard" expr="playernewcard"/> <param name="playertotal" expr="blackjack.GetTotalOf('caller').toString()"/> </invoke> <transition event="success" cond="blackjack.GetTotalOf('caller') >= 21" target="PlayDone"/> <transition event="success" target="AskHit"/> <!-- less than 21 --> </state> <state id="PlayDone"> <onenter> <script>enterPlayDone();</script> </onenter> <invoke src="dialog.vxml#PlayDone" type="vxml3"> <param name="skinpath" expr="skinpath"/> <param name="gameresult" expr="blackjack.GetGameResult()"/> <param name="dealertotal" expr="blackjack.GetTotalOf('dealer').toString()"/> </invoke> <transition event="playagain" target="Intro2"/> <transition event="quit" target="_home"/> </state> <state id="NewDealer"> <onenter> <script>enterNewDealer();</script> </onenter> <invoke src="dialog.vxml#Dummy" type="vxml3"/> <transition event="success" target="Welcome"/> </state> </state> </scxml>
Since SCXML documents are XML documents, normal XML namespace rules apply to inline content specified with <content> and <data>. In particular, if no namespace is specified, the inline content will be placed in the SCXML namespace. Consider the following example:
<send target="http://example.com/send/target" type="'http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor'"> <content> <a>fffff</a> </content> </send>
The recipient of the message will see the following:
<a xmlns="http://www.w3.org/2005/07/scxml">fffff</a>
The following markup would cause the message to be delivered without namespaces:
<send target="http://example.com/send/target" type="'http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor'"> <content> <a xmlns="">fffff</a> </content> </send>
The recipient of the message will see the following:
<a>fffff</a>
The sender can also specify multiple namespaces:
<send target="http://example.com/send/target" type="'http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor'"> <content> <root xmlns="http://example.com/r" xmlns:a="http://example.com/a" xmlns:b="http://example.com/b" xmlns:c="http://example.com/c"> <a:alpha>1</a:alpha> <b:beta>2</b:beta> <c:gamma>3</c:gamma> </root> </content> </send>
In this case, the receiver would see:
<root xmlns="http://example.com/r"> <alpha xmlns="http://example.com/a">1</alpha> <beta xmlns="http://example.com/b>2</beta> <gamma xmlns="http://example.com/c>3</gamma> </root>
Custom Action Elements can be defined in other specifications/namespaces and are responsible for performing actions on behalf of custom components. Logically Custom Action Elements can be thought of as a collection of actions and handlers to perform specific tasks. An example of this is a CCXML <accept> element that is a Custom Action Element:
<transition event="ccxml:connection.alerting"> <ccxml:accept connectionid="_event.data.connectionid"/> </transition>
This could be written using a <send> element using the following syntax:
<datamodel> <data name="connectionid"/> </datamodel> <transition event="ccxml:connection.alerting"> <assign location="connectionid" expr="_event.data.connectionid"/><send type="ccxml" event="ccxml:accept" namelist="connectionid"/><send type="ccxml" event="ccxml:accept" namelist="connectionid"/> </transition>
A more complicated example might be a CCXML <createcall> where you are both providing variables and getting values back that using only the <send> syntax would be more complex as it would need to be broken over several steps. For example:
<onentry><ccxml:createcall dest="'tel:+18315552020'" connectionid="myConnectionID"/><ccxml:createcall dest="'tel:+18315552020'" connectionid="myConnectionID"/> </onentry>
Would need to be modeled in two steps using <send> as you would need to do something like the following:
<datamodel> <data name="dest" expr="'tel:+18315552020'"/> <data name="connectionid"/> </datamodel> <onentry> <send type="ccxml" event="ccxml:createcall" namelist="dest"/> </onentry> <transition event="ccxml:createcall.success"><assign liocation="connectionid" expr="_event.data.connectionid"/><assign location="connectionid" expr="_event.data.connectionid"/> </transition>
The exact mappings between Custom Action Elements and <send> actions are to be defined in the individual Custom Action Element specifications.
[This section is normative.]
This
appendix
registers
a
new
MIME
media
type,
"
application/scxml+xml
".
The
"
application/scxml+xml
"
media
type
is
being
submitted
to
the
IESG
for
review,
approval,
and
registration
with
IANA.
application
scxml+xml
charset
charset
parameter
of
the
application/xml
media
type
as
specified
in
[RFC
3023]
or
its
successor.
application/scxml+xml
"
may
describe
content
that
has
security
implications
beyond
those
described
here.
However,
if
the
processor
follows
only
the
normative
semantics
of
this
specification,
this
content
will
be
ignored.
Only
in
the
case
where
the
processor
recognizes
and
processes
the
additional
content,
or
where
further
processing
of
that
content
is
dispatched
to
other
processors,
would
security
issues
potentially
arise.
And
in
that
case,
they
would
fall
outside
the
domain
of
this
registration
document.
application/scxml+xml
"
processors
MAY
expect
that
content
received
is
well-formed
XML,
but
processors
SHOULD
NOT
assume
that
the
content
is
valid
SCXML
or
expect
to
recognize
all
of
the
elements
and
attributes
in
the
document.
.scxml
".