XQuery/序列图
外观
< XQuery
即使使用绘图工具,序列图也很难绘制。当序列发生变化时,它们更难编辑。一种替代方法是定义一个 XML 词汇表来定义消息排序,并使用 XQuery 将此描述渲染为 XHTML。这种文本方法还允许在每个步骤中显示解释,并生成序列 XML 定义的替代渲染,例如打印版本。
此演示器使用简化的元模型,仅包含参与者之间的消息和参与者执行的动作。
(文章正在重新设计 - CW)
以下是一个在 3 层架构中交互的示例描述:(非常需要重写)
<SequenceDiagram id="3tier"> <name>3-tier architecture</name> <description>An overview of the 3-tier Architecture</description> <cast> <actor> <name>user</name> <label>The User</label> <color>pink</color> <location>client</location> <description>The user of the site</description> </actor> <actor> <name>browser</name> <label>Presentation Layer</label> <color>lightgreen</color> <location>client</location> <description>A browser such as Firefox, Opera or Internet Explorer</description> </actor> <actor> <name>server</name> <label>Application Layer</label> <color>lightblue</color> <location>server</location> <description>Scripts in languages such as PHP or Java invoked via a web server</description> </actor> <actor> <name>database</name> <label>Persistance Layer</label> <color>grey</color> <location>server</location> <description>A database server such as Oracle or MySQL</description> </actor> </cast> <communication> <connection> <actor>user</actor> <actor>browser</actor> <method/> <prep>on</prep> </connection> <connection> <actor>browser</actor> <actor>server</actor> <method>HTTP</method> <prep>to</prep> </connection> <connection> <actor>server</actor> <actor>database</actor> <method>SQL</method> <prep>to</prep> </connection> </communication> <trace> <message> <from>user</from> <to>browser</to> <action>click</action> <object>link</object> </message> <message> <from>browser</from> <to>server</to> <action>request</action> <object>URL</object> <url>http://www.cems.uwe.ac.uk/~cjwallac/apps/poll2/tally.php?pollid=2</url> </message> <do> <at>server</at> <action>decode input</action> <object/> </do> <do> <at>server</at> <action>create SQL request</action> <object/> </do> <message> <from>server</from> <to>database</to> <action>request</action> <object>SQL statement</object> </message> <message> <from>database</from> <to>server</to> <action>respond</action> <object>tables</object> </message> <do> <at>server</at> <action>create page with data in table</action> <object/> </do> <message> <from>server</from> <to>browser</to> <action>respond</action> <object>HTML page</object> </message> <message> <from>user</from> <to>browser</to> <action>read</action> <object>page</object> </message> </trace> </SequenceDiagram>
'displayDiagram' 脚本将此模型渲染为 XHTML 表格
declare option exist:serialize "method=xhtml media-type=text/html indent=yes"; declare variable $homesym :=' || '; declare variable $leftsym := ' >> '; declare variable $rightsym := ' << '; declare function local:makeText($event){ concat($event/action,' ',string-join($event/object,' + ')) }; let $id:= request:get-parameter('id','') let $sd :=//SequenceDiagram[@id=$id] let $trace := $sd/trace let $actors := $sd/cast/actor let $nactors := count($sd/cast/actor) let $width := 100 div $nactors return <html> <head><title>Sequence Diagram {string($sd/@id)}</title> </head> <body> <h1>{string($sd/name)} </h1> <div class="description"> {$sd/description/node() } </div> <table border='1'> <tr> {for $a in $actors return <th width='{$width}%' bgcolor='{$a/color}'>{string($a/label)}</th> } </tr> { if ($actors/description) then <tr> {for $a in $actors return <th width='{$width}%' bgcolor='{$a/color}'>{string($a/description)} </th> } </tr> else () } {for $event in $trace/* return <tr> {if (name($event)='do') then let $p := index-of($actors/name,$event/at ) let $text:= local:makeText($event) return ( for $i in (1 to $p - 1) return <td/>, <td align='center' bgcolor='{$actors[name=$event/at]/color}'> { if ($event/url) then <a href='{$event/url}' target='demo'>{$text}</a> else $text } </td>, for $i in ($p + 1to $nactors) return <td/> ) else if (name($event)='message') then let $pfrom := index-of($actors/name,$event/from ) let $pto := index-of($actors/name,$event/to) let $pfirst := min (($pfrom,$pto)) let $plast := max(($pfrom,$pto)) let $ltor := $pfrom = $pfirst let $text:= local:makeText($event) let $connection := $sd//connection[actor = $event/from and actor= $event/to] let $text := if ($ltor) then concat($connection/method,$leftsym,$text,$leftsym) else concat($rightsym,$text,$rightsym, $connection/method) return ( for $i in (1 to $pfirst - 1) return <td/>, <td align='center' colspan='{$plast - $pfirst + 1 }' bgcolor ='{$actors[name=$event/from]/color}' > {$text} { if ($event/url) then <a href='{$event/url}' target='demo'>Link </a> else () } </td>, for $i in ($plast + 1 to $nactors) return <td/> ) else () } </tr> } </table> </body> </html>
- 一个 GoogleEarth 应用程序
与显示完整的交互不同,图表可以通过仅显示前 n 步以及最后一步的解释文本来简单地进行动画处理。添加一些控件可以让用户在序列中向前和向后迈进。
3层 GoogleEarth 用于计算下一步的函数
declare function local:next-step($step,$action, $max) { if ($action = "start") then 0 else if ($action = "back") then max (($step -1,0)) else if ($action = "forward") then min(($max,$step+1)) else if ($action="end") then $max else $step };
并调用该函数
let $step := local:next-step( number(request:request-parameter("step",0)), request:request-parameter("action", "start"), count($trace/*))
提供控件并维护交互状态的表单
<h2> <form> <input type="hidden" name="id" value="{$id}"/> <input type="hidden" name="step" value="{$step}"/> <input type="submit" name="action" value="start"/> <input type="submit" name="action" value="back"/> <input type="submit" name="action" value="forward"/> <input type="submit" name="action" value="end"/> </form> </h2>
将显示的事件限制为指定数量的步骤
for $event in $trace/*[position()<=$step]
并显示最后一步的解释
<div class="description"> {if ($step=0) then $sd/description/node() else $trace/*[position()=$step]/description/node() } </div>
将整个图表存储在 XML 中的优势之一是,图表可以在打印时以不同的方式显示,以便可以将每个步骤及其描述一起显示。