mirror of
https://github.com/Quodatum/graphxq.git
synced 2025-04-11 11:42:24 +01:00
dotml
This commit is contained in:
parent
3aa4cb7757
commit
63c8f5d0a9
10 changed files with 147 additions and 105 deletions
18
src/graphxq/dotml.xqm
Normal file
18
src/graphxq/dotml.xqm
Normal file
|
@ -0,0 +1,18 @@
|
|||
(:~
|
||||
: dotml module
|
||||
: @see http://www.martin-loetzsch.de/DOTML/
|
||||
:)
|
||||
|
||||
module namespace dotml="http://www.martin-loetzsch.de/DOTML";
|
||||
declare default function namespace 'http://www.martin-loetzsch.de/DOTML';
|
||||
|
||||
import module namespace xslt="http://basex.org/modules/xslt";
|
||||
|
||||
(:~
|
||||
: @return graphviz dot string
|
||||
:)
|
||||
declare function generate($dotml) as xs:string
|
||||
{
|
||||
xslt:transform($dotml, fn:resolve-uri( "dotml/dotml2dot.xsl"))
|
||||
};
|
||||
|
|
@ -1,11 +1,10 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml" xmlns:dotml="http://www.martin-loetzsch.de/DOTML">
|
||||
<!--
|
||||
File dotml2dot.xsl
|
||||
Copyright 2002 - 2006 Martin Loetzsch
|
||||
Translates dotml documents into the native dot syntax.
|
||||
-->
|
||||
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml" xmlns:dotml="http://www.martin-loetzsch.de/DOTML">
|
||||
<xsl:output method="text"/>
|
||||
<xsl:variable xml:space="preserve" name="graph-attributes">bgcolor fontcolor fontname fontsize label margin nodesep rankdir ranksep ratio size</xsl:variable>
|
||||
<xsl:variable xml:space="preserve" name="cluster-attributes">bgcolor color fillcolor fontcolor fontname fontsize label labeljust labelloc style</xsl:variable>
|
||||
<xsl:variable xml:space="preserve" name="node-attributes">color fillcolor fixedsize fontcolor fontname fontsize height shape style URL width</xsl:variable>
|
||||
|
@ -16,12 +15,11 @@ Translates dotml documents into the native dot syntax.
|
|||
<xsl:apply-templates/>
|
||||
</xsl:template>
|
||||
<xsl:template match="text()"/>
|
||||
<xsl:template match="dotml:graph">digraph g {compound="true";<xsl:call-template name="copy-attributes">
|
||||
<xsl:template match="dotml:graph"><dummy>digraph g {compound="true";<xsl:call-template name="copy-attributes">
|
||||
<xsl:with-param name="separator" select="';'"/>
|
||||
<xsl:with-param name="attributes" select="$graph-attributes"/>
|
||||
</xsl:call-template>
|
||||
<xsl:apply-templates/>}
|
||||
<dot-filename><xsl:value-of select="@file-name"/></dot-filename>
|
||||
<xsl:apply-templates/>}</dummy>
|
||||
</xsl:template>
|
||||
<xsl:template match="dotml:sub-graph">subgraph sub_graph_<xsl:value-of select="count(preceding::dotml:sub-graph)"/>{rank="<xsl:value-of select="@rank"/>";<xsl:apply-templates/>}</xsl:template>
|
||||
<xsl:template match="dotml:cluster">subgraph cluster_<xsl:value-of select="@id"/>{<xsl:call-template name="copy-attributes">
|
||||
|
|
|
@ -38,7 +38,8 @@ declare function dot( $dot as xs:string*, $params as xs:string*) as node()*{
|
|||
else $gr:empty
|
||||
};
|
||||
|
||||
declare %private function dot1( $dot as xs:string) as node(){
|
||||
declare %private function dot1( $dot as xs:string) as element(svg:svg)
|
||||
{
|
||||
let $fname:=$gr:tmpdir || random:uuid()
|
||||
let $junk:=file:write-text($fname,$dot)
|
||||
let $r:=proc:execute($gr:dotpath , ("-Tsvg",$fname))
|
||||
|
@ -77,6 +78,7 @@ declare %private function dot1( $dot as xs:string) as node(){
|
|||
</svg>
|
||||
|
||||
};
|
||||
|
||||
(:~
|
||||
:Layout one ore more graphs given in the GXL language and render them as SVG.
|
||||
: gxl2dot Test.gxl > Test.dot
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
(:~
|
||||
: restxq interface for graphviz
|
||||
: RESTXQ interface for graphviz
|
||||
: @author andy bunce
|
||||
: @since sept 2012
|
||||
:)
|
||||
|
@ -8,13 +8,19 @@ module namespace grxq = 'apb.graphviz.web';
|
|||
declare default function namespace 'apb.graphviz.web';
|
||||
|
||||
import module namespace gr = 'apb.graphviz' at "graphviz.xqm";
|
||||
import module namespace dotml = 'http://www.martin-loetzsch.de/DOTML' at "dotml.xqm";
|
||||
import module namespace dotui = 'apb.graphxq.dotui' at "dotui.xqm";
|
||||
import module namespace txq = 'apb.txq' at "lib/txq.xqm";
|
||||
import module namespace request = "http://exquery.org/ns/request";
|
||||
|
||||
declare namespace svg= "http://www.w3.org/2000/svg";
|
||||
declare namespace rest = 'http://exquery.org/ns/restxq';
|
||||
|
||||
declare variable $grxq:layout:=fn:resolve-uri("views/layout.xml");
|
||||
|
||||
(:~
|
||||
: Home page for app
|
||||
:)
|
||||
declare
|
||||
%rest:GET %rest:path("graphxq")
|
||||
%output:method("html") %output:version("5.0")
|
||||
|
@ -23,14 +29,14 @@ declare
|
|||
function graphxq($dot,$url) {
|
||||
let $edot:=if($url) then "" else fn:encode-for-uri($dot)
|
||||
let $dot2:=getdot($dot,$url)
|
||||
let $svg:=get-svg($dot)
|
||||
let $map:=map{"dot":=$dot,"url":=$url,"svg":=$svg,"edot":=$edot}
|
||||
let $page:=render("views/page1.xml",$map)
|
||||
return $page
|
||||
let $svg:=dot2svg($dot)
|
||||
let $map:=map{"dot":=$dot,"url":=$url,"svg":=$svg,"edot":=$edot}
|
||||
let $page:=render("views/page1.xml",$map)
|
||||
return $page
|
||||
};
|
||||
|
||||
(:~
|
||||
: return svg for dot, with download option
|
||||
: GET or POST return svg for dot, with download option
|
||||
:)
|
||||
declare
|
||||
%rest:path("graphxq/svg")
|
||||
|
@ -39,18 +45,18 @@ declare
|
|||
%rest:form-param("dl","{$dl}")
|
||||
%output:media-type("image/svg+xml")
|
||||
function graphxq-svg($dot,$url,$dl) {
|
||||
let $dot2:=getdot($dot,$url)
|
||||
let $svg:=get-svg($dot2)
|
||||
let $resp:=<rest:response>
|
||||
<http:response>
|
||||
<http:header name="Access-Control-Allow-Origin" value="*"/>
|
||||
{if($dl)
|
||||
then <http:header name="Content-Disposition" value='attachment;filename="graphxq.svg"'/>
|
||||
else ()}
|
||||
</http:response>
|
||||
</rest:response>
|
||||
|
||||
return ($resp,$svg)
|
||||
let $dot2:=getdot($dot,$url)
|
||||
let $svg:=dot2svg($dot2)
|
||||
let $resp:=<rest:response>
|
||||
<http:response>
|
||||
<http:header name="Access-Control-Allow-Origin" value="*"/>
|
||||
{if($dl)
|
||||
then <http:header name="Content-Disposition" value='attachment;filename="graphxq.svg"'/>
|
||||
else ()}
|
||||
</http:response>
|
||||
</rest:response>
|
||||
|
||||
return ($resp,$svg)
|
||||
};
|
||||
|
||||
(:~
|
||||
|
@ -64,25 +70,34 @@ declare
|
|||
function dotform($src){
|
||||
let $dot:= getdot("digraph {{a -> b}}",$src)
|
||||
let $svgwidget:=fn:doc("views/widget.svg")
|
||||
let $map:=map{"list-shapes":=dotui:shapes(""),
|
||||
"list-colors":=dotui:colors(""),
|
||||
"svgwidget":=$svgwidget,
|
||||
"dot":=$dot}
|
||||
return render("views/dotform.xml",$map)
|
||||
let $map:=map{"list-shapes":=dotui:shapes(""),
|
||||
"list-colors":=dotui:colors(""),
|
||||
"svgwidget":=$svgwidget,
|
||||
"dot":=$dot}
|
||||
return render("views/dotform.xml",$map)
|
||||
};
|
||||
|
||||
declare
|
||||
%rest:GET %rest:path("graphxq/dotml")
|
||||
%output:method("html") %output:version("5.0")
|
||||
function dotmlform(){
|
||||
render("views/dotmlform.xml",map{})
|
||||
render("views/dotmlform.xml",map{})
|
||||
};
|
||||
|
||||
(:~ static about page :)
|
||||
declare
|
||||
%rest:GET %rest:path("graphxq/about")
|
||||
%output:method("html") %output:version("5.0")
|
||||
function about(){
|
||||
render("views/about.xml",map{})
|
||||
render("views/about.xml",map{})
|
||||
};
|
||||
|
||||
(:~ static api page :)
|
||||
declare
|
||||
%rest:GET %rest:path("graphxq/api")
|
||||
%output:method("html") %output:version("5.0")
|
||||
function api(){
|
||||
render("views/api.xml",map{})
|
||||
};
|
||||
|
||||
declare
|
||||
|
@ -93,44 +108,72 @@ function search($q ) {
|
|||
let $map:=map{"q":=$q}
|
||||
return render("views/search.xml",$map)
|
||||
};
|
||||
|
||||
declare
|
||||
%rest:GET %rest:path("graphxq/library")
|
||||
%output:method("html") %output:version("5.0")
|
||||
|
||||
function library( ) {
|
||||
let $map:=map{ }
|
||||
return render("views/library.xml",$map)
|
||||
};
|
||||
|
||||
(:~
|
||||
: @return svg from dotml
|
||||
:)
|
||||
declare
|
||||
%rest:POST %rest:path("graphxq/api/dotml")
|
||||
%rest:form-param("dotml","{$dotml}")
|
||||
function api-dotml($dotml ) as node()
|
||||
{
|
||||
let $dotml:=fn:parse-xml($dotml)
|
||||
let $x:=dotml:generate($dotml)
|
||||
(: let $svg:=dot2svg($x) :)
|
||||
return $x
|
||||
|
||||
};
|
||||
|
||||
(:~ use dot or url :)
|
||||
declare %private function getdot($dot,$url) as xs:string{
|
||||
(:~ if url is defined then treat as url and fetch else use dot :)
|
||||
declare %private function getdot($dot as xs:string,$url) as xs:string{
|
||||
if($url) then
|
||||
try{fn:unparsed-text(fn:resolve-uri($url))} catch * { "digraph {{ failed to load remote }}" }
|
||||
else
|
||||
$dot
|
||||
};
|
||||
|
||||
(:~ post process svg :)
|
||||
declare %private function get-svg($dot as xs:string) as node(){
|
||||
(:~ if url is defined then treat as url and fetch else use dotml :)
|
||||
declare %private function getdotml($dotml as xs:string,$url) as xs:string{
|
||||
if($url) then
|
||||
try{fn:unparsed-text(fn:resolve-uri($url))} catch * { "digraph {{ failed to load remote }}" }
|
||||
else
|
||||
$dotml
|
||||
};
|
||||
|
||||
(:~ Generate svg from dot :)
|
||||
declare %private function dot2svg($dot as xs:string) as node(){
|
||||
let $svgx:=gr:dot($dot,())
|
||||
return gr:autosize($svgx)
|
||||
};
|
||||
};
|
||||
|
||||
declare function render($template,$locals){
|
||||
(:~
|
||||
: Render html page
|
||||
: @param template path to page template
|
||||
: @params locals map of page variables
|
||||
:)
|
||||
declare function render($template as xs:string,$locals){
|
||||
let $sidebar:=<div>
|
||||
<a href="/graphxq/viewbox/viewBox.svg">viewbox work</a>
|
||||
<ul>
|
||||
<div>Samples:</div>
|
||||
<li> <a href="dot?src=samples/dot/process.gv">process</a></li>
|
||||
<li><a href="/restxq/graphxq/dot?src=samples/dot/unix.gv">unix</a></li>
|
||||
<li> <a href="/restxq/graphxq/dot?src=samples/dot/root.gv">root (slow)</a></li>
|
||||
</ul>
|
||||
<a href="/graphxq/viewbox/viewBox.svg">viewbox work</a>
|
||||
<ul>
|
||||
<div>Samples:</div>
|
||||
<li> <a href="dot?src=samples/dot/process.gv">process</a></li>
|
||||
<li><a href="dot?src=samples/dot/unix.gv">unix</a></li>
|
||||
<li><a href="dot?src=samples/dot/root.gv">root (slow)</a></li>
|
||||
<li><a href="dotml?src=samples/dotml/sample1.xml">dotml sample</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
let $default:=map{"sidebar":=$sidebar ,
|
||||
let $default:=map{"sidebar":=$sidebar ,
|
||||
"usermenu":=<div>users</div>,
|
||||
"title":=request:path(),
|
||||
"messages":=()}
|
||||
let $locals:=map:new(($default,$locals))
|
||||
return txq:render(fn:resolve-uri($template),$locals,$grxq:layout)
|
||||
};
|
||||
"messages":=()}
|
||||
let $locals:=map:new(($default,$locals))
|
||||
return txq:render(fn:resolve-uri($template),$locals,$grxq:layout)
|
||||
};
|
|
@ -1,4 +1,4 @@
|
|||
<graph file-name="graphs/example_xabsl_option1" ranksep="0.3" nodesep="0.2">
|
||||
<graph xmlns="http://www.martin-loetzsch.de/DOTML" ranksep="0.3" nodesep="0.2">
|
||||
<cluster id="option" label="option handle-ball-at-left-and-right-border" fontname="Arial" fontcolor="#005A9C" fontsize="11" fillcolor="#F4F4F4" style="filled">
|
||||
<sub-graph rank="same">
|
||||
<node label="go\nto\nball" fontcolor="#005A9C" fontsize="11" style="filled" fillcolor="#FFFFFF" fontname="Arial" id="state_go_to_ball" shape="Mcircle"/>
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
(:~
|
||||
: A(nother) templating Engine for XQuery (BaseX 7.5+(or -) specific)
|
||||
:
|
||||
: @author andy bunce
|
||||
: @since sept 2012
|
||||
:)
|
||||
|
||||
module namespace txq = 'apb.txq';
|
||||
declare default function namespace 'apb.txq';
|
||||
import module namespace xquery = "http://basex.org/modules/xquery";
|
||||
|
||||
|
||||
(:~
|
||||
: template function
|
||||
: @return updated doc from map
|
||||
:)
|
||||
declare function render($map as map(*),$layout as xs:string,$file as xs:string)
|
||||
{
|
||||
let $content:=render($map,$file)
|
||||
let $map:=map:new(($map,map{"body":=$content}))
|
||||
return render($map,$layout)
|
||||
|
||||
};
|
||||
|
||||
(:~
|
||||
: template function
|
||||
: @return updated doc from map
|
||||
:)
|
||||
declare function render($layout as xs:string,$map as map(*))
|
||||
{
|
||||
let $map:=map:new(($map,map{"partial":=partial(?,?,?,$map,$layout)}))
|
||||
return xquery:invoke($layout,$map)
|
||||
|
||||
};
|
||||
|
||||
(:~
|
||||
: partial template function: evaluate part for each value in sequence
|
||||
: @return updated doc from map
|
||||
:)
|
||||
declare function partial($part as xs:string,$name,$seq,$map,$base)
|
||||
{
|
||||
for $s in $seq
|
||||
let $map:=map:new(($map,map{$name:=$s}))
|
||||
return render($map,fn:resolve-uri($part,$base))
|
||||
};
|
||||
|
|
@ -42,7 +42,7 @@
|
|||
<li class="tweet-btn"><iframe title="Twitter Tweet Button"
|
||||
style="width: 106px; height: 20px;"
|
||||
class="twitter-share-button twitter-count-horizontal"
|
||||
src="http://platform.twitter.com/widgets/tweet_button.html?count=horizontal&id=twitter-widget-0&lang=en&original_referer=https%3A%2F%2Fgithub.com%2Fapb2006%2Fxqwebdoc%2F&size=m&text=xqwebdoc #xquery&url=https%3A%2F%2Fgithub.com%2Fapb2006%2Fxqwebdoc&via=apb1704"
|
||||
src="http://platform.twitter.com/widgets/tweet_button.html?count=horizontal&id=twitter-widget-0&lang=en&original_referer=https%3A%2F%2Fgithub.com%2Fapb2006%2Fgraphxq&size=m&text=graphxq #xquery&url=https%3A%2F%2Fgithub.com%2Fapb2006%2Fxqwebdoc&via=apb1704"
|
||||
allowtransparency="true" scrolling="no" frameborder="0"></iframe></li>
|
||||
</ul>
|
||||
</div>
|
7
src/graphxq/views/api.xml
Normal file
7
src/graphxq/views/api.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<div>
|
||||
<h1>About GraphXQ API</h1>
|
||||
<p>
|
||||
POST or GET <div>restxq/svg?dot=..</div>
|
||||
</p>
|
||||
|
||||
</div>
|
|
@ -1,8 +1,17 @@
|
|||
<div class="row-fluid" style="heigth:20em">
|
||||
<div class="row-fluid" style="height:20em">
|
||||
<div class="span5">
|
||||
<form method="post" action="." style="background-color:#EEEEEE;padding:8px;">
|
||||
<form method="post" action="api/dotml" style="background-color:#EEEEEE;padding:8px;">
|
||||
|
||||
<textarea name="dot" rows="2" cols="80"></textarea>
|
||||
<textarea name="dotml" rows="12" cols="80">
|
||||
<graph file-name="graphs/decorate">
|
||||
|
||||
<node id="a"/>
|
||||
<node id="b"/>
|
||||
<node id="c"/>
|
||||
<edge from="a" to="c" decorate="false" label="decorate='false'"/>
|
||||
<edge from="b" to="c" decorate="true" label="decorate='true'"/>
|
||||
</graph>
|
||||
</textarea>
|
||||
|
||||
<button type="submit">Redraw</button>
|
||||
</form >
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<base href="/restxq/graphxq/" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="description" content="xquery documentation" />
|
||||
<meta name="description" content="graphviz tool" />
|
||||
<meta name="author" content="andy bunce" />
|
||||
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.2.2/css/bootstrap.css" rel="stylesheet"
|
||||
type="text/css" />
|
||||
|
@ -63,11 +63,22 @@
|
|||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav">
|
||||
<li >
|
||||
<a href="library">Library</a>
|
||||
</li>
|
||||
<li class="nav">
|
||||
<a href="about">About</a>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||
About
|
||||
<b class="caret"></b>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a href="about"><i class="icon-edit"></i> About</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="api"><i class="icon-align-center"></i> API</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<form class="pull-right navbar-search" action="search">
|
||||
|
|
Loading…
Add table
Reference in a new issue