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 中的優勢之一是,圖表可以在列印時以不同的方式顯示,以便可以將每個步驟及其描述一起顯示。