[add] examples

This commit is contained in:
Andy Bunce 2021-05-17 23:19:44 +01:00
parent c1eeee4835
commit 30f15aca89
5 changed files with 337 additions and 0 deletions

70
code/diag-xqdoc.xq Normal file
View File

@ -0,0 +1,70 @@
(:~
: generate dotml from xqdoc source
: apb Jan 2013
:)
declare namespace doc="http://www.xqdoc.org/1.0";
declare namespace dotml="http://www.martin-loetzsch.de/DOTML";
declare variable $ns-ignore:=("http://www.w3.org/2005/xpath-functions",
"http://www.w3.org/2010/xslt-xquery-serialization",
"http://www.w3.org/2001/XMLSchema",
"http://www.w3.org/2005/xpath-functions/math" );
declare function local:sid($s as xs:string){
"A" || xs:hexBinary(hash:md5($s))
};
declare function local:fid($uri as xs:string ,$name as xs:string,$arity as xs:string){
let $a:=fn:trace(($uri || "*" || $name || "*" || $arity),"fid: ")
return "A" || xs:hexBinary(hash:md5($uri || $name ||$arity))
};
declare function local:foo($dml){
let $moduri:=$dml/doc:xqdoc/doc:module/doc:uri/fn:string()
return
<dotml:graph file-name="graphs/bgcolor" rankdir="LR" label="a test" >
{for $import in $dml//doc:import
let $ns:=$import/doc:uri/fn:string()
where some $call in $dml//doc:invoked satisfies $call/doc:uri=$import/doc:uri
return <dotml:cluster id="{local:sid($ns)}"
label="{$ns}"
bgcolor="#FF8080" >
{for $call in $dml//doc:invoked[doc:uri=$import/doc:uri]
return <dotml:node
id="{local:fid($call/doc:name/@uri,$call/doc:name/@localname,$call/@arity)}"
label="{$call/doc:name/fn:string()}"
fillcolor="lightblue" style="filled"/>
}
</dotml:cluster>
}
<dotml:cluster id="main" rankdir="LR"
label="main"
bgcolor="seashell"
>
{for $f in $dml//doc:function
return <dotml:node id="{local:fid($moduri,$f/doc:name,$f/@arity)}" label="{$f/doc:name}" fillcolor="yellow" style="filled"/>,
for $v in $dml//doc:variable
return <dotml:node id="{generate-id($v)}" label="{$v/doc:name}" fillcolor="green" style="filled"/>
}
</dotml:cluster>
{for $call in $dml//doc:invoked
let $f:=$call/..
where not($call/doc:name/@uri/fn:string()=$ns-ignore)
return <dotml:edge
from="{local:fid($moduri,$f/doc:name,$f/@arity)}"
to="{local:fid($call/doc:name/@uri,$call/doc:name/@localname,$call/@arity)}"/> }
</dotml:graph>
};
let $a:=local:foo(/)
(:
let $req:=<http:request method="POST" >
<http:body media-type="application/x-www-form-urlencoded">data={fn:encode-for-uri(fn:serialize($a))}</http:body>
</http:request>
let $ws:= http:send-request($req,"http://localhost:8984/restxq/graphxq/api/dotml")
return file:write("aa.svg",$ws[2])
:)
return $a

119
code/graphviz.xqm Normal file
View File

