Question

I can't find any existing solutions because I do not think that anybody else has used eXist-db to do this yet. Does anybody know how to draw bar charts using SVG from eXist-db?

Firstly date:

DTD:

<?xml version="1.0" encoding="utf-8"?>
<!ELEMENT akweny (akwen+)>
<!ELEMENT akwen (nazwa, typ, powierzchnia, akweny?)>
<!ELEMENT nazwa (#PCDATA)>
<!ELEMENT typ (#PCDATA)>
<!ELEMENT powierzchnia (#PCDATA)>

And XML for example:

<?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE akweny SYSTEM "akweny.dtd">
    <akweny>
        <akwen>
            <nazwa>Atlantycki</nazwa>
            <typ>ocean</typ>
            <powierzchnia>106450</powierzchnia>
            <akweny>
                <akwen>
                    <nazwa>Północne</nazwa>
                    <typ>morze</typ>
                    <powierzchnia>750</powierzchnia>
                </akwen>
                <akwen>
                    <nazwa>Batyckie</nazwa>
                    <typ>morze</typ>
                    <powierzchnia>386</powierzchnia>
                    <akweny>
                        <akwen>
                            <nazwa>Botnicka</nazwa>
                            <typ>zatoka</typ>
                            <powierzchnia>117</powierzchnia>
                        </akwen>
                    </akweny>
                </akwen>
            </akweny>
        </akwen>
        <akwen>
            <nazwa>Spokojny</nazwa>
            <typ>ocean</typ>
            <powierzchnia>179700</powierzchnia>
        </akwen>
    </akweny>

I know eXist-db has some XSLT transformation functions, e.g.

transform:stream-transform($node-tree as node()*, $stylesheet as item(), 
$parameters as node()?) as item()

But how the hell can I use this? I can't find any examples. I don know how to use it...

Here is my link:

bars.xq?nazwa=anyNazwa&typ=anyTyp&powierzchnia=100

It should show Any of nazwa, any of typ and greater than powierzchnia of 100.

Here is my simple XQuery

let $nodes := doc('/db/Dane/akweny.xml')//akweny[ancestor::akwen/nazwa=request:get-parameter("nazwa", ()) and typ=request:get-parameter("typ", ())]
        for $x in $nodes/* 
        let $nazwa := $x/nazwa/text()
        let $typ := $x/typ/text()
        let $powierzchnia := $x/powierzchnia/text()
            where $powierzchnia >= number(request:get-parameter("powierchnia", ()))

My question is:

How to show all the children of the selected node by: nazwa, typ and powierchnia in the form of a bar chart?

Was it helpful?

Solution

Here is an example of doing this in pure XQuery, this will work in eXist, or any other XQuery 1.0 processor:

declare variable $local:max-graph-height := 400; (: pixels :)
declare variable $local:graph-bar-width := 120; (: pixels :)
declare variable $local:graph-bar-spacing := 10; (: pixels :)
declare variable $local:graph-text-below := 20; (: pixels :)

let $awkeny := doc("/db/Dane/akweny.xml")//akwen[xs:int(powierzchnia) gt 100]
let $max-powierzchnia := max($awkeny/powierzchnia)

return

    <svg xmlns="http://www.w3.org/2000/svg" 
        xmlns:xlink="http://www.w3.org/1999/xlink" 
        id="graph"
        height="{ $local:max-graph-height + ($local:graph-text-below * 2) }" 
        width="{ ($local:graph-bar-width + $local:graph-bar-spacing) * count($awkeny) }">

        <linearGradient x1="0%" x2="0%" y1="10%" y2="100%" id="gradient">
            <stop style="stop-color:#0000FF" offset="0"></stop>
            <stop style="stop-color:#FFFFFF" offset="1"></stop>
        </linearGradient>

        {
        for $awken at $i in $awkeny
        let $height := (xs:float($awken/*:powierzchnia) div $max-powierzchnia) * $local:max-graph-height
        let $x := ($i - 1) * ($local:graph-bar-with + $local:graph-bar-spacing)
        let $y := $local:max-graph-height - $height
        return
            (
            <rect width="{$local:graph-bar-with}" 
                height="{$height}" x="{$x}" y="{$y}" 
                fill="url(#gradient)"></rect>,
            <text x="{$x}" 
                y="{$local:max-graph-height + $local:graph-text-below}" 
                fill="red">{$awken/*:nazwa/text()}</text>
            )
        }
    </svg>

The above XQuery when run on your awkeny.xml produces a bar-chart in SVG that looks like the following: SVG Bar Chart of awkeny.xml generated from XQuery

Now I think you just need to work that into your XQuery in eXist as you appear from your example to be taking parameters from the incoming HTTP Request, however I can see from your question that you already know how to do that. So you should now be well on your way...

OTHER TIPS

you could have look at the eXist-db jfreechart extension:

https://github.com/eXist-db/jfreechart

When the image type svgz is specified, a compressed SVG file is generated. Precompiled XAR files (including a simple demo) is available both on GitHub and via the eXist-db package manager (public repo)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top