摘要
这篇文档描述了SCXML,或者说是“状态图可扩展标记语言”。SCXML基于CCXML和Harel State Tables为状态机提供了一个一般性的可执行环境,
概述
这篇文档描述的SCXML,是一种基于事件的状态机语言。它是CCXML和Harel State Tables 结合的产物。CCXML是一种基于事件的状态机语言,被设计用来在语音应用中支持通话控制。CCXML1.0规范定义了一个状态机和事件处理语法以及一系列的通话控制元素。Harel State Table由David Harel于1987年提出的一种状态机记号,后来UML中的状态机沿用了这些记号。Harel State Tables 提供了一个简洁、语义良好和功能强大的控制结构。这篇文章就是使用XML语法和Harel State Table语义来描述CCXML中状态和事件转移的逻辑概念
核心结构
[这部分是非正式的]
介绍
基础的状态机概念
组合状态
并行状态
初始化,终止和历史状态
转移类型
scxml
[这部分是规范的]
文档的顶层元素,携带了版本信息。一个状态机由<scxml>和他的孩子元素共同组成。
提示:任何时候只有一个孩子是处于活跃状态。
属性
名字 |
必须 |
约束 |
类型 |
默认值 |
有效值 |
描述 |
inital |
False |
None |
Id引用 |
None |
|
初始状态的id值,如果没有指定,默认的初始状态是文档中第一个孩子状态 |
name |
False |
None |
名称记号 |
None |
|
任何有效的名称记号 状态机的名字 |
xmlns |
True |
None |
URI |
None |
必须是:“http://w3.org/005/07/scxml” |
|
version |
True |
None |
数字 |
None |
必须是:“1.0” |
|
datamodel |
False |
None |
名称记号 |
自定义 |
“null”,“ecmascript”,”xpath”,或者实现者定义的值 |
表示状态机中的数据模型 |
binding |
False |
None |
Enum |
early |
“early”,”late” |
指明数据绑定的时间 |
孩子元素
名字名字 |
说明 |
出现次数 |
<state> |
一个组合状态或者原子状态 |
0…* |
<parallel> |
一个并行状态 |
0…* |
<final> |
一个顶层的终止状态,当状态机达到这个状态必须终止 |
0…* |
<datamodel> |
定义了部分或者所有的数据模型 |
0…1 |
<script> |
提供了全局脚本的能力 |
0…1 |
说明
一个结构良好的SCXML文档必须至少有一个<state>,或者<parallel>或者<final>孩子,在系统初始化的时候,如果执行呢‘initial’属性,SCXML Processer必须进入 ‘initial’属性指定的状态中。如果没有执行‘initial’属性,Processer必须进入文档中的第一个状态。平台应该顶一个默认的datamodel值。
state
[这部分是规范的]
属性
名字 |
必须 |
约束 |
类型 |
默认值 |
有效值 |
描述 |
id |
False |
None |
Id引用 |
None |
一个有效的id定义 |
状态的标识符 |
initial |
False |
不能和<initial>元素同时指定,不能在原子状态内部指定 |
名称记号 |
None |
|
另一个状态的ID标识符,但是要保证配置后是合法的状态机配置 复合状态或者并发状态默认初始化的状态 |
孩子元素
名字名字 |
说明 |
出现次数 |
<onentry> |
可选的元素,用来呈现进入这个状态时可执行内容 |
0…* |
<onexit> |
可选的元素,用来呈现退出这个状态时可执行内容 |
0…* |
<transition> |
定义了一个转移,源状态是当前状态 |
0…* |
<initial> |
复合状态机的子状态,定义了默认的初始化状态 |
0…1 |
<parallel> |
定义了并发子状态 |
0…* |
<final> |
定义了一个final子状态 |
0…* |
<history> |
一个伪状态机,记录了上转移出此状态机的子孙状态 |
0…* |
<datamodel> |
定义了部分或者所有的数据模型 |
0…1 |
<invoke> |
调用一个外部服务 |
0…* |
定义
定义1 :一个原子(atomic)状态是一个没有<state>元素,<parallel>或者<final>孩子的<state>
定义2 :一个复合(compound)状态是一个有<state>元素,<parallel>或者<final>孩子(或者这几者的组合)的<state>
定义3 :一个复合状态的默认的初始化状态由‘initial’属性或者<initial>元素指定,如果前两者都没有出现,那么初始化状态就是当前复合状态的按文档顺序来说的第一个孩子状态
说明
在一个结构良好的SCXML文档,一个复合状态必须制定‘initial’属性或者一个<initial>元素,但是二者不能同时指定。
parallel
[这部分是规范的]
<parallel>元素封装了一系列的孩子状态,如果并行状态是处于活跃状态,当孩子元素的父元素是active的,这些孩子状态会同时处于active状态
属性
名字 |
必须 |
约束 |
类型 |
默认值 |
有效值 |
描述 |
id |
False |
|
Id |
None |
一个有效的id定义 |
状态的标识符 |
initial |
False |
不能和?initial>元素同时指定,不能在原子状态内部指定 |
名称记号 |
None |
|
另一个状态的ID标识符,但是要保证配置后是合法的状态机配置 复合状态或者并发状态默认初始化的状态 |
孩子元素
名字名字 |
说明 |
出现次数 |
<onentry> |
可选的元素,用来呈现进入这个状态时可执行内容 |
0…* |
<onexit> |
可选的元素,用来呈现退出这个状态时可执行内容 |
0…* |
<transition> |
定义了一个转移,源状态是当前状态 |
0…* |
<initial> |
复合状态机的子状态,定义了默认的初始化状态 |
0…1 |
<parallel> |
定义了并发子状态 |
0…* |
<final> |
定义了一个final子状态 |
0…* |
<history> |
一个伪状态机,记录了上转移出此状态机的子孙状态 |
0…* |
<datamodel> |
定义了部分或者所有的数据模型 |
0…1 |
<invoke> |
调用一个外部服务 |
0…* |
transition
[这部分是规范的]
states 之间的Transition是有 事件(Events)和条件(Condition)触发的。在Transition中可以包含可执行内容(executable content),当转移发生的时候这些可执行内容将会执行。
属性
名字 |
必须 |
约束 |
类型 |
默认值 |
有效值 |
描述 |
event |
False |
|
EventTypes.datatype |
None |
一个使用”.”分割符指定的字符串 |
触发这个转移的事件 |
cond |
False |
|
Boolean表达式 |
True |
任何boolean表达式 |
转移的守护条件 |
target |
False |
|
ID引用 |
None |
|
转向的状态或者并行状态的标识符 |
type |
False |
|
Enum |
external |
“internal”,”external” |
当目标状态是子孙状态的时候,决定是否源状态要不要退出再重新进入 |
孩子元素
可执行内容都可以作为孩子元素,
说明
一份结构良好的SCXML文档必须至少指定 ‘event’,’cond’ 或者’target’中的一个。
initial
[这部分是规范的]
这个元素表示一个复合状态默认的初始化状态
属性
本元素没有属性
孩子元素
名字名字 |
说明 |
出现次数 |
<transition> |
定义了一个转移,这个转移不能指定cond和event属性,但是必须指定一个非空的有效的target属性,属性值必须是当前容器状态的子孙状态.可以包含可执行内容 |
1 |
final
[这部分是规范的]
这个元素表示<scxml>或者复合状态中的最终状态
属性
名字 |
必须 |
约束 |
类型 |
默认值 |
有效值 |
描述 |
id |
False |
|
Id |
None |
一个有效的id值 |
状态的标识符 |
孩子元素
名字名字 |
说明 |
出现次数 |
<onentry> |
可选的元素,用来呈现进入这个状态时可执行内容 |
0…* |
<onexit> |
可选的元素,用来呈现退出这个状态时可执行内容 |
0…*(个人觉得<scxml>节点下的<final>元素不应该有<onexit>)孩子节点 |
<donedata> |
指定数据被包含在done.state.id 或者 done.invoke.id 事件里面 |
|
说明
当状态机进入一个<state>元素的<final>孩子节点的时候,SCXML Processor在完成了<onentry>元素中可执行内容之后 必须生成一个done.state.id事件,id是父亲状态的id值。然后,如果父状态是一个<parallel>的孩子元素,并且所有的<parallel>的孩子都进入了<final>状态,Processor必须生成一个done.state.id 事件,id是<parallel>元素的id值。
当状态机达到了<scxml>元素的<final>孩子时候,状态机必须终止。如果当前的SCXML状态机(以后简称SCXML session 会话)是被另外一个状态机(Session)的<invoke>元素触发的。当当前session终止的时候,SCXML Processor 必须生成一个done.invoke.id 事件,并且返回这个事件给调用的那个session,id的值是一个唯一的标识符。
onentry
[这部分是规范的]
一个包含可执行内容的元素,当进入某一个状态的时候,<onentry>内的内容被执行
属性
没有属性|
孩子元素
可执行内容都可以在这里定义
说明
SCXML Processor 必须按文档中定义的顺序,执行<onentry>元素和元素内的内容。
onexit
[这部分是规范的]
一个包含可执行内容的元素,当退出某一个状态的时候,<onexit>内的内容被执行
属性
没有属性|
孩子元素
可执行内容都可以在这里定义
说明
SCXML Processor 必须按文档中定义的顺序,执行<onexit>元素和元素内的内容。
history
[这部分是规范的]
<history>伪状态允许一个状态机记住它的状态配置。如果一个转移使用<history>状态作为它的目标状态,将会返回状态机记录到的状态配置。伪状态知识参考uml状态图
属性
名字 |
必须 |
约束 |
类型 |
默认值 |
有效值 |
描述 |
id |
False |
|
Id |
None |
一个有效的id值 |
这个伪状态的标识符 |
type |
False |
|
Enum |
“shallow” |
“deep”,”shallow” |
决定了究竟是当前状态的活跃的原子状态还是,当前状态向内一层的活跃的子状态被记录 |
孩子元素
名字名字 |
说明 |
出现次数 |
<transition> |
转移的目标指定了默认的历史配置。 |
1 |
说明
在一份结构良好的SCXML文档中,这个转移不能包含cond和event属性,但是必须包含一个非空的target属性,这个值构成了一个有效的状态配置。
更多内容请访问 ThinerZQ’s Blog