@ -0,0 +1,119 @@
(:~
: graphviz module
: based on http://www.zorba-xquery.com/html/modules/zorba/image/graphviz
:)
module namespace gr="apb.graphviz";
declare default function namespace 'apb.graphviz';
import module namespace proc="http://basex.org/modules/proc";
import module namespace file="http://expath.org/ns/file";
import module namespace xslt="http://basex.org/modules/xslt";
declare namespace svg= "http://www.w3.org/2000/svg";
declare namespace xlink="http://www.w3.org/1999/xlink";
declare %private variable $gr:dotpath:=if(fn:environment-variable("DOTPATH"))
then fn:environment-variable("DOTPATH")
else "dot";
(:~
: folder for temp files \=windows
:)
declare %private variable $gr:tmpdir:=if(file:dir-separator()="\")
then fn:environment-variable("TEMP") || "\"
else "/tmp/";
declare %private variable $gr:empty:=
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 20" version="1.1"
width="100%" height="100%" preserveAspectRatio="xMidYMid meet">
<text x="150" y="10" text-anchor="middle">Empty.</text>
</svg>;
(:~
:Layout one or more graphs given in the DOT language and render them as SVG.
:)
declare function dot( $dot as xs:string*, $params as xs:string*) as node()*{
let $params:=("-Tsvg")
for $d in $dot
return if(fn:not($d))
then $gr:empty
else let $r:=dot-execute($d,$params)
return dot-svg($r)
};
(:~ run dot command :)
declare %private function dot-execute( $dot as xs:string, $params as xs:string*) as element(result){
let $fname:=$gr:tmpdir || random:uuid()
let $junk:=file:write-text($fname,$dot)
let $r:=proc:execute($gr:dotpath , ($params,$fname))
let $junk:=file:delete($fname)
return if($r/code!="0")
then fn:error(xs:QName('gr:dot1'),$r/error)
else $r
};
(:~ run dot command returning binary :)
declare function dot-executeb( $dot as xs:string, $params as xs:string*) as xs:base64Binary{
let $fname:=$gr:tmpdir || random:uuid()
let $oname:=$fname || ".o"
let $junk:=file:write-text($fname,$dot)
let $r:=proc:execute($gr:dotpath , ($params,"-o"|| $oname,$fname))
let $junk:=file:delete($fname)
return if($r/code!="0")
then fn:error(xs:QName('gr:dot1'),$r/error)
else let $d:=file:read-binary($oname)
(: let $junk:=file:delete($oname) :)
return $d
};
(:~ cleanup dot svg result :)
declare %private function dot-svg( $r as element(result)) as element(svg:svg){
let $s:=fn:parse-xml($r/output) (: o/p has comment nodes :)
let $ver:=$s/comment()[1]/fn:normalize-space()
let $title:=$s/comment()[2]/fn:normalize-space()
let $svg:=$s/*
return <svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" >
{$svg/@* ,
<metadata>
<rdf:RDF
xmlns:rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rdfs = "http://www.w3.org/2000/01/rdf-schema#"
xmlns:dc = "http://purl.org/dc/elements/1.1/" >
<rdf:Description about="https://github.com/apb2006/graphxq"
dc:title="{$title}"
dc:description="A graph visualization"
dc:date="{fn:current-dateTime()}"
dc:format="image/svg+xml">
<dc:creator>
<rdf:Bag>
<rdf:li>{$ver}</rdf:li>
<rdf:li resource="https://github.com/apb2006/graphxq"/>
</rdf:Bag>
</dc:creator>
</rdf:Description>
</rdf:RDF>
</metadata>,
$svg/*}
</svg>
};
(:~
: set svg to autosize 100%
:)
declare function autosize($svg as node()) as node(){
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%" height="100%" preserveAspectRatio="xMidYMid meet">
{$svg/@* except ($svg/@width,$svg/@height,$svg/@preserveAspectRatio),
$svg/*}
</svg>
};
(:~
: set svg to autosize 100%
:)
declare function autosize-old($svg as node()) as node(){
xslt:transform($svg , fn:resolve-uri("dotml/dotpatch.xsl"))
};

27
process.gv Normal file
View File

@ -0,0 +1,27 @@
digraph process {
subgraph cluster_0 {
style=filled;
color=lightgrey;
node [style=filled,color=white];
a0 -> a1 -> a2 -> a3;
label = "process #1";
}
subgraph cluster_1 {
node [style=filled];
b0 -> b1 -> b2 -> b3;
label = "process #2";
color=blue
}
start -> a0;
start -> b0;
a1 -> b3;
b2 -> a3;
a3 -> a0;
a3 -> end;
b3 -> end;
start [shape=Mdiamond];
end [shape=Msquare];
}

121
xml/dotpatch.xsl Normal file
View File

@ -0,0 +1,121 @@
<?xml version="1.0"?>
<!--
tidy up graphviz svg o/p
-->
<xsl:stylesheet version="1.0" xmlns="http://www.w3.org/2000/svg"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" >
<xsl:param name="filter">MyFilter</xsl:param>
<xsl:param name="rotate" select="false()"/>
<xsl:output method="xml" encoding="UTF-8" indent="yes" omit-xml-declaration="yes"/>
<xsl:template match="/svg:svg">
<xsl:variable name="w" select="substring-before(@width,'pt')"/>
<xsl:variable name="aa" select="string(@width)"/>
<xsl:variable name="h" select="substring-before(@height,'pt')"/>
<xsl:variable name="filters">
<defs xmlns="http://www.w3.org/2000/svg">
<filter id="Drop_Shadow" filterUnits="objectBoundingBox" x="-10%" y="-10%" width="150%" height="150%">
<feGaussianBlur in="SourceAlpha" stdDeviation="3" result="blurredAlpha"/>
<feOffset in="blurredAlpha" dx="3" dy="3" result="offsetBlurredAlpha"/>
<feFlood result="flooded" style="flood-color:rgb(0,0,0);flood-opacity:0.65"/>
<feComposite in="flooded" operator="in" in2="offsetBlurredAlpha" result="coloredShadow"/>
<feComposite in="SourceGraphic" in2="coloredShadow" operator="over"/>
</filter>
<filter id="Bevel" filterUnits="objectBoundingBox" x="-10%" y="-10%" width="150%" height="150%">
<feGaussianBlur in="SourceAlpha" stdDeviation="3" result="blur"/>
<feSpecularLighting in="blur" surfaceScale="5" specularConstant="0.5" specularExponent="10" result="specOut" style="lighting-color:rgb(255,255,64)">
<fePointLight x="-5000" y="-10000" z="20000"/>
</feSpecularLighting>
<feComposite in="specOut" in2="SourceAlpha" operator="in" result="specOut2"/>
<feComposite in="SourceGraphic" in2="specOut2" operator="arithmetic" k1="0" k2="1" k3="1" k4="0" result="litPaint"/>
</filter>
<filter id="grey_bevel_shadow" filterUnits="objectBoundingBox" x="-10%" y="-10%" width="150%" height="150%">
<feGaussianBlur result="blurredAlpha" in="SourceAlpha" stdDeviation="3"/>
<feOffset result="offsetBlurredAlpha" in="blurredAlpha" dx="2" dy="1"/>
<feDiffuseLighting result="bumpMapDiffuse" in="blurredAlpha" surfaceScale="5" diffuseConstant="0.5" style="lighting-color:rgb(255,255,255)">
<feDistantLight azimuth="135" elevation="60"/>
</feDiffuseLighting>
<feComposite result="litPaint" in="bumpMapDiffuse" operator="arithmetic" k1="1" k2="0" k3="0" k4="0" in2="SourceGraphic"/>
<feSpecularLighting result="bumpMapSpecular" in="blurredAlpha" surfaceScale="5" specularConstant="0.5" specularExponent="10" style="lighting-color:rgb(255,255,255)">
<feDistantLight azimuth="135" elevation="60"/>
</feSpecularLighting>
<feComposite result="litPaint" in="litPaint" operator="arithmetic" k1="0" k2="1" k3="1" k4="0" in2="bumpMapSpecular"/>
<feComposite result="litPaint" in="litPaint" operator="in" in2="SourceAlpha"/>
<feMerge>
<feMergeNode in="offsetBlurredAlpha"/>
<feMergeNode in="litPaint"/>
</feMerge>
</filter>
<filter id="Bumpy" filterUnits="objectBoundingBox" x="-10%" y="-10%" width="150%" height="150%">
<feTurbulence type="turbulence" baseFrequency="0.15" numOctaves="1" result="image0"/>
<feGaussianBlur stdDeviation="3" in="image0" result="image1"/>
<feDiffuseLighting in="image1" surfaceScale="10" diffuseConstant="1" result="image3" style="lighting-color:rgb(255,255,255)">
<feDistantLight azimuth="0" elevation="45"/>
</feDiffuseLighting>
<feComposite in="image3" in2="SourceGraphic" operator="arithmetic" k2="0.5" k3="0.5" result="image4"/>
<feComposite in="image4" in2="SourceGraphic" operator="in" result="image5"/>
</filter>
<filter id="MyFilter" filterUnits="objectBoundingBox" x="-10%" y="-10%" width="150%" height="150%">
<desc>Produces a 3D lighting effect suitable for pies and lines</desc>
<feGaussianBlur in="SourceAlpha" stdDeviation="4" result="blur"/>
<feOffset in="blur" dx="3" dy="5" result="offsetBlur"/>
<feSpecularLighting in="blur" surfaceScale="5" specularConstant="1" specularExponent="30" style="lighting-color:White" result="specOut">
<fePointLight x="-5000" y="-10000" z="20000"/>
</feSpecularLighting>
<feComposite in="specOut" in2="SourceAlpha" operator="in" result="specOut"/>
<feComposite in="SourceGraphic" in2="specOut" operator="arithmetic" k1="0" k2="1" k3="1" k4="0" result="litPaint"/>
<feMerge>
<feMergeNode in="offsetBlur"/>
<feMergeNode in="litPaint"/>
</feMerge>
</filter>
<filter id="MyShadow" filterUnits="objectBoundingBox" x="-20%" y="-20%" width="180%" height="180%">
<desc>Simple blurred shadow (ideal for headings)</desc>
<feGaussianBlur in="SourceAlpha" stdDeviation="6" result="blur"/>
<feOffset in="blur" dx="12" dy="10" result="offsetBlur"/>
<feMerge>
<feMergeNode in="offsetBlur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
</xsl:variable>
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" aa="{$aa}"
preserveAspectRatio="xMidYMid meet" viewBox="0 0 {$w} {$h}" text-rendering="optimizeLegibility">
<xsl:copy-of select="$filters"/>
<xsl:choose>
<xsl:when test="rotate">
<g transform="rotate(90 {$w div 2} {$h div 2} )">
<xsl:call-template name="copy-content"/>
</g>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="*"/>
</xsl:otherwise>
</xsl:choose>
</svg>
</xsl:template>
<xsl:template name="copy-content">
<xsl:apply-templates select="@*|processing-instruction()|*|text()"/>
</xsl:template>
<!--default behaviours for all nodes-->
<xsl:template match="processing-instruction()|*|@*|text()">
<xsl:copy>
<xsl:call-template name="copy-content"/>
</xsl:copy>
</xsl:template>
<!-- apply non text in nodes -->
<xsl:template match="svg:g[@class='node']">
<g>
<g filter="url(#{$filter})">
<xsl:apply-templates select="*[local-name()!='text']"/>
</g>
<g>
<xsl:apply-templates select="svg:text"/>
</g>
</g>
</xsl:template>
</xsl:stylesheet>