Please refer to theerrata for this document, which may include normative corrections.
See alsotranslations.
Copyright© 2015W3C® (MIT,ERCIM,Keio,Beihang). W3Cliability,trademark anddocumentuse rules apply.
This document describes SCXML, or the "State Chart extensibleMarkup Language". SCXML provides a generic state-machine basedexecution environment based on CCXML and Harel State Tables.
This section describes the status of this document at thetime of its publication. Other documents may supersede thisdocument. A list of current W3C publications and the latestrevision of this technical report can be found in theW3C technical reports index athttp://www.w3.org/TR/.
This istheRecommendationof SCXML Version 1.0.It has been published by theVoiceBrowser Working Group, which is part oftheVoice BrowserActivity.
Comments are welcomeatwww-voice@w3.org(archive).SeeW3C mailing list and archiveusage guidelines.
This specification has been widely reviewed(see theThird Last Call Working Draft Disposition of Comments)and satisfies the Working Group's technical requirements.A list of implementations is included intheSCXML 1.0Implementation Report, along with the associated test suite.The Working Group removed an unused reference to ECMASCRIPT-327 basedon a public comment, updated the broken link for E4X, and fixed typos.However, there are no substantial changes from the30 April Proposded Recommendation.
This document has been reviewed by W3C Members, by softwaredevelopers, and by other W3C groups and interested parties, and isendorsed by the Director as a W3C Recommendation. It is a stabledocument and may be used as reference material or cited fromanother document. W3C's role in making the Recommendation is todraw attention to the specification and to promote its widespreaddeployment. This enhances the functionality and interoperability ofthe Web.
This document has been produced as part of theVoice Browser Activity(activity statement),following the procedures set out for theW3C Process. Theauthors of this document are members of theVoice Browser WorkingGroup.
This document was produced by a group operating under the5February 2004 W3C Patent Policy.W3C maintains apublic list of any patent disclosures made inconnection with the deliverables of the group; that page alsoincludes instructions for disclosing a patent. An individual whohas actual knowledge of a patent which the individual believescontainsEssential Claim(s) must disclose the information in accordancewithsection 6 of the W3C Patent Policy.
This document is governed by the14 October 2005 W3CProcess Document.
The sections of this document are normative unless otherwisespecified.
1Terminology
2Overview
3Core Constructs
3.1Introduction
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.11Legal State Configurations andSpecifications
3.12SCXMLEvents
3.13Selecting and ExecutingTransitions
3.14IDs
4Executable Content
4.1Introduction
4.2<raise>
4.3<if>
4.4<elseif>
4.5<else>
4.6<foreach>
4.7<log>
4.8Other ExecutableContent
4.9Evaluation of ExecutableContent
4.10Extensibilityof Executable Content
5Data Model and Data Manipulation
5.1Introduction
5.2<datamodel>
5.3<data>
5.4<assign>
5.5<donedata>
5.6<content>
5.7<param>
5.8<script>
5.9Expressions
5.10SystemVariables
6External Communications
6.1Introduction
6.2<send>
6.3<cancel>
6.4<invoke>
6.5<finalize>
AConformance
A.1Conforming Documents
A.2Conforming Processors
BData Models
B.1The NullData Model
B.2The ECMAScriptData Model
CEvent I/O Processors
C.1SCXMLEvent I/O Processor
C.2Basic HTTP Event I/OProcessor
DAlgorithm for SCXMLInterpretation
ESchema
FRelated Work
GExamples
G.1LanguageOverview
G.2MicrowaveExample
G.3MicrowaveExample (Using parallel)
G.4CalculatorExample
G.5Examples of Invokeand finalize
G.6Inline Content andNamespaces
G.7Custom ActionElements
HMIME Type
H.1Registration of MIME media typeapplication/scxml+xml
H.2FragmentIdentifiers
IReferences
I.1NormativeReferences
I.2InformativeReferences
The key wordsMUST,MUST NOT,
The terms base URI and relative URI are used in thisspecification as they are defined in[RFC2396].
All sections not marked as "informative" are normative.
[This section is informative.]
This document outlines State Chart XML (SCXML), which is ageneral-purpose event-based state machine language that combinesconcepts from CCXML and Harel State Tables. CCXML[CCXML 1.0] is an event-based state machinelanguage designed to support call control features in VoiceApplications (specifically including VoiceXML but not limited toit). The CCXML 1.0 specification defines both a state machine andevent handing syntax and a standardized set of call controlelements. Harel State Tables are a state machine notation that wasdeveloped by the mathematician David Harel[Harel and Politi] and is included in UML[UML 2.3]. They offer a clean and well-thoughtout 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 ofthis document is to combine Harel semantics with an XML syntax thatis a logical extension of CCXML's state and event notation.
3 Core Constructs presents thecore state machine concepts, while4Executable Content contains an extensible set of actionsthat the state machine can take in response to events.5 Data Model and Data Manipulationdefines constructs for storing and modifying data, while6 External Communicationsprovides the capability of communicating with externalentities.
[This section is informative.]
The most basic state machine concepts are3.3 <state>,3.5 <transition> and event(3.12 SCXML Events). Each statecontains a set of transitions that define how it reacts to events.Events can be generated by the state machine itself or by externalentities. In a traditional state machine, the machine is always ina single state. This state is called the active state. When anevent occurs, the state machine checks the transitions that aredefined in the active state. If it finds one that matches theevent, it moves from the active state to the state specified by thetransition (called the "target" of the transition.) Thus the targetstate becomes the new active state.
The Harel state notation defines several extensions to thesebasic notions. First of all, the state machine may take actions (asdefined in4 Executable Content)while taking transitions. Specifically, each state may contain3.8 <onentry> and3.9 <onexit> actions. Transitionsmay also contain actions. If a state machine takes transition Tfrom state S1 to state S2, it first performs the onexit actions inS1, then the actions in T, then the onentry actions in S2.Secondly, in addition to the 'event' attribute that specifies theevent(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 matchesthe 'event' attribute (see3.12.1Event Descriptors for details) and the 'cond' conditionevaluates to true. If the 'event' attribute is missing, thetransition is taken whenever the 'cond' evaluates to true. If morethan one transition matches, the first one in document order willbe taken. Thus, in the following example, the system willtransition to s1 when event e (or e.foo, etc.) occurs if x is equalto 1, but will transition to s2 if event e (or e.foo, etc.) occursand x is not equal to 1, and will go to s3 if any other eventoccurs.
<state id=s"> <transition event="e" cond="x==1"/> <transition event="e"/> <transition event="*"/></state>
One of the most powerful concepts in Harel notation is the ideathat 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 theparent state, while the nested elements are child states. The childstates may themselves have nested children and the nesting mayproceed to any depth. Ultimately we will reach a state that doesnot contain any child states. Such a state is called an atomicstate. When a compound state is active, one and only one of itschild states is active. Conversely, when an child state is active,its parent state must be active too. Thus at any point we have aset of active states, containing an atomic state and all of itsancestors. (We will see in the next section that multiple atomicstates can be active at the same time.)
Compound states also affect how transitions are selected. Whenlooking for transitions, the state machine first looks in the mostdeeply nested active state(s), i.e., in the atomic state(s) thathave no substates. If no transitions match in the atomic state, thestate machine will look in its parent state, then in the parent'sparent, etc. Thus transitions in ancestor states serve as defaultsthat 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 childrenexecute 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 itschildren are active. Specifically, when the state machine entersthe parent <parallel> state, it also enters each child state.The child states execute in parallel in the sense that any eventthat is processed is processed in each child state independently,and each child state may take a different transition in response tothe event. (Similarly, one child state may take a transition inresponse to an event, while another child ignores it.) When all ofthe children reach final states, the <parallel> elementitself is considered to be in a final state, and a completion eventdone.state.id is generated, whereid is the id ofthe <parallel> element.
Transitionswithin the individual child elementsoperate normally. However whenever a transition is taken with atargetoutside the <parallel> element, the<parallel> element and all of its child elements are exitedand the corresponding <onexit> handlers are executed. Thehandlers for the child elements execute first, in document order,followed by those of the parent <parallel> element, followedby an action expression in the <transition> element, and thenthe <onentry> handlers in the "target" state.
In the following example, parallel state 'p' has two children S1and S2. Suppose a transition takes S1's child S12 as a target.(Note that this is permitted even though S12 is not the defaultinitial state for S1 and that S11 is not, in fact, visited in thecourse of this example). Upon this transition, the state machine,in addition to entering S1 and S12, will also enter S1's parallelsibling S2 and its initial state S21. Once the transition has beentaken, p, S1, S2, S12, and S21 will all be active. If event 'e1'occurs, it will cause S12 to transition to S1Final, and S21 totransition to S22. Entering S1Final will cause the eventdone.state.S1 to be generated. At this point, S1 is in a finalstate, but S2 is still active. Now suppose event 'e2' occurs. Thiswill cause S22 to transition to S2Final, and the eventdone.state.S2 will be generated. Furthermore, since all of p'schildren are now in final states, the event 'done.state.p' will begenerated, which will cause the transition contained in p to betriggered, exiting the entire region.
<parallel> <transition event="done.state.p"/> <state initial="S11"> <state> <transition event="e4"/> </state> <state> <transition event="e1"/> </state> <final/> </state> <state initial="S21"> <state id=S21"> <transition event="e1"/> </state> <state> <transition event="e2"#AlgorithmforSCXMLInterpretation">D Algorithm for SCXMLInterpretation for a detailed description of the semanticsof <parallel> and the rest of SCXML.
In the presence of compound states, transitions no longer simplymove from the current active state to a new active state, but fromone set of active states to another. (See3.11 Legal StateConfigurations and Specifications for details.) If thetarget of a transition is an atomic state, the state machine willenter not only the atomic state, but also any of its ancestorstates that are not already active. Conversely, a transition maytake a compound state as its target. In this case, one of thecompound state's children must also become active, but thetransition does not specify which one. In this case we look at thetarget state's3.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 machinewill also enter its default initial state, and so on recursivelyuntil it reaches an atomic state.) The presence of default initialstates provides a form of encapsulation, since a transition mayselect a compound state as its target without understanding itsinternal substate structure.
The default initial state of a compound state may also bespecified via the 'initial' attribute. The only difference betweenthe <initial> element and the 'initial' attribute is that the<initial> element contains a <transition> element whichmay in turn contain executable content which will be executedbefore the default state is entered. If the 'initial' attribute isspecified instead, the specified state will be entered, but noexecutable content will be executed. (If neither the<initial> child or the 'initial' element is specified, thedefault initial state is the first child state in document order.)As an example, suppose that parent state S contains child states S1and S2 in that order. If S specifies S1 as its default initialstate via the 'initial' attribute (or fails to specify any initialstate), then any transition that specifies S as its target willresult 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 asits target. If, on the other hand, S specifies S1 as its defaultinitial state via an <initial> element containing a<transition> with S1 as its target, the <transition>can contain executable content which will execute before thedefault entry into S1. In this case, there is a difference betweena transition that takes S as its target and one that takes S1 asits target. In the former case, but not in the latter, theexecutable content inside the <initial> transition will beexecuted.
A compound state may also have final and history states aschildren.3.7 <final> is usedto signify that the parent state is in some sense "done" with itsprocessing. When a state machine enters a <final> substate ofa compound state, the parent state remains active, but the event"done.state.id" is generated, whereid is thestate id of the parent state. This event can trigger a transitionin any ancestor state (including the parent). If the transitiontakes a target outside the parent state, the"done.state.id" event in effect serves as a signal that itis time to leave the parent state.3.10<history> allows for pause and resume semantics incompound states. Before the state machine exits a compound state,it records the state's active descendants. If the 'type' attributeof the <history> state is set to "deep", the state machinesaves the state's full active descendant configuration, down to theatomic descendant(s). If 'type' is set to "shallow", the statemachine remembers only which immediate child was active. Afterthat, if a transition takes a <history> child of the state asits target, the state machine re-enters not only the parentcompound state but also the state(s) in the saved configuration.Thus a transition with a deep history state as its target returnsto exactly where the state was when it was last exited, while atransition with a shallow history state as a target re-enters thepreviously active child state, but will enter the child's defaultinitial 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 thetransition's source state (which is the state that contains thetransition), the transition's target state(or states), and theLeast Common Compound Ancestor (LCCA) of thesource and target states (which is the closest compound state thatis an ancestor of all the source and target states). When atransition is taken, the state machine will exit all active statesthat are proper descendants of the LCCA, starting with theinnermost one(s) and working up to the immediate descendant(s) ofthe LCCA. (A 'proper descendant' of a state is a child, or a childof a child, or a child of a child of a child, etc.) Then the statemachine enters the target state(s), plus any states that arebetween it and the LCCA, starting with the outermost one (i.e., theimmediate descendant of the LCCA) and working down to the targetstate(s). As states are exited, their <onexit> handlers areexecuted. Then the executable content in the transition isexecuted, followed by the <onentry> handlers of the statesthat are entered. If the target state(s) of the transition is notatomic, the state machine will enter their default initial statesrecursively 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 isstate 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 see3.13Selecting and Executing Transitions andD Algorithm for SCXMLInterpretation.
<state initial="s1"> <state initial="s11"> <onexit> <log expr="'leaving s1'"/> </onexit> <state> <onexit> <log expr="'leaving s11'"/> </onexit> </state> <transition event="e"> <log expr="'executing transition'"/> </transition> </state> <state initial="s21"> <state> <onentry> <log expr="'entering s21'"/> </onentry> </state> <onentry> <log expr="'entering s2'"/> </onentry> </state> <onentry> <log expr="'entering S'"/> <onentry> <onexit> <log expr="'leaving S'"/> <onexit></state>==== log output will be ======>leaving s11leaving s1executing transitionentering s2entering s21
The behavior of transitions with 'type' of "internal" isidentical, except in the case of a transition whose source state isa compound state and whose target(s) is a descendant of the source.In such a case, an internal transition will not exit and re-enterits source state, while an external one will, as shown in theexample below.
<state initial="s1"> <state initial="s11"> <onentry> <log expr="entering S1"/> </onentry> <onexit> <log expr="'leaving s1'"/> </onexit> <state> <onentry> <log expr="entering s11"/> </onentry> <onexit> <log expr="'leaving s11'"/> </onexit> </state> <transition event="e" type="internal"> <log expr="'executing transition'"/> </transition> </state> ==== log output will be ======>leaving s11executing transitionentering s11=== if transition were external, log output would be ====>leaving s11leaving s1executing transitionentering s1entering s11
If the 'target' on a <transition> is omitted, then thevalue of 'type' does not have any effect and taking the transitiondoes not change the state configuration but does invoke theexecutable content that is included in the transition. Note thatthis is different from a <transition> whose 'target' is itssource state. In the latter case, the state is exited andreentered, triggering execution of its <onentry> and<onexit> executable content.
[This section is normative.]
The top-level wrapper element, which carries versioninformation. The actual state machine consists of its children.Note that only one of the children is active at any one time. See3.11 Legal StateConfigurations and Specifications for details.
Name | Required | Attribute Constraints | Type | Default Value | Valid Values | Description |
---|---|---|---|---|---|---|
initial | false | none | IDREFS | none | A legal state specification. See3.11 Legal StateConfigurations and Specifications for details. | The id of the initial state(s) for the document. If notspecified, the default initial state is the first child state indocument order. |
name | false | none | NMTOKEN | none | Any valid NMTOKEN | The name of this state machine. It is for purely informationalpurposes. |
xmlns | true | none | URI | none | The valueMUST be"http://www.w3.org/2005/07/scxml". | |
version | true | none | decimal | none | The valueMUST be "1.0" | |
datamodel | false | none | NMTOKEN | platform-specific | "null", "ecmascript", "xpath" or other platform-definedvalues. | The datamodel that this document requires. "null" denotes theNull datamodel, "ecmascript" the ECMAScript datamodel, and "xpath"the XPath datamodel, as defined inB DataModels. |
binding | false | none | enum | "early" | "early", "late" | The data binding to use. See5.3.3Data Binding for details. |
A conformant SCXML documentMUST have at least one <state>,<parallel> or <final> child. At system initializationtime, the SCXML ProcessorMUST enter the states specified by the'initial' attribute, if it is present. If it is not present, theProcessorMUST enter the first state in document order.PlatformsSHOULD 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[XMLSchema] | The identifier for this state. See3.14IDs 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. See3.11 Legal StateConfigurations and Specifications for details. | The id of the default initial state (or states) for thisstate. |
[Definition: Anatomic state is a<state> that has no <state>, <parallel> or<final> children.]
[Definition: Acompound state isa <state> that has <state>, <parallel>, or<final> children (or a combination of these).]
[Definition: Thedefaultinitial state(s) of a compound state are those specified bythe 'initial' attribute or <initial> element, if either ispresent. Otherwise it is the state's first child state in documentorder. ]
In a conformant SCXML document, a compound state
[This section is normative.]
The <parallel> element encapsulates a set of child stateswhich are simultaneously active when the parent element isactive.
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. See3.14IDs for details. |
[This section is normative.]
Transitions between states are triggered by events andconditionalized via guard conditions. They may contain executablecontent, 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. See3.12.1 Event Descriptors fordetails. | A list of designators of events that trigger this transition.See3.13 Selecting andExecuting Transitions for details on how transitions areselected and executed. SeeE Schemafor the definition of the datatype. | |
cond | false | Boolean expression | 'true' | Any boolean expression. See5.9.1 ConditionalExpressions for details. | The guard condition for this transition. See3.13 Selecting and ExecutingTransitions for details. | |
target | false | . | IDREFS | none | A legal state specification. See3.11 Legal StateConfigurations and Specifications for details. | The identifier(s) of the state or parallel region to transitionto. See3.13 Selecting andExecuting Transitions for details. |
type | false | enum | "external" | "internal" "external" | Determines whether the source state is exited in transitionswhose target state is a descendant of the source state. See3.13 Selecting and ExecutingTransitions for details. |
A conformant SCXML documentMUST specify at least one of 'event', 'cond'or 'target'.3.13 Selecting andExecuting Transitions contains more detail on thesemantics 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> orcompound <state> element.
Name | Required | Attribute Constraints | Type | Default Value | Valid Values | Description |
---|---|---|---|---|---|---|
id | false | ID | none | A valid id as defined in[XMLSchema] | The identifier for this state. See3.14IDs for details. |
When the state machine enters the <final> child of a<state> element, the SCXML Processor
When the state machine reaches the <final> child of an<scxml> element, itMUST terminate. SeeD Algorithm for SCXMLInterpretation for details. If the SCXML session wastriggered as the result by an <invoke> element in anothersession, the SCXML processorMUST generate the eventdone.invoke.id after termination and return it to theother session, whereid is the unique identifier generatedwhen the <invoke> element was executed. See6.4 <invoke> for details.
[This section is normative.]
A wrapper element containing executable content to be executedwhen the state is entered.
The children of the <onentry> handler consist ofexecutable content as defined in4Executable Content.
The SCXML processorMUST execute the <onentry> handlers of astate in document order when the state is entered. In doing so, itMUST treateach handler as a separate block of executable content.
[This section is normative.]
A wrapper element containing executable content to be executedwhen the state is exited.
The children of the <onexit> handler consist of executablecontent as defined in4 ExecutableContent.
The SCXML processorMUST execute the <onexit> handlers of astate in document order when the state is exited. In doing so, itMUST treateach handler as a separate block of executable content.
The <history> pseudo-state allows a state machine toremember its state configuration. A <transition> taking the<history> state as its target will return the state machineto this recorded configuration.
Name | Required | Attribute Constraints | Type | Default Value | Valid Values | Description |
---|---|---|---|---|---|---|
id | false | ID | none | A valid id as defined in[XMLSchema] | Identifier for this pseudo-state. See3.14IDs for details. | |
type | false | enum | "shallow" | "deep" or "shallow" | Determines whether the active atomic substate(s) of the currentstate or only its immediate active substate(s) are recorded. |
If the 'type' of a <history> element is "shallow", theSCXML processorMUST record the immediately active children ofits parent before taking any transition that exits the parent. Ifthe 'type' of a <history> element is "deep", the SCXMLprocessorMUST record the active atomic descendants ofthe parent before taking any transition that exits the parent.After the parent state has been visited for the first time, foreach <history> element, we define the set of states that theprocessor has recorded to be the 'stored state configuration' forthat history state. We also define the states specified by the'target' of the <history> element's <transition> childto be the 'default stored state configuration' for that element. Ifa transition is executed that takes the <history> state asits target, the behavior depends on whether the parent state hasbeen visited before. If it has, the SCXML processor
[This section is normative.]
[Definition: A <state> or<parallel> element isactive if it has been enteredby a transition and has not subsequently been exited.]
[Definition: Thestateconfiguration of a state machine is the set of currentlyactive states. ]
An SCXML document places the state machine in an initial stateconfiguration at initialization time (via the 'initial' attributeof the <scxml> element). Each transition that the statemachine takes thereafter places the state machine in another stateconfiguration (which need not be distinct from the former one.) Aconformant SCXML documentMUST place the state machine only in legalstate configurations, where a legal state configuration is one thatmeets the following conditions:
It follows from this definition that if a state machine is inmore than one atomic state, the atomic states can be traced backthrough a chain of <state> or <parallel> ancestors to asingle <parallel> ancestor.
The 'target' attribute of a <transition> (or the 'initial'attribute of a <state> or <scxml> element) do not inthe 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 thelist. We therefore define a legal state specification to be a setof states such that 1) no state is an ancestor of any other stateon the list, and 2) a full legal state configuration results whenall ancestors and default initial descendants have been added.(Note that the process of adding default initial descendants isrecursive, since the 'initial' value may itself be non-atomic.) Ina conformant SCXML document, the value of an 'initial' attribute orthe 'target' of a <transition>
In a conformant SCXML document, there is an additionalrequirement on the value of the 'initial' attribute of a<state> and on the 'target' of a <transition> inside an<initial> or <history> element: all the states
[This section is normative.]
Events are one of the basic concepts in SCXML since they drivemost transitions. The internal structure of events isplatform-specific as long as the following external interface isobserved:
For the most part, the set of events raised during the executionof an SCXML document is application-specific and generated underauthor control by use of the <raise> and <send>elements. However, certain events are mandatory and generatedautomatically by the interpreter. These are described in3.12.3 List of Errors andEvents. PlatformsMAY extend the names of these automaticallygenerated events by adding a suffix. For example, a platform couldextend done.state.id with a timestamp suffix and generatedone.state.id.timestamp instead. Because any prefix ofdone.state.id is also a prefix ofdone.state.id.timestamp, any transition that matches theformer event will also match the latter.
Like an event name, an event descriptor is a series ofalphanumeric characters segmented into tokens by the "." character.The 'event' attribute of a transition consists of one or more suchevent descriptors separated by spaces.
[Definition: A transitionmatches an event if at least one of its event descriptorsmatches the event's name. ]
[Definition:An event descriptormatches an event name if its string oftokens is an exact match or a prefix of the set of tokens in theevent's name. In all cases, the token matching is case sensitive.]
For example, a transition with an 'event' attribute of "errorfoo" will match event names "error", "error.send","error.send.failed", etc. (or "foo", "foo.bar" etc.) but would notmatch events named "errors.my.custom","errorhandler.mistake", "error.send" or "foobar".
For compatibility with CCXML, and to make the prefix matchingpossibly more clear to a reader of the SCXML document, an eventdescriptorMAY also end with the wildcard '.*', whichmatches zero or more tokens at the end of the processed event'sname. Note that a transition with 'event' of "error", one with"error.", and one with "error.*" are functionally equivalent sincethey are token prefixes of exactly the same set of event names.
An event designator consisting solely of "*" can be used as awildcard matching any sequence of tokens, and thus any event. Notethat this is different from a transition lacking the 'event'attribute altogether. Such an eventless transition does not matchany event, but will be taken whenever its 'cond' attributeevaluates to 'true'. As shown inD Algorithm for SCXMLInterpretation, the SCXML interpreter will check for sucheventless transitions when it first enters a state, before it looksfor transitions driven by internal or external events.
Once the SCXML processor has begun executing a well-formed SCXMLdocument, itMUST signal any errors that occur by raisingSCXML events whose names begin with 'error.'. the processor
The set of error events may be extended in future versions ofthis specification. However, the set of names beginning with'error.platform' is reserved for platform- and application-specificerrors. Therefore applications and platforms
Note however that authors can arrange for otherwise unhandlederrors to cause the interpreter to exit by creating a transitionwith "event" attribute of 'error' and a target of any top-levelfinal state (i.e. one that is a child of <scxml>). If such atransition T is placed in a state S, it will cause the statemachine to terminate on any error that is raised in S or one of itssubstates and is not handled by another transition that is placedin a substate of S or in S and preceding T in document order.
The following events are generated automatically by the SCXMLimplementation under conditions defined elsewhere in thisdocument.
Name | Description | Defined in | See also |
---|---|---|---|
done.state.id | Indicates that the state machine has entered a final substateof stateid. | 3.7 <final> | 3.1 Introduction |
done.invoke.id | Indicates that the invoked process with invokeididhas completed processing. | 6.4 <invoke> | 3.7 <final>,exitInterpreter procedure inD Algorithm for SCXMLInterpretation |
error.communication | Indicates that an error has occurred while trying tocommunicate with an external entity. | 3.12.2 Errors | 6.2 <send>,C.1 SCXML Event I/OProcessor,C.2Basic HTTP Event I/O Processor |
error.execution | Indicates that an error internal to the execution of thedocument has occurred, such as one arising from expressionevaluation. | 3.12.2 Errors | 4.6 <foreach>,5.4 <assign>,5.7 <param>,5.9.1 ConditionalExpressions,5.9.2Location Expressions,5.9.3 Legal Data Values and ValueExpressions,5.9.4Errors in Expressions,5.10System Variables,6.2<send>,B.2.4 LocationExpressions,B.2.7<assign> |
error.platform | Indicates that a platform- or application-specific error hasoccurred. | 3.12.2 Errors |
[This section is normative.]
To simplify the following definitions, we introduce the eventNULL. NULL has no name and is used only in these definitions. Itnever occurs in the event queues of an SCXML Processor. All otherevents have names and are distinct from NULL. (In effect, NULL is apseudo-event that is used in these definitions as a trigger foreventless transitions.)
[Definition: A transition T isenabled by named event E in atomic state S if a) T'ssource state is S or an ancestor of S,and b) T matches E's name(see3.12.1 EventDescriptors) and c) T lacks a 'cond' attribute or its'cond' attribute evaluates to "true". A transition isenabled by NULL in atomic state S if a) T lacks an 'event'attribute, and b) T's source state is S or an ancestor of S and c)T lacks an 'cond' attribute or its 'cond' attribute evaluates to"true". (Note that such a transition can never be enabled by anynamed event.)]
[Definition: Thesource state of atransition is the <state> or <parallel> element that itoccurs in. Theeffective target state(s) of the transitionis the state or set of states specified by its 'target' attribute,with any history states being replaced by the corresponding storedstate configuration or default stored state configuration. Thecomplete target set of a transition consists of all thestates that will be active after the transition is taken. Itcontains the effective target states of the transition plus alltheir ancestors, expanded by the recursive application of thefollowing two operations: 1) if any <parallel> element is amember of the set, any of its children that are not members of theset must be added 2) if any compound <state> is in the setand none of its children is in the set, its default initialstate(s) are added to the set. Any state whose child(ren) are addedto the complete target set by clause 2 is called adefaultentry state. ]
[Definition: Theexit set of a transition in configuration C is the set ofstates that are exited when the transition is taken when the statemachine is in C. If the transition does not contain a 'target', itsexit set is empty. Otherwise (i.e., if the transition contains a'target'), if its 'type' is "external", its exit set consists ofall active states in C that are proper descendants of theLeast Common Compound Ancestor (LCCA) of thesource and target states. Otherwise, if the transition has 'type'"internal", its source state is a compound state, and all itstarget states are proper descendants of its source state, the exitset consists of all active states in C that are proper descendantsof its source state. (If a transition has 'type' of "internal", butits source state is not compound or its target states are not allproper descendants of its source state, its exit set is defined asif it had 'type' of "external". The exit set of a set oftransitions is the union of the exit sets of the individualtransitions. ]
[Definition: Theentry set of a transition in configuration C is the set ofstates that are entered when the transition is taken. If atransition does not contain a 'target', its entry set is empty.Otherwise, it consists of all members of the transition's completetarget set that that are not currently active or are in the exitset. (Thus the entry set consists of all members of thetransition's complete target set that will not be active once thestates in the exit set have been exited.) The entry set of a set oftransitions is the union of the entry sets of the individualtransitions.]
[Definition: A transition T isoptimally enabled by event E in atomic state S if a) T isenabled by E in S and b) no transition that precedes T in documentorder in T's source state is enabled by E in S and c) no transitionis enabled by E in S in any descendant of T's source state.]
[Definition: Two transitions T1 andT2conflict in state configuration C if their exit sets inC have a non-null intersection.]
N.B. If two transitions conflict, then taking them both may leadto an illegal configuration. Hence, only one of the transitions maysafely be taken. In order to resolve conflicts between transitions,we assign priorities to transitions as follows: let transitions T1and T2 conflict, where T1 is optimally enabled in atomic state S1,and T2 is optimally enabled in atomic state S2, where S1 and S2 areboth 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) S1precedes S2 in document order.
[Definition: Theoptimaltransition set enabled by event E in state configuration C isthe largest set of transitions such that a) each transition in theset is optimally enabled by E in an atomic state in C b) notransition conflicts with another transition in the set c) there isno optimally enabled transition outside the set that has a higherpriority than some member of the set. ]
[Definition: Amicrostep consists of the execution of the transitions inan optimal enabled transition set.]
[Definition: Amacrostep is a series of one or more microsteps ending ina configuration where the internal event queue is empty and notransitions are enabled by NULL. ]
To execute a microstep, the SCXML Processor
To exit a state, the SCXML Processor
To enter a state, the SCXML Processor
At startup, the SCXML Processor
After entering the initial configuration, and after executingeach microstep, the SCXML Processor
After checking the state configuration, the Processor
After completing a macrostep, the SCXML Processor
[This section is normative.]
In a conformant SCXML document, the values of all attributes oftype "id"MUST be unique within the session. When suchan attribute is defined to be optional and the author omits it,then, for elements other than <send> and <invoke>, theSCXML processorMUST generate a unique id automatically atdocument load time. (Note that Such system generated IDs cannotnormally be referenced elsewhere in the document because they arenot known to the author. In particular, a state with a systemgenerated ID cannot be the target of a transition.) The ids for<send> and <invoke> are subtly different. In aconformant SCXML document, theyMUST be unique within the session, but in thecase where the author does not provide them, the processor
[This section is informative.]
Executable content allows the state machine todothings. It provides the hooks that allow an SCXML session to modifyits data model and interact with external entities. Executablecontent consists of actions that are performed as part of takingtransitions. In particular, executable content occurs inside<onentry> and <onexit> elements as well as insidetransitions. When the state machine takes a transition, it executesthe <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.
This standard defines elements of executable content which canraise events4.2 <raise>,communicate with external entities6.2<send>, log information4.7<log> execute scripts5.8<script> and modify the data model5.4 <assign>, as well as controlconstructs to conditionalize execution4.3<if> and to iterate over the items in a collection4.6 <foreach>. In addition,SCXML implementations are allowed to define their own,platform-specific executable content (see4.10 Extensibility of ExecutableContent).
[This section is normative.]
The <raise> element raises an event in the current SCXMLsession. Note that the event will not be processed until thecurrent block of executable content has completed and all eventsthat 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 contentelements ec1 and ec2. If event e1 is already in the internal eventqueue when S is entered, the event generated by <raise> willnot be processed until ec1 and ec2 have finished execution and e1has been processed.
Name | Required | Attribute Constraints | Type | Default Value | Valid Values | Description |
---|---|---|---|---|---|---|
event | true | NMTOKEN | none | Specifies the name of the event. This will be matched againstthe 'event' attribute of transitions. |
The SCXML processorMUST place the event that is generated at therear of the session's internal event queue.
[This section is normative.]
<if> is a container for conditionally executedelements.
Name | Required | Attribute Constraints | Type | Default Value | Valid Values | Description |
---|---|---|---|---|---|---|
cond | true | Conditional expression | none | A valid conditional expression | A boolean expression. See5.9.1 ConditionalExpressions for details. |
The behavior of <if> is defined in terms of partitions ofexecutable content. The first partition consists of the executablecontent between the <if> and the first <elseif>,<else> or </if> tag. Each <elseif> tag defines apartition that extends from it to the next <elseif>,<else> or </if> tag. The <else> tag defines apartition that extends from it to the closing </if> tag. In aconformant SCXML document, a partition
When the <if> element is executed, the SCXML processor
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 toiterate through a collection in the data model and to execute theactions 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 iterablecollection. | The <foreach> element will iterate over a shallow copy ofthis collection. | |
item | true | xsd:string | none | Any variable name that is valid in the specified datamodel. | A variable that stores a different item of the collection ineach iteration of the loop. | |
index | false | xsd:string | none | Any variable name that is valid in the specified datamodel. | A variable that stores the current iteration index upon eachiteration of the foreach loop. |
The children of <foreach> consist of one or more items ofexecutable content. (Note that they are considered to be part ofthe same block of executable content as the parent <foreach>element.)
The SCXML processorMUST declare a new variable if the onespecified by 'item' is not already defined. If 'index' is present,the SCXML processorMUST declare a new variable if the onespecified by 'index' is not already defined. If 'array' does notevaluate to a legal iterable collection, or if 'item' does notspecify a legal variable name, the SCXML processor
The SCXML processorMUST act as if it has made a shallow copy ofthe collection produced by the evaluation of 'array'. Specifically,modifications to the collection during the execution of<foreach>MUST NOT affect the iteration behavior. TheSCXML processorMUST start with the first item in thecollection and proceed to the last item in the iteration order thatis defined for the collection. (This order depends on the datamodel in use. ) For each item in turn, the processor
[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-dependentinterpretation. It is intended to provide meta-data about the logstring specified by 'expr'. | ||
expr | false | Value expression | none | An expression returning the value to be logged. See5.9.3 Legal Data Values and ValueExpressions for details. The nature of the loggingmechanism is implementation-dependent. For example, the SCXMLprocessor may convert this value to a convenient format beforelogging it. |
The manner in which the message is displayed or logged isplatform-dependent. The SCXML processor
[This section is normative.]
The following elements of executable content are definedelsewhere in this specification. They
[This section is normative.]
Wherever executable content is permitted, an arbitrary number ofelementsMAY occur. Such a sequence of elements ofexecutable content is called a block. For example, if transition ttakes the state machine from atomic state S1 to atomic state S2,there are three blocks of executable content executed: the one inthe <onexit> handler of S1, the one inside t, and the oneinside the <onentry> handler of S2. The SCXML processor
Events raised during the processing of executable content aretreated like any other events. Note in particular, that errorevents will not be removed from the queue and processed until allevents preceding them in the queue have been processed. See3.12.2 Errors. for details.
[This section is normative.]
ImplementationsMAY provide additional executable contentcorresponding to special features of their implementations. Thefunctionality of such platform-specific content is not restricted,except that itMUST NOT cause transitions or any form ofchange of state (except indirectly, by raising events that triggertransitions). Note that SCXML treats the executable contenttriggered by a transition as a single blocking operation and thatno events are processed until all the executable content hascompleted. For example, when taking a transition into state S, theSCXML processor will not process any events or take any transitionsuntil all <onentry> handlers in S have finished. It is thusimportant that all executable content, including platform-specificextensions, execute swiftly.
In a conformant SCXML document any extensions to executablecontentMUST NOT be defined the 'scxml' namespace.(Note that the schemaE Schemaallows elements from arbitrary namespaces inside blocks ofexecutable content.) The following example shows the incorporationof CCXML functionality (see[CCXML 1.0]) intoSCXML. 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 behaviorof <accept> element is platform-dependent. SeeA.2 Conforming Processorsfor details.
A general method for implementing extensions using the<send> element is presented inG.7 Custom Action Elements.
[This section is informative.]
The Data Model offers the capability of storing, reading, andmodifying a set of data that is internal to the state machine. Thisspecification does not mandate any specific data model, but insteaddefines a set of abstract capabilities that can be realized byvarious languages, such as ECMAScript or XML/XPath. Implementationsmay choose the set of data models that they support. In addition tothe underlying data structure, the data model defines a set ofexpressions as described in5.9Expressions. These expressions are used to refer tospecific locations in the data model, to compute values to assignto those locations, and to evaluate boolean conditions. Finally,the data model includes a set of system variables, as defined in5.10 System Variables, whichare automatically maintained by the SCXML processor.
The data model is defined via the5.2<datamodel> element, which contains zero or more5.3 <data> elements, each of whichdefines a single data element and assigns an initial value to it.These values may be specified in-line or loaded from an externalsource. They can then be updated via the5.4<assign> element. The5.5<donedata>,5.6<content> , and5.7<param> elements can be used to incorporate datainto communications with external entities. Finally, the5.8 <script> element permits theincorporation of a scripting language.
The interpretation of these elements depends on the data modelin question, and not all elements are supported in all data models.For the details of specific data models, seeB Data Models.
[This section is normative.]
<datamodel> is a wrapper element which encapsulates anynumber of <data> elements, each of which defines a singledata object. The exact nature of the data object depends on thedata model language used.
[This section is normative.]
The <data> element is used to declare and populateportions of the data model.
Name | Required | Attribute Constraints | Type | Default Value | Valid Values | Description |
---|---|---|---|---|---|---|
id | true | ID | none | The name of the data item. See3.14IDs for details. | ||
src | false | URI | none | Gives the location from which the data object should befetched. See5.9.3 Legal DataValues and Value Expressions for details. | ||
expr | false | Expression | none | Any valid value expression | Evaluates to provide the value of the data item. See5.9.3 Legal Data Values and ValueExpressions for details. |
The children of the <data> element represent an in-linespecification of the value of the data object.
In a conformant SCXML document, a <data> element
The SCXML ProcessorMUST use any values provided by theenvironment at instantiation time in place of those contained inthe top-level <data> elements. (Top-level data elements arethose that are children of the <datamodel > element that is achild of <scxml>). The manner in which the environmentspecifies these overriding values is platform-dependent.
If the 'expr' attribute is present, the Platform
ImplementationsMAY predeclare and predefine variables in thedata model. However, conformant SCXML implementations
Note that this specification does not define any way to modifythe data model except by<assign>, <finalize>, andpossibly platform-specific elements of executable content. Inparticular, no means is defined for external entities to modify thedata model. In this sense the data model is local to the SCXMLsession and the SCXML Processor checks for eventless transitions(i.e. ones that are triggered based only on the state of the datamodel) only after entering a state or processing an event. Howeverin some deployments it may be possible for external entities tomodify the data model. For example, if SCXML is implemented inJavaScript in a browser, the scope of a document's data model isalways accessible through the main window object and thusJavaScript code elsewhere in the window can modify the data modelindependent of the SCXML interpretation algorithm. Such a situationcan lead to race conditions and unpredictable behavior
Authors control when the initial values are assigned to the dataelements by means of the 'binding' attribute on the <scxml>element. When 'binding' is assigned the value "early" (thedefault), the SCXML ProcessorMUST create all data elements and assign theirinitial values at document initialization time. When 'binding' isassigned the value "late", the SCXML Processor
[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 newvalue. See5.9.2 LocationExpressions for details. | |
expr | false | This attribute must not occur in an <assign> element thathas children. | value expression | none | Any valid value expression | An expression returning the value to be assigned. See5.9.3 Legal Data Values and ValueExpressions for details. |
The children of the <assign>element provide an in-linespecification of the legal data value (see5.9.3 Legal Data Values and ValueExpressions) to be inserted into the data model at thespecified location.
A conformant SCXML documentMUST specify either "expr" or children of<assign>, but not both.
Assignment to a data model is done by using a locationexpression to denote the part of the data model where the insertionis to be made. If the location expression does not denote a validlocation in the data model or if the value specified (by 'expr' orchildren) is not a legal value for the location specified, theSCXML ProcessorMUST place the error 'error.execution' in theinternal event queue. Otherwise, the SCXML Processor
[This section is normative.]
A wrapper element holding data to be returned when a<final> state is entered.
A conformant SCXML documentMUST 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 uponentry into the final state, itMUST evaluate the <donedata> elements<param> or <content> children and place the resultingdata in the _event.data field. The exact format of that data willbe determined by the data model (seeB DataModels for details). In other cases (namely when the<final> element is a child of <scxml> and the statemachine has not been triggered by <invoke>), the SCXMLProcessorSHOULD return the data to the environment inan implementation-dependent manner.
[This section is normative.]
A container element holding data to be passed to an externalservice.
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. See5.9.3Legal Data Values and Value Expressions for details. |
A conformant SCXML document
The use of the <content> element depends on the context inwhich it occurs. See5.5<donedata>,6.2<send> and6.4<invoke> for details. When the SCXML Processorevaluates the <content> element, if the 'expr' valueexpression is present, the Processor
[This section is normative.]
The <param> tag provides a general way of identifying akey and a dynamically calculated value which can be passed to anexternal 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 (see5.9.3Legal Data Values and Value Expressions) that is evaluatedto provide the value. |
location | false | May not occur with 'expr' | location expression | none | Valid location expression | A location expression (see5.9.2 LocationExpressions) that specifies the location in the datamodelto retrieve the value from. |
A conformant SCXML documentMUST specify either the 'expr' attribute of<param> or the 'location' attribute, but
[This section is normative.]
The <script> element adds scripting capability to thestate 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 bedownloaded. |
A conformant SCXML documentMUST specify either the 'src' attribute orchild content, but not both. If 'src' is specified, the SCXMLProcessorMUST download the script from the specifiedlocation at load time. If the script can not be downloaded within aplatform-specific timeout interval, the document is considerednon-conformant, and the platform
The SCXML ProcessorMUST evaluate any <script> element thatis a child of <scxml> at document load time. It
In a conformant SCXML document, the name of any script variableMAY be usedas a location expression (see5.9.2 LocationExpressions).
For an example of a data model incorporating scripting, seeB.2 The ECMAScript DataModel.
[This section is normative.]
SCXML contains three types of expressions, as described below.Different data models will support different languages for theseexpression types, but certain properties of the expressions areconstant across languages and are defined here.
When "late" data binding is used, accessing data substructure inexpressions before the corresponding <data> element is loadedMUST yieldthe same execution-time behavior as accessing non-existent datasubstructure in a loaded <data> instance. Such behavior isdefined by the data expression language in use.
Conditional expressions are used inside the 'cond' attribute of<transition>, <if> and <elseif>. If a conditionalexpression cannot be evaluated as a boolean value ('true' or'false') or if its evaluation causes an error, the SCXML ProcessorMUST treatthe expression as if it evaluated to 'false' and
Location expressions are used to specify a location in the datamodel, e.g. as part of the <assign>, <param>,<send> or <invoke> elements. The exact nature of alocation depends on the data model. If a location expression cannotbe evaluated to yield a valid location, the SCXML processor
A data model definition contains a specification of theunderlying data structure. Such a specification of the datastructure implicitly defines a set of "legal data values", namelythe objects that can be part of such a data structure. Inconjunction with this, the data model definition specifies a set ofvalue expressions which can be evaluated at runtime to return legaldata values. If a value expression does not return a legal datavalue, the SCXML ProcessorMUST place the error 'error.execution' in theinternal event queue.
The SCXML ProcessorMAY reject documents containing syntacticallyill-formed expressions at document load time, or it
[This section is normative.]
The SCXML ProcessorMUST maintain a protected portion of the datamodel containing information that can be useful to applications. Werefer to the items in this special part of the data model as'system variables'. Implementations
The set of system variables may be expanded in future versionsof this specification. Variable names beginning with '_' arereserved for system use. A conformant SCXML document
The concrete realization of these variables in a specific datamodel depends on the language used. The Processor
Events have an internal structure which is reflected in the_event variable. This variable can be accessed to conditiontransitions (via boolean expressions in the 'cond' attribute) or toupdate the data model (via <assign>), etc.
The SCXML ProcessorMUST ensure that the following fields arepresent in all events, whether internal or external.
[This section is informative.]
The External Communications capability allows an SCXML sessionto send and receive events from external entities, and to invokeexternal services.6.2 <send>provides "fire and forget" capability to deliver events and data toany destination, including other SCXML sessions. The 'delay'attribute allows for deferred event delivery and can be used toimplement a timer. The details of event transport as well as theformat of the event and data are determined by the Event I/OProcessor selected. Each implementation will support one or moresuch processor, and the author of the SCXML markup can choose theone that is appropriate for the type of endpoint he is trying toreach.
6.4 <invoke> offers a moretightly coupled form of communication, specifically the ability totrigger a platform-defined service and pass data to it. It and itschild <finalize> are useful in states that model the behaviorof an external service. The <invoke> element is executedafter the state's <onentry> element and causes an instance ofthe external service to be created. The <param> and<content> elements and the 'namelist' attribute can be usedto pass data to the service. Any events that are received by thestate machine from the invoked component during the invocation arepreprocessed by the <finalize> handlerbeforetransitions are selected. The <finalize> code is used tonormalize the form of the returned data and to update the datamodel before the transitions' "event" and "cond" clauses areevaluated.
When parallel states invoke the same external serviceconcurrently, separate instances of the external service will bestarted. They can be distinguished by ids which are associated withthem. Similarly, the ids contained in the events returned from theexternal services can be used to determine which events areresponses to which invocation. Each event that is returned will beprocessed only by the <finalize> in the state that invokedit, but that event is then processed like any other event that thestate machine receives. The finalize code can thus be thought of asa preprocessing stage that applies before the event is added to theevent queue. Note that the event will be passed to all parallelstates to check for transitions.
Since an invocation will be canceled when the state machineleaves the invoking state, it does not make sense to start aninvocation in a state that will be exited immediately. Thereforethe <invoke> element is executed upon entry into the state,but onlyafter checking for eventless transitions andtransitions driven by pending internal events. If any such enabledtransition is found , it is taken and the state is exitedimmediately, without triggering the invocation. Thus invocationsare triggered only when the state machine has reached a stableconfiguration, i.e., one that it will be staying in while it waitsfor external events.
[This section is normative.]
<send> is used to send events and data to externalsystems, including external SCXML Interpreters, or to raise eventsin the current SCXML session.
Name | Required | Attribute Constraints | Type | Default Value | Valid Values | Description |
---|---|---|---|---|---|---|
event | false | Must not occur with 'eventexpr'. If the type ishttp://www.w3.org/TR/scxml/#SCXMLEventProcessor, either thisattribute or 'eventexpr' must be present. | EventType.datatype | none | A string indicating the name of message being generated. SeeE Schema for details on the datatype. | |
eventexpr | false | Must not occur with 'event'. If the type ishttp://www.w3.org/TR/scxml/#SCXMLEventProcessor, either thisattribute or 'event' must be present. | Value expression | none | A dynamic alternative to 'event'. If this attribute is present,the SCXML ProcessorMUST evaluate it when the parent <send>element is evaluated and treat the result as if it had been enteredas 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 platformshould send the event to. See6.2.4 TheTarget 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 ispresent, the SCXML ProcessorMUST evaluate it when the parent <send>element is evaluated and treat the result as if it had been enteredas the value of 'target'. |
type | false | Must not occur with 'typeexpr' | URI | none | The URI that identifies the transport mechanism for themessage. See6.2.5 The Type ofSend for details. | |
typeexpr | false | Must not occur with 'type' | value expression | none | A dynamic alternative to 'type'. If this attribute is present,the SCXML ProcessorMUST evaluate it when the parent <send>element is evaluated and treat the result as if it had been enteredas 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 instanceof <send>. See3.14 IDs fordetails. |
idlocation | false | Must not occur with 'id'. | Location expression | none | Any valid location expression | Any location expression evaluating to a data model location inwhich a system-generated id can be stored. See below fordetails. |
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 dispatchingthe message. SeeE Schema fordetails on the data type. |
delayexpr | false | Must not occur with 'delay' or when the attribute 'target' hasthe value "_internal". | Value expression | None | A value expression which returns a time designation as definedin CSS2[CSS2] format | A dynamic alternative to 'delay'. If this attribute is present,the SCXML ProcessorMUST evaluate it when the parent <send>element is evaluated and treat the result as if it had been enteredas the value of 'delay'. |
namelist | false | Must not be specified in conjunction with <content>element. | List of location expressions | none | List of valid location expressions | A space-separated list of one or more data model locations tobe included as attribute/value pairs with the message. (The name ofthe location is the attribute and the value stored at the locationis the value.) See5.9.2Location Expressions for details. |
A conformant SCXML documentMUST specify exactly one of 'event','eventexpr' and <content>. A conformant document
The SCXML ProcessorMUST include all attributes and valuesprovided by <param> or 'namelist' even if duplicatesoccur.
If 'idlocation' is present, the SCXML Processor
If a delay is specified via 'delay' or 'delayexpr', the SCXMLProcessorMUST interpret the character string as a timeinterval. ItMUST dispatch the message only when the delayinterval elapses. (Note that the evaluation of thesend
tag will return immediately.) The Processor
The target of the <send> operation specifies thedestination of the event. The target is defined by either the'target' or the 'targetexpr' attribute. In most cases, the formatof the target depends on the type of the target (for example a SIPURL for SIP-INFO messages or a HTTP URL for Web Services). If thevalue of the 'target' or 'targetexpr' attribute is not supported orinvalid, the ProcessorMUST place the error error.execution on theinternal event queue. If it is unable to dispatch the message, theProcessorMUST place the error error.communication onthe internal event queue.
The type of the <send> operation specifies the method thatthe SCXML processorMUST use to deliver the message to its target.A conformant SCXML documentMAY use either the 'type' or the 'typeexpr'attribute to define the type. If neither the 'type' nor the'typeexpr' is defined, the SCXML Processor
SCXML ProcessorsMUST support the following type:
Value | Details |
---|---|
http://www.w3.org/TR/scxml/#SCXMLEventProcessor | Target is an SCXML session. The transportmechanism is platform-specific. |
For details on thehttp://www.w3.org/TR/scxml/#SCXMLEventProcessor type, seeC.1 SCXML Event I/OProcessor.
Support for HTTP POST is optional, however Processors thatsupport itmust 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 thehttp://www.w3.org/TR/scxml/#BasicHTTPEventProcessor type, seeC.2 Basic HTTP Event I/OProcessor.
ProcessorsMAY support other types such as web-services,SIP or basic HTTP GET. When they do so, they
The sending SCXML Interpreter
Note that the document author can specify the message content inone of two mutually exclusive ways:
<datamodel><data expr="'tel:+18005551212'"/><data expr="'http://www.example.com/mycontent.txt'"/></datamodel> ...<send type="x-messaging" event="fax.SEND" namelist="content"/>
<send 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 theevent was successfully delivered to its target, but only that theplatform was able to dispatch the event.
[This section is normative.]
The <cancel> element is used to cancel a delayed<send> event. The SCXML Processor
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 delayedevents 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 ispresent, the SCXML ProcessorMUST evaluate it when the parent<cancel> element is evaluated and treat the result as if ithad been entered as the value of 'sendid'. |
A conformant SCXML documentMUST specify exactly one of sendid orsendidexpr.
[This section is normative.]
The <invoke> element is used to create an instance of anexternal 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 belowfor details. |
typeexpr | false | Must not occur with the 'type' attribute. | value expression | none | Any value expression that evaluates to a URI that would be avalid value for 'type'. | A dynamic alternative to 'type'. If this attribute is present,the SCXML ProcessorMUST evaluate it when the parent<invoke> element is evaluated and treat the result as if ithad 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 fordetails. |
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 ProcessorMUST evaluate it when the parent<invoke> element is evaluated and treat the result as if ithad 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 instanceof <invoke>. See3.14 IDs fordetails. |
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.See5.9.2 LocationExpressions for details. |
namelist | false | Must not occur with the <param> element. | List of location expressions | none | List of valid location expressions | A space-separated list of one or more data model locations tobe passed as attribute/value pairs to the invoked service. (Thename of the location is the attribute and the value stored at thelocation is the value.) See6.4.4 DataSharing and5.9.2Location Expressions for details. |
autoforward | false | boolean | false | true or false | A flag indicating whether to forward events to the invokedprocess. See below for details. |
PlatformsMUST support http://www.w3.org/TR/scxml/ as avalue for the 'type' attribute. Platforms
A conformant SCXML documentMAY specify either the 'id' or 'idlocation'attribute, butMUST NOT specify both. If the 'idlocation'attribute is present, the SCXML Processor
When the <invoke> element is executed, if the evaluationof its arguments produces an error, the SCXML Processor
When the 'autoforward' attribute is set to true, the SCXMLProcessorMUST send an exact copy of every externalevent it receives to the invoked process. All the fields specifiedin5.10.1 The InternalStructure of EventsMUST have the same values in the forwardedcopy of the event. The SCXML Processor
The external serviceMAY return multiple events while it isprocessing. If there is a <finalize> handler in the instanceof <invoke> that created the service that generated theevent, the SCXML ProcessorMUST execute the code in that <finalize>handler right before it removes the event from the event queue forprocessing. ItMUST NOT execute the <finalize> handlerin any other instance of <invoke>. Once the external servicehas finished processing itMUST return a special event'done.invoke.id' to the external event queue of theinvoking process, whereid is the invokeid for thecorresponding <invoke> element. The external service
Invoked services of type http://www.w3.org/TR/scxml/,http://www.w3.org/TR/ccxml/, http://www.w3.org/TR/voicexml30/, orhttp://www.w3.org/TR/voicexml21/
The implementation of <invoke>, including communicationbetween parent and child processes, is platform-specific, but thefollowing requirements hold in the case where the invoked processis itself an SCXML session:
[This section is informative.]
The invoked external resource is logically separate from thestate machine that invokes it and does not share data with itunless 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 viaevents. 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-hocbasis. The 'type' attribute of <send> is set to the samevalue as was used in the original <invoke>, while the targethas the special form #_invokeid, whereinvokeidis the identifier corresponding to the original <invoke> tag.For example, in a document using ECMAScript as the data model, thefollowing 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 inthe data model location MyInvoke. Since the target attribute is anexpression which is evaluated, the following code will extract thatidentifier 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 anSCXML session, it can use <send> with the special target'_parent' and type 'scxml' to send events, possibly containingdata, to the invoking session.
[This section is normative.]
The <finalize> element enables an invoking session toupdate its data model with data contained in events returned by theinvoked session. <finalize> contains executable content thatis executed whenever the external service returns an event afterthe <invoke> has been executed. This content is appliedbefore the system looks for transitions that match the event.Within the executable content, the system variable '_event' can beused to refer to the data contained in the event which is beingprocessed.In the case of parallel states, only the finalize code inthe original invoking state is executed.
In a conformant SCXML document, the executable content inside<finalize>MUST NOT raise events or invoke externalactions. In particular, the <send> and <raise> elementsMUSTNOT occur.
If one or more elements of executable content is specified, theSCXML ProcessorMUST execute them each time an event isreceived from the child process that was created by the parent<invoke> element. The Processor
If no executable content is specified, the SCXML Processor
In the example below, a state machine using an ECMAScript datamodel invokes a clock object that returns the current time in aping 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 thatis used in the condition of a transition. Thus <finalize>normalizes the data before the conditions on transitions areevaluated.
<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 SCXMLdocuments.
A SCXML 1.0 processor is a user agent that can parse and processConforming SCXML 1.0 documents.
In a Conforming SCXML 1.0 Processor, the XML parser
A Conforming SCXML 1.0 Processor
When a Conforming SCXML 1.0 Processor encounters anon-conformant document, or one containing non-SCXML elements orattributes which are proprietary, or defined in a non-SCXMLnamespace, its behavior is undefined.
There is no conformance requirement with respect to performancecharacteristics of the SCXML 1.0 Processor.
[This section is normative.]
The 'datamodel' attribute on <scxml> defines the datamodel that the document uses. The data model includes theunderlying data structure plus languages for boolean expressions,location expressions, value expressions, and scripting. Aconformant SCXML documentMAY specify the data model it uses. ConformantSCXML processorsMUST support the null data model, and
The definition of a data model
The value "null" for the 'datamodel' attribute results in anabsent or empty data model. In particular:
The boolean expression language consists of the In predicateonly. It has the form 'In(id)', whereidis the id of a state in the enclosing state machine. The predicateMUSTreturn 'true' if and only if that state is in the current stateconfiguration.
The <foreach> element and the elements defined in5 Data Model and Data Manipulationare not supported in the Null Data Model.
The value 'ecmascript' for the 'datamodel' attribute results inan ECMAScript data model. Implementations that support this valueMUSTsupport the third edition of ECMAScript[ECMASCRIPT-262]. Implementations
For each <data> element in the document, the SCXMLProcessorMUST create an ECMAScript variable objectwhose name is the value of the 'id' attribute of<data>
. In cases where the 'src' attribute orin-line content is provided in the <data> element, then if anindication of the type of the content is available (e.g., via aContent-Type header), then the Processor
The ProcessorMUST place all variables in a single globalECMAScript scope. Specifically, the SCXML Processor
The ProcessorMUST convert ECMAScript expressions used inconditional expressions into their effective boolean value usingthe ToBoolean operator as described in Section 9.2 of[ECMASCRIPT-262].
The following example illustrates this usage.
<state> <datamodel> <data/> </datamodel> <onentry> <assign location="time" expr="currentDateTime()"/> </onentry> <transition cond="yearFromDatetime(time) > 2009"/> <transition/></state>
The SCXML processorMUST define an ECMAScript function named'In()' that takes a stateID as its argument and returns 'true' ifand only if that state is in the current state configuration, asdescribed in5.9.1Conditional Expressions. Here is an example of its use,taken fromG.3 Microwave Example(Using parallel) below:
<transition cond="In('closed')"/>
The SCXML ProcessorMUST accept any ECMAScript left-hand-sideexpression as a location expression. The following exampleillustrates this usage. (Note that the example assumes that thedata loaded from http://example.com/employees.json creates thenecessary data structure, so that employees.employee[12].salaryexists when <assign> is evaluated. If it didn't, theProcessor would raise error.execution and the <assign> wouldhave no effect.)
The SCXML ProcessorMUST accept any ECMAScript expression as avalue expression.
When <content> is a child of <donedata>, theProcessorMUST interpret its value as defined inB.2.8.1 _event.data. When<content> is a child of <send>, the interpretation ofits value depends on the Event I/O Processor. When <content>is a child of <invoke>, the interpretation of its value isplatform-specific.
When evaluating an <assign> element in the ECMAScript datamodel, the SCXML ProcessorMUST replace the existing value at 'location'with the value produced by evaluating 'expr'. If it is unable to doso (for example, if the <assign> element attempts to assignto a read-only attribute), itMUST place the error error.execution on theinternal event queue.
The SCXML ProcessorMUST define an ECMAScript read-only variablefor each system variable defined in5.10 System Variables. The_sessionid
and_name
system variables aredefined as variables with ECMAScript String values. The_event
system variable is defined as an object withproperties for each of the fields defined in5.10.1 The Internal Structureof Events:name
,type
,sendid
,origin
,origintype
,andinvokeid
are String values, whiledata
can be of any type. In cases where thisspecification does not specify a value for one of these fields orstates that the field is empty or has no value, the Processor
_event.data is populated with content provided by an externalevent or by <param> or <content>. In somecircumstances, the entity that generated the event may haveindicated how the data is to be interpreted. In such cases, theProcessorSHOULD try to format the data according tothose indications. Otherwise, if the SCXML Processsor can interpretthe content as key-value pairs, then for each unique key, theProcessorMUST create a property of _event.data whosename is the name of the key-value pair and whose value is the valueof the key-value pair. In the case of duplicate keys, the behavioris platform-specific. (Note that content specified by <param>or delivered as POST parameters via the BasicHTTP Event I/OProcessor consists unambiguously of key-value pairs.) Otherwise(i.e., if the content does not consist of key-value pairs), if theProcessor supports JSON and it can interpret the content as JSON,itMUSTcreate the corresponding ECMAScript object(s) as the value of_event.data. Otherwise, if the Processor can interpret the contentas a valid XML document, itMUST create the corresponding DOM structureand assign it as the value _event.data. Otherwise, the ProcessorMUST treatthe content as a space-normalized string literal and assign it asthe value of _event.data.
Suppose as part of executing a state machine named "myName" witha platform-assigned sessionid "12345", we are processing an eventwith the name "foo.bar" and the following object payload:
{ "answer" : 42 }
Then the underlying ECMAScript data model would have thefollowing 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 eventssent via the BasicHTTP Event I/O Processor, the SCXML Processor isrequired to serialize data from the ECMAScript data model fortransmission to a remote entity. In such cases, if the Processorsupports JSON, and is able to serialize the data in sufficientdetail to allow its reconstruction, the Processor
The SCXML ProcessorMUST accept any ECMAScript program as definedin Section 14 of[ECMASCRIPT-262] asthe content of a <script> element.
In the ECMAScript data model, the SCXML Processor
[This section is normative.]
The SCXML Event I/O Processor is intended to transport messagesbetween SCXML sessions. This specification defines the mappingbetween the parameters in the sending session and the event that israised in the receiving session, but the transport mechanism isplatform-specific.
The sending and receiving SCXML Processors
When using the SCXML Event I/O Processor, SCXML Processors
If neither the 'target' nor the 'targetexpr' attribute isspecified, the SCXML ProcessorMUST add the event to the external event queueof the sending session.
If the sending SCXML session specifies a session that does notexist or is inaccessible, the SCXML Processor
SCXML ProcessorsMUST maintain a'http://www.w3.org/TR/scxml/#SCXMLEventProcessor' entry in the_ioprocessors system variable. The Processor
Here are some examples of SCXML messages sent between SCXMLsessions. Each example shows the original <send> element anda transition handling the resulting event in the receiving SCXMLsession.
EXAMPLE 1: First, here is a message with an XML payloadgenerated by <send> with a 'namelist':
SESSION1 : SENDING SESSIONPattern: "event" attribute with an optional "namelist"<datamodel> <data expr="'mailto:recipient@example.com'"/> <data expr="'http://www.example.com/mycontent.txt'"/> <data> <headers xmlns="http://www.example.com/headers"> <cc>archive@example.com</cc> <subject>Example email</subject> </headers> </data></datamodel> ...<send 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 receivingSCXML session. In this example <my:email> isplatform-specific executable content that sends an email:
SESSION2 : RECEIVING SESSIONPattern: "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> usinginline XML content:
SESSION1 : SENDING SESSIONPattern: "xmlns" attribute with explicit inline content<send 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 thereceiving SCXML session. It uses the special executable content<csta:makecall> to generate a telephone call:
SESSION2 : RECEIVING SESSIONPattern: "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 usingJSON content:
SESSION1 : SENDING SESSIONPattern: "event" attribute with an optional "namelist"<datamodel> <data expr="'mailto:recipient@example.com'"/> <data expr="'http://www.example.com/mycontent.txt'"/> <data src="http://www.example.com/headers.json"/></datamodel> ...<send sendid="send-123" 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 thereceiving SCXML session. In this example, <my:email> isspecial executable content as in the first example.
SESSION2 : RECEIVING SESSIONPattern: "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 minimalinteroperable mechanism for sending and receiving events to andfrom external components and SCXML 1.0 implementations. Support forthe Basic HTTP Event I/O Processor is optional.
An SCXML Processor that supports the Basic HTTP Event I/OProcessorMUST accept messages at the access URI as HTTPPOST requests (see[RFC 2616]). The SCXMLProcessorMUST validate the message it receives and thenMUST buildthe appropriate SCXML event andMUST add it to the external event queue.
If a single instance of the parameter '_scxmleventname' ispresent, the SCXML ProcessorMUST use its value as the name of the SCXMLevent that it raises. If multiple instances of the parameter arepresent, the behavior is platform-specific. If the parameter'_scxmleventname' is not present, the SCXML Processor
After it adds the received message to the appropriate eventqueue, the SCXML ProcessorMUST then indicate the result to the externalcomponent via a success response code 2XX. Note that this responseis sent before the event is removed from the queue and processed.In the cases where the message cannot be formed into an SCXMLevent, the ProcessorMUST return an HTTP error code as defined in[RFC 2616].
An SCXML implementation can send events with the Basic HTTPEvent I/O Processor using the <send> element (see6.2 <send>) with the type attributeset to "http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor" andthe target attribute set to the access URI of the target. Ifneither the 'target' nor the 'targetexpr' attribute is specified,the SCXML ProcessorMUST add the event error.communication to theinternal event queue of the sending session.
The SCXML ProcessorMUST attempt to deliver the message using HTTPmethod "POST" and with parameter values encoded by default in anapplication/x-www-form-urlencoded body (POST method). An SCXMLProcessorMAY support other encodings, and allow them tobe specified in a platform-specific way.
If the 'event' parameter of <send> is defined, the SCXMLProcessorMUST use its value as the value of the HTTPPOST parameter _scxmleventname. If the namelist attribute isdefined, the SCXML ProcessorMUST map its variable names and values to HTTPPOST parameters. If one or more <param> children are present,the SCXML ProcessorMUST map their names (i.e. name attributes)and values to HTTP POST parameters. If a <content> child ispresent, the SCXML ProcessorMUST use its value as the body of themessage.
SCXML Processors that support the BasicHTTP Event I/O ProcessorMUSTmaintain a 'http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor'entry in the _ioprocessors system variable. The Processor
[This section is informative.]
This section contains an illustrative algorithm for theinterpretation of an SCXML document. It is intended as a guide forimplementers only. Implementations are free to implement SCXMLinterpreters in any way they choose.
The following definitions and highlevel principles andconstraint 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 ofsemantics, that SCXML adheres to:
Note that the algorithm assumes a Lisp-like semantics in whichthe empty Set null is equivalent to boolean 'false' and all otherentities are equivalent to 'true'.
These are the abstract datatypes that are used in thealgorithm.
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 f. Returns false for an empty list.function
every(f) // Returns true if every element in the list satisfies the predicate f. Returns true for an empty list.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
some(f) // Returns true if some element in the set satisfies the predicate f. Returns false for an empty set.function
every(f) // Returns true if every element in the set satisfies the predicate f. Returns true for an empty 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 emptydatatype 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 thealgorithm. Their values will be set in the procedureinterpret().
global configurationglobal statesToInvokeglobal datamodelglobal internalQueueglobal externalQueueglobal historyValueglobal runningglobal binding
The following binary predicates are used for determining theorder in which states are entered and exited.
entryOrder
// Ancestors precede descendants, with document order being used to break ties (Note:since ancestors precede descendants, this is equivalent to document order.)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.)
The following binary predicate is used to determine the order inwhich we examine transitions within a state.
documentOrder
// The order in which the elements occurred in the original document.
This section defines the procedures and functions that make upthe core of the SCXML interpreter. N.B. in the code below, thekeyword 'continue' has its traditional meaning in languages like C:break off the current iteration of the loop and proceed to the nextiteration.
procedure
interpret(scxml,id)The purpose of this procedure is to initialize the interpreterand to start processing.
In order to interpret an SCXML document, first (optionally)perform[xinclude] processing and(optionally) validate the document, throwing an exception ifvalidation fails. Then convert initial attributes to<initial> container children with transitions to the statespecified by the attribute. (This step is done purely to simplifythe statement of the algorithm and has no effect on the system'sbehavior. Such transitions will not contain any executablecontent). Initialize the global data structures, including the datamodel. If binding is set to 'early', initialize the data model.Then execute the global <script> element, if any. Finallycall enterStates on the initial configuration, set the globalrunning variable to true and start the interpreter's eventloop.
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 anexternal entity cancels processing. In either case 'running' willbe set to false (see EnterStates, below, for termination byentering a top-level final state.)
At the top of the loop, we have either just entered the statemachine, or we have just processed an external event. Eachiteration through the loop consists of four main steps: 1)Completethe macrostep by repeatedly taking any internally enabledtransitions, namely those that don't require an event or that aretriggered by an internal event. After each suchtransition/microstep, check to see if we have reached a finalstate. 2) When there are no more internally enabled transitionsavailable, the macrostep is done. Execute any <invoke> tagsfor states that we entered on the last iteration through the loop3) 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 anexternal event and then execute any transitions that it triggers.However special preliminary processing is applied to the event ifthe state has executed any <invoke> elements. First, if thisevent was generated by an invoked process, apply <finalize>processing to it. Secondly, if any <invoke> elements haveautoforwarding set, forward the event to them. These steps applybefore the transitions are taken.
This event loop thus enforces run-to-completion semantics, inwhich the system process an external event and then takes all the'follow-up' transitions that the processing has enabled beforelooking for another external event. For example, suppose that theexternal event queue contains events ext1 and ext2 and themachine is in state s1. If processing ext1 takes the machine to s2and generatesinternal event int1, and s2 contains atransition t triggered by int1, the system is guaranteed to take t,no matter what transitions s2 or other states have that would betriggered by ext2. Note that this is true even though ext2 wasalready in the external event queue when int1 was generated. Ineffect, the algorithm treats the processing of int1 as finishing upthe 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.sort(entryOrder): for inv in state.invoke.sort(documentOrder): 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 SCXMLprocess by exiting all active states. If the machine is in atop-level final state, a Done event is generated. (Note that inthis case, the final state will be the only active state.) Theimplementation of returnDoneEvent is platform-dependent, but ifthis session is the result of an <invoke> in another SCXMLsession, returnDoneEvent will cause the eventdone.invoke.<id> to be placed in the external event queue ofthat session, where <id> is the id generated in that sessionwhen the <invoke> was executed.
procedure exitInterpreter(): statesToExit = configuration.toList().sort(exitOrder) for s in statesToExit: for content in s.onexit.sort(documentOrder): executeContent(content) for inv in s.invoke: cancelInvoke(inv) configuration.delete(s) if isFinalState(s) and isScxmlElement(s.parent): returnDoneEvent(s.donedata)
function
selectEventlessTransitions()This function selects all transitions that are enabled in thecurrent configuration that do not require an event trigger. Firstfind a transition with no 'event' attribute whose conditionevaluates totrue
. If multiple matching transitionsare present, take the first in document order. If none are present,search in the state's ancestors in ancestry order until one isfound. As soon as such a transition is found, add it toenabledTransitions, and proceed to the next atomic state in theconfiguration. If no such transition is found in the state or itsancestors, proceed to the next state in the configuration. When allatomic states have been visited and transitions selected, filterthe set of enabled transitions, removing any that are preempted byother 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.sort(documentOrder): 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 collectthe transitions that are enabled by this event in the currentconfiguration.
Create an empty set ofenabledTransitions
. For eachatomic state , find a transition whose 'event' attribute matchesevent
and whose condition evaluates totrue
. If multiple matching transitions are present,take the first in document order. If none are present, search inthe state's ancestors in ancestry order until one is found. As soonas such a transition is found, add it to enabledTransitions, andproceed to the next atomic state in the configuration. If no suchtransition is found in the state or its ancestors, proceed to thenext state in the configuration. When all atomic states have beenvisited and transitions selected, filter out any preemptedtransitions 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.sort(documentOrder): 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 aparallel state is active. In that case, we may have one transitionselected for each of its children. These transitions may conflictwith each other in the sense that they have incompatible targetstates. Loosely speaking, transitions are compatible when each oneis contained within a single <state> child of the<parallel> element. Transitions that aren't contained withina single child force the state machine to leave the<parallel> ancestor (even if they reenter it later). Suchtransitions conflict with each other, and with transitions thatremain within a single <state> child, in that they may havetargets that cannot be simultaneously active. The test thattransitions have non-intersecting exit sets captures thisrequirement. (If the intersection is null, the source and targetsof the two transitions are contained in separate <state>descendants of <parallel>. If intersection is non-null, thenat least one of the transitions is exiting the <parallel>).When such a conflict occurs, then if the source state of one of thetransitions is a descendant of the source state of the other, weselect the transition in the descendant. Otherwise we prefer thetransition that was selected by the earlier state in document orderand discard the other transition. Note that targetless transitionshave empty exit sets and thus do not conflict with any othertransitions.
We start with a list of enabledTransitions and produce aconflict-free list of filteredTransitions. For each t1 inenabledTransitions, we test it against all t2 that are alreadyselected in filteredTransitions. If there is a conflict, then ift1's source state is a descendant of t2's source state, we prefert1 and say that it preempts t2 (so we we make a note to remove t2from filteredTransitions). Otherwise, we prefer t2 since it wasselected in an earlier state in document order, so we say that itpreempts t1. (There's no need to do anything in this case since t2is already in filteredTransitions. Furthermore, once one transitionpreempts t1, there is no need to test t1 against any othertransitions.) Finally, if t1 isn't preempted by any transition infilteredTransitions, remove any transitions that it preempts andadd 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 microstepprocedure
is toprocess a single set of transitions. These may have been enabled byan external event, an internal event, or by the presence or absenceof 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 beexited, then their actions must be executed, and finally theirtarget states entered.
If a single atomic state is active, then enabledTransitions willcontain only a single transition. If multiple states are active(i.e., we are in a parallel region), then there may be multipletransitions, one per active atomic state (though some states maynot select a transition.) In this case, the transitions are takenin 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 onstatesToExit from the set of states that will have invokeprocessing done at the start of the next macrostep. (Supposemacrostep M1 consists of microsteps m11 and m12. We may enter states in m11 and exit it in m12. We will add s to statesToInvoke inm11, and must remove it in m12. In the subsequent macrostep M2, wewill apply invoke processing to all states that were entered, andnot exited, in M1.) Then convert statesToExit to a list and sort itin 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 descendantsof s that are members in the current configuration, else set itsvalue to be the list of all immediate children of s that aremembers of the current configuration. Again for each state s in thelist, first execute any onexit handlers, then cancel any ongoinginvocations, and finally remove s from the currentconfiguration.
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.sort(documentOrder): executeContent(content) for inv in s.invoke: cancelInvoke(inv) configuration.delete(s)
procedure
computeExitSet(enabledTransitions)For each transition t in enabledTransitions, if t is targetlessthen do nothing, else compute the transition's domain. (This willbe the source state in the case of internal transitions) or theleast common compound ancestor state of the source state and targetstates of t (in the case of external transitions. Add to thestatesToExit set all states in the configuration that aredescendants 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 ofenabledTransitions
, execute its executablecontent.
procedure executeTransitionContent(enabledTransitions): for t in enabledTransitions: executeContent(t)
procedure
enterStates(enabledTransitions)First, compute the list of all the states that will be enteredas a result of taking the transitions in enabledTransitions. Addthem to statesToInvoke so that invoke processing can be done at thestart of the next macrostep. Convert statesToEnter to a list andsort it in entryOrder. For each state s in the list, first add s tothe current configuration. Then if we are using late binding, andthis is the first time we have entered s, initialize its datamodel. Then execute any onentry handlers. If s's initial state isbeing entered by default, execute any executable content in theinitial transition. If a history state in s was the target of atransition, and s has not been entered before, execute the contentinside the history state's default transition. Finally, if s is afinal state, generate relevant Done events. If we have reached atop-level final state, set running to false as a signal to stopprocessing.
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.sort(documentOrder): 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 aresult of taking 'transitions'. This value will be returned in'statesToEnter' (which is modified by this procedure). Also placein 'statesForDefaultEntry' the set of all states whose defaultinitial states were entered. First gather up all the target statesin 'transitions'. Then add them and, for all that are not atomicstates, add all of their (default) descendants until we reach oneor more atomic states. Then add any ancestors that will be enteredwithin the domain of the transition. (Ancestors outside of thedomain 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 upentering when it enters 'state'. (N.B. If 'state' is a historypseudo-state, we dereference it and add the history value instead.)Note that this procedure permanently modifies both statesToEnterand statesForDefaultEntry.
First, If state is a history state then add either the historyvalues associated with state or state's default target tostatesToEnter. Then (since the history value may not be animmediate descendant of 'state's parent) add any ancestors betweenthe history value and state's parent. Else (if state is not ahistory state), add state to statesToEnter. Then if state is acompound state, add state to statesForDefaultEntry and recursivelycall addStatesToEnter on its default initial state(s). Then, sincethe default initial states may not be children of 'state', add anyancestors between the default initial states and 'state'.Otherwise, if state is a parallel state, recursively calladdStatesToEnter on any of its child states that don't already havea 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) for s in historyValue[state.id]: 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) for s in state.transition.target: addAncestorStatesToEnter(s, state.parent, statesToEnter, statesForDefaultEntry, defaultHistoryContent) else: statesToEnter.add(state) if isCompoundState(state): statesForDefaultEntry.add(state) for s in state.initial.transition.target: addDescendantStatesToEnter(s,statesToEnter,statesForDefaultEntry, defaultHistoryContent) for s in state.initial.transition.target: 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 notincluding, 'ancestor' that must be entered in order to enter'state'. If any of these ancestor states is a parallel state, wemust 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 itschildren is an active <final> state (i.e. is a member of thecurrent configuration), or if s is a <parallel> state andisInFinalState 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 areexited or entered as a result of taking 'transition' aredescendants 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)TheLeast Common Compound Ancestoris the <state> or <scxml> element s such that s is aproper ancestor of all states on stateList and no descendant of shas this property. Note that there is guaranteed to be such anelement since the <scxml> wrapper element is a commonancestor of all states. Note also that since we are speaking ofproper ancestor (parent or parent of a parent, etc.) the LCCA isnever 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' istaken, 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 inancestry order (state1's parent followed by the parent's parent,etc. up to an including the <scxml> element). If state2 isnon-null, returns in ancestry order the set of all ancestors ofstate1, up to but not including state2. (A "proper ancestor" of astate is its parent, or the parent's parent, or the parent'sparent's parent, etc.))If state2 is state1's parent, or equal tostate1, 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, ora 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 inwww.w3.org/2011/04/SCXML.Two sets of schemas are available. One uses Schema 1.0 and isrelatively loose, in the sense that it does not enforce all therestrictions contained in this specification. Its master schema ishttp://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 ishttp://www.w3.org/2011/04/SCXML/scxml-strict.xsd.
[This section is informative.]
A number of other XML-based state machine notations have beendeveloped, but none serves the same purpose as SCXML. XMI[UML XMI] is a notation developed for representingUML diagrams, including Harel statecharts. However it is intendedas a machine interchange format and is not readily authorable byhumans. ebXML[ebXML] is a language forbusiness process specification intended to support B2B e-commerceapplications. It contains a state machine language that is in someways similar to the one presented here, but its syntax andsemantics are closely tied to its intended use in e-commerce. It istherefore not suitable as a general-purpose state machine language.XTND[XTND], also called XML Transition NetworkDefinition, is a notation for simple finite state machines butlacks Harel's notions of hierarchical and parallel states and arethus not suitable for a general-purpose state machine that issemantically equivalent to Harel state charts.
[This section is informative.]
This SCXML document gives an overview of the SCXML language andshows 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 --> <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> <!-- its initial state is Test1 --> <initial> <transition/> </initial> <!-- Really simple state showing the basic syntax. --> <state> <initial> <transition/> </initial> <!-- Runs before we go into the substate --> <onentry> <log expr="'Inside Test1'"/> </onentry> <!-- Here is our first substate --> <state> <onentry> <log expr="'Inside Test1Sub1.'"/> </onentry> <onexit> <log expr="'Leaving Test1Sub1'"/> </onexit> <!-- Go to Sub2 on Event1 --> <transition event="Event1"/> </state> <!-- Here is the second substate It is final, so Test1 is done when we get here --> <final/> <!-- We get this event when we reach Test1Sub2. --> <transition event="Test1.done"/> <!-- We run this on the way out of Test1 --> <onexit> <log expr="'Leaving Test1...'"/> </onexit> </state> <state xmlns:xi="http://www.w3.org/2001/XInclude"> <initial> <transition/> </initial> <!-- This time we reference a state defined in an external file. --> <xi:include href="SCXMLExamples/Test2Sub1.xml" parse="text"/> <final/> <!-- Test2Sub2 is defined as final, so this event is generated when we reach it --> <transition event="done.state.Test2" next="Test3"/> </state> <state> <initial> <transition/> </initial> <state> <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"/> <onexit> <log expr="'Leaving Test3Sub1...'"/> </onexit> </state> <onexit> <log expr="'Leaving Test3...'"/> </onexit> </state> <state> <onentry> <log expr="'Inside Test4...'"/> </onentry> <initial> <transition/> </initial> <state> <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/> </state> </state> <state> <onentry> <log expr="'Inside Test5...'"/> </onentry> <initial> <transition/> </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> <state initial="Test5PSub1Final"> <final/> </state> <state initial="Test5PSub2Final"> <final/> </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"/> </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. --> <state xmlns:ccxml="http://www.w3.org/2002/09/ccxml" xmlns:v3="http://www.w3.org/2005/07/vxml3"> <datamodel> <data expr="32459"/> <data expr="17620"/> <data expr="'tel:+18315552020'"/> <data expr="'helloworld2.vxml'"/> <data expr="'HelloWorld'"/> </datamodel> <onentry> <!-- Use <send> a message to a CCXML Processor asking it to run createcall --> <send 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 would be platform-dependent. --> <v3:form> <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 implicitly by some process outside of the v3:form --> <send 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"/> </transition> <transition event="ccxml:connection.disconnected"/> <transition event="send.failed"> <!-- 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/> <!-- End of Main > --> </state></scxml>
The example below shows the implementation of a simple microwaveoven 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 expr="5"/> <data expr="true"/> <data expr="0"/> </datamodel> <state> <!-- off state --> <transition event="turn.on"/> </state> <state> <initial> <transition/> </initial> <!-- on/pause state --> <transition event="turn.off"/> <transition cond="timer >= cook_time"/> <state> <!-- default immediate transition if door is shut --> <transition cond="door_closed"/> <transition event="door.close"> <assign location="door_closed" expr="true"/> <!-- start cooking --> </transition> </state> <state> <transition event="door.open"> <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 microwaveoven 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"> <!-- trivial 5 second microwave oven example --> <!-- using parallel and In() predicate --> <datamodel> <data expr="5"/> <data expr="true"/> <data expr="0"/> </datamodel> <parallel> <!-- this region tracks the microwave state and timer --> <state> <initial> <transition/> </initial> <state> <!-- off state --> <transition event="turn.on"/> </state> <state> <initial> <transition/> </initial> <!-- on/pause state --> <transition event="turn.off"/> <transition cond="timer >= cook_time"/> <state> <transition cond="In('closed')"/> </state> <state> <transition cond="In('open')"/> <!-- 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> <initial> <transition/> </initial> <state> <transition event="door.open"/> </state> <state> <transition event="door.close"/> </state> </state> </parallel></scxml>
The example below shows the implementation of a simplecalculator 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 /> <data expr="0" /> <data /> </datamodel> <state initial="on"> <state initial="ready"> <onentry> <send event="DISPLAY.UPDATE" /> </onentry> <state initial="begin"> <state> <transition event="OPER.MINUS" /> <onentry> <send event="DISPLAY.UPDATE" /> </onentry> </state> <state> </state> <transition event="OPER" /> <transition event="DIGIT.0"> <assign location="short_expr" expr="''" /> </transition> <transition event="DIGIT"> <assign location="short_expr" expr="''" /> </transition> <transition event="POINT"> <assign location="short_expr" expr="''" /> </transition> </state> <state> <onentry> <assign location="short_expr" expr="'-'" /> <send event="DISPLAY.UPDATE" /> </onentry> <transition event="DIGIT.0" /> <transition event="DIGIT" /> <transition event="POINT" /> </state> <state> <state> <transition event="DIGIT" cond="_event.name != 'DIGIT.0'" /> <transition event="POINT" /> </state> <state> <transition event="POINT" /> <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> <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" /> </state> <state> <transition event="OPER.MINUS" /> <transition event="POINT" /> <transition event="DIGIT.0" /> <transition event="DIGIT" /> <onentry> <raise event="CALC.SUB" /> <send event="OP.INSERT"> <param name="operator" expr="_event.name" /> </send> </onentry> </state> <state> <onentry> <assign location="short_expr" expr="'-'" /> <send event="DISPLAY.UPDATE" /> </onentry> <transition event="DIGIT.0" /> <transition event="DIGIT" /> <transition event="POINT" /> </state> <state> <state> <transition event="DIGIT" cond="_event.name != 'DIGIT.0'" /> <transition event="POINT" /> </state> <state> <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" /> </state> <state> <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"> <raise event="CALC.SUB" /> <raise event="OP.INSERT" /> </transition> <transition event="EQUALS"> <raise event="CALC.SUB" /> <raise event="CALC.DO" /> </transition> </state> <transition event="C" /> </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 Invokeand finalize. The first example shows the control flow for a voiceportal offering traffic reports.
<?xml version="1.0"?><?access-control allow="*"?><scxml version="1.0" initial="Intro" datamodel="ecmascript"> <state> <invoke src="dialog.vxml#Intro" type="vxml2"/> <transition event="success" cond="sessionChrome.playAds"/> <transition event="success" cond="!sessionChrome.playAds && ANIQuality" /> <transition event="success" cond="!sessionChrome.playAds && !ANIQuality" /> </state> <state> <invoke src="dialog.vxml#PlayAds" type="vxml2"/> <transition event="success" cond="ANIQuality"/> <transition event="success" cond="!ANIQuality"/> </state> <state> <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"/> <transition event="doOver"/> <transition event="restart"/> <!-- bail out to caller --> </state> <state> <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"/> <transition event="go_back"/> <transition event="doOver"/> <transition event="restart"/> </state> <state> <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"/> <transition event="go_back"/> <transition event="doOver"/> <transition event="fullreport"/> <transition event="restart"/> </state> <state> <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"/> <transition event="new_city"/> </state> <state> <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"/> </state></scxml>
The following example shows a the control flow for a blackjackgame.
<?xml version="1.0"?><?access-control allow="*"?><scxml version="1.0" datamodel="ecmascript" initial="master"> <state> <initial> <transition/> </initial> <transition event="new_dealer"/> <transition event="mumble"/> <!-- bail out to caller --> <transition event="silence"/> <!-- bail out to caller --> <state> <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"/> </state> <state> <invoke src="dialog.vxml#Welcome" type="vxml3"> <param name="skinpath" expr="skinpath"/> </invoke> <transition event="success"/> </state> <state> <invoke src="dialog.vxml#Intro2" type="vxml3"> <param name="skinpath" expr="skinpath"/> </invoke> <transition event="success"/> </state> <state> <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"/> </state> <state> <invoke src="dialog.vxml#AskHit" type="vxml3"> <param name="skinpath" expr="skinpath"/> <finalize> <script>finalizeAskHit();</script> </finalize> </invoke> <transition event="hit"/> <transition event="stand"/> </state> <state> <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"/> <transition event="success"/> <!-- less than 21 --> </state> <state> <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"/> <transition event="quit"/> </state> <state> <onenter> <script>enterNewDealer();</script> </onenter> <invoke src="dialog.vxml#Dummy" type="vxml3"/> <transition event="success"/> </state> </state></scxml>
Since SCXML documents are XML documents, normal XML namespacerules apply to inline content specified with <content> and<data>. In particular, if no namespace is specified, theinline content will be placed in the SCXML namespace. Consider thefollowing example:
<send 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 deliveredwithout namespaces:
<send 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 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 otherspecifications/namespaces and are responsible for performingactions on behalf of custom components. Logically Custom ActionElements can be thought of as a collection of actions and handlersto 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 thefollowing 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"/> </transition>
A more complicated example might be a CCXML <createcall>where you are both providing variables and getting values back thatusing only the <send> syntax would be more complex as itwould need to be broken over several steps. For example:
<onentry> <ccxml:createcall dest="'tel:+18315552020'" connectionid="myConnectionID"/> </onentry>
Would need to be modeled in two steps using <send> as youwould 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 location="connectionid" expr="_event.data.connectionid"/></transition>
The exact mappings between Custom Action Elements and<send> actions are to be defined in the individual CustomAction Element specifications.
[This section is normative.]
This appendix registers a new MIME media type,"application/scxml+xml
".
The "application/scxml+xml
" media type is beingsubmitted to the IESG for review, approval, and registration withIANA.
application
scxml+xml
charset
charset
parameter of theapplication/xml
media type as specified in[RFC 3023] or itssuccessor.application/scxml+xml
" may describe content that hassecurity implications beyond those described here. However, if theprocessor follows only the normative semantics of thisspecification, this content will be ignored. Only in the case wherethe processor recognizes and processes the additional content, orwhere further processing of that content is dispatched to otherprocessors, would security issues potentially arise. And in thatcase, they would fall outside the domain of this registrationdocument.application/scxml+xml
" processors MAYexpect that content received is well-formed XML, but processorsSHOULD NOT assume that the content is valid SCXML or expect torecognize all of the elements and attributes in the document..scxml
".