<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:double="http://www.xstandoff.net/2009/functions/double" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xd="http://www.pnp-software.com/XSLTdoc" xmlns:xsf="http://www.xstandoff.net/2009/xstandoff/1.1" xmlns:string="http://www.xstandoff.net/2009/functions/string" xmlns="http://www.w3.org/2000/svg" xmlns:elem="http://www.xstandoff.net/2009/functions/elem" version="2.0" exclude-result-prefixes="xsf xs string elem double xd">

    

    

    
<!-- ############ STYLESHEET DOCUMENTATION ##########-->

    
              <xd:doc type="stylesheet">

        
<xd:author>Daniel Jettka; daniel.jettka@uni-bielefeld.de</xd:author>

        
<xd:copyright>GNU Lesser General Public License, see below for details</xd:copyright>

        
<xd:short><p><b>XSF2SVG.xsl - Visualisation of XSF instances.</b></p></xd:short>

        
<xd:detail>

            
<p><b>Version 12.02.2011, 11:46 (GMT)</b></p>

            
<p>This program is free software: you can redistribute it and/or modify it under the terms of the GNU GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.</p>

            
<p>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU GNU Lesser General Public License for more details.</p>

            
<p>You should have received a copy of the GNU GNU Lesser General Public License along with this program (file 'lgpl-3.0.txt').  If not, see <a href="http://www.gnu.org/licenses/">http://www.gnu.org/licenses/</a>.</p>

            
<p>The stylesheet XSF2SVG.xsl transforms an XSF instance into an SVG file which displays the 

                levels and layers, and their content respectively, in an hierarchical order. The correspondence 

                of annotation and primary data is demonstrated by mouseover effects implemented in JavaScript.

                The underlying concept allows for the coverage of overlapping markup.
</p>

            
<p>The realisation of the visualisation is strongly influenced by 

                
<a href="http://piez.org/wendell/papers/dh2010/clix-sonnets/index.html">Wendell Piez' solution 

                to visualising overlapping markup
</a>.</p>

            
<p><b>Input XML file:</b> XSF instance</p>

            
<p><b>Additional file (required):</b> a file containing the primary data in plain text</p>

            
<p><b>Stylesheet parameter:</b> max-line-length</p>

            
<p><b>Execution via command line (XSLT processor Saxon9):</b> java -jar saxon9.jar [optional Saxon Parameters] -o [SVG output filename] [XSF input filename] XSF2SVG.xsl</p>

         
</xd:detail>

    
</xd:doc>


    

    

    
<xsl:output method="xml" encoding="UTF-8" doctype-public="-//W3C//DTD SVG 1.1//EN" indent="no" doctype-system="http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" standalone="no" exclude-result-prefixes="#all" />

    

    
              <xd:doc type="xs:integer"><xd:short><p>Maximal length of a line in primary data section. Note: Should allow for a correct and convenient visualisation of element boxes (computed automatically if param is not specified)</p></xd:short></xd:doc>


    
<xsl:param name="max-line-length" select="xs:integer(round($text-line-height - (($text-line-height div 1.5) div $smallest-segment-length)))" as="xs:integer" required="no" />

    

    
<!--##########Keys###########-->

    
              <xd:doc><xd:short><p>Get &lt;xsf:segment&gt; by its @xml:id</p></xd:short></xd:doc>


    
<xsl:key name="seg-by-id" match="xsf:segment" use="@xml:id" />

    
              <xd:doc><xd:short><p>Horizontal offset of elements (stored in @position of element found by the information in use)</p></xd:short></xd:doc>


    
<xsl:key name="horizontal-element-offset" match="@position" use="(../local-name(), ../../position(), ../../../@xml:id)" />

    
              <xd:doc><xd:short><p>Get @count-element-levels from the element referenced by @abs-layer-position</p></xd:short></xd:doc>


    
<xsl:key name="count-element-levels" match="@count-element-levels" use="../@abs-layer-position" />

    
              <xd:doc><xd:short><p>Vertical position of a segment position in the element bars (see global variable $yPos)</p></xd:short></xd:doc>


    
<xsl:key name="yPos" match="@yPos" use="xs:integer(../@position)" />

    
<!--##########################-->

    

    

    
<!--#####Global Variables#####-->

    

    
<!--distances-->

    
              <xd:doc type="xs:integer"><xd:short><p>Absolute distance of the main window from the top</p></xd:short></xd:doc>


    
<xsl:variable name="top-dist" select="50" as="xs:integer" />

    
              <xd:doc type="xs:integer"><xd:short><p>Absolute distance of the main window from the left</p></xd:short></xd:doc>


    
<xsl:variable name="left-dist" select="20" as="xs:integer" />

    
              <xd:doc type="xs:integer"><xd:short><p>Horizontal distance between element boxes</p></xd:short></xd:doc>


    
<xsl:variable name="element-horizontal-dist" select="7" as="xs:integer" />

    
              <xd:doc type="xs:integer"><xd:short><p>Vertical distance between element boxes</p></xd:short></xd:doc>


    
<xsl:variable name="element-vertical-dist" select="1" as="xs:integer" />

    
              <xd:doc type="xs:double"><xd:short><p>Distance between the element name lists</p></xd:short></xd:doc>


    
<xsl:variable name="element-overview-block-dist" select="$element-names-font-size * 3" as="xs:double" />

    
              <xd:doc type="xs:decimal"><xd:short><p>The distance between the overview of the element names from the different layers and the bars representing the individual elements.</p></xd:short></xd:doc>


    
<xsl:variable name="distance-elem-overview-TO-options" select="(max($layers/xsf:layer/count(tokenize(@distinct-elements, ' '))) + 1) * $element-names-line-height" as="xs:decimal" />

    

    
<!--colors-->

    
              <xd:doc type="xs:string"><xd:short><p>Default color for primary data text</p></xd:short></xd:doc>


    
<xsl:variable name="pd-text-color" select="'#646464'" as="xs:string" />

    
              <xd:doc type="xs:string"><xd:short><p>Color for focussed primary data text</p></xd:short></xd:doc>


    
<xsl:variable name="pd-text-focus-color" select="'#ff0000'" as="xs:string" />

    
              <xd:doc type="xs:string"><xd:short><p>Default color of element boxes</p></xd:short></xd:doc>


    
<xsl:variable name="element-color" select="'#bbbbbb'" as="xs:string" />

    
              <xd:doc type="xs:string"><xd:short><p>Color for focussed element boxes</p></xd:short></xd:doc>


    
<xsl:variable name="element-focus-color" select="'#ff0000'" as="xs:string" />

    
              <xd:doc type="xs:string"><xd:short><p>Color for focussed elements which are part of overlaps</p></xd:short></xd:doc>


    
<xsl:variable name="focus-overlap-color" select="'#606060'" as="xs:string" />

    
              <xd:doc type="xs:integer+"><xd:short><p>Colors (hex) for bars from different annotation layers.</p></xd:short></xd:doc>


    
<xsl:variable name="bar-colors" select="('#92ff8f', '#8fc9ff', '#fffb8f', '#ffc98f', '#eb8fff', '#ff8fbc', '#69b767', '#6798b7', '#b6b767', '#b7a567', '#ae67b7', '#b76794')[position() &lt;= count($layers//xsf:layer)]" as="xs:string+" />

        

    
<!--sizes-->

    
              <xd:doc type="xs:integer"><xd:short><p>Font size used</p></xd:short></xd:doc>


    
<xsl:variable name="font-size" select="30" as="xs:integer" />

    
              <xd:doc type="xs:decimal"><xd:short><p>Height of the text lines</p></xd:short></xd:doc>


    
<xsl:variable name="text-line-height" select="$font-size * 1.5" as="xs:decimal" />

    
              <xd:doc type="xs:decimal"><xd:short><p>Font size of element names listed for an overview</p></xd:short></xd:doc>


    
<xsl:variable name="element-names-font-size" select="$font-size * 0.75" as="xs:decimal" />

    
              <xd:doc type="xs:decimal"><xd:short><p>Line height of listed element names</p></xd:short></xd:doc>


    
<xsl:variable name="element-names-line-height" select="$element-names-font-size * 1.5" as="xs:decimal" />

    
              <xd:doc type="xs:integer"><xd:short><p>Width of element boxes</p></xd:short></xd:doc>


    
<xsl:variable name="element-width" select="15" as="xs:integer" />

    
              <xd:doc type="xs:double"><xd:short><p>Width of the block containing the element bars</p></xd:short></xd:doc>


    
<xsl:variable name="element-bars-g-width" select="(2 * $left-dist) + (sum($layers//@count-element-levels) * ($element-horizontal-dist + $element-width))" as="xs:double" />

    
              <xd:doc type="xs:integer"><xd:short><p>Height of a linebreak in the element bar representation</p></xd:short></xd:doc>


    
<xsl:variable name="element-bars-line-break-height" select="2" as="xs:integer" />

    
              <xd:doc type="xs:double"><xd:short><p>Width of a single char in the element names overview</p></xd:short></xd:doc>


    
<xsl:variable name="char-width-element-overview" select="$element-names-font-size div 2" as="xs:double" />

    
              <xd:doc type="xs:decimal"><xd:short><p>Total height of the options panel</p></xd:short></xd:doc>


    
<xsl:variable name="options-height" select="$text-line-height * 1" as="xs:decimal" />

    

    
<!--others-->

    
              <xd:doc type="xs:integer"><xd:short><p>Amount of distinct elements present in all XSF layers</p></xd:short></xd:doc>


    
<xsl:variable name="count-distinct-elements" select="sum(//xsf:layer/count(distinct-values(descendant::*/name())))" as="xs:integer" />

    
              <xd:doc type="xs:integer"><xd:short><p>Amount of lines present in primary data</p></xd:short></xd:doc>


    
<xsl:variable name="count-lines-primary-data" select="count(tokenize($primary-data-text, '\n'))" as="xs:integer" />

    
              <xd:doc type="xs:integer"><xd:short><p>Length of the smallest XSF segment which is not of zero length (empty elements)</p></xd:short></xd:doc>


    
<xsl:variable name="smallest-segment-length" select="xs:integer(min(//xsf:segment/(@end - @start)[. != 0]))" as="xs:integer" />

    
              <xd:doc type="xs:integer"><xd:short><p>Last position of primary data</p></xd:short></xd:doc>


    
<xsl:variable name="pd-end" select="(//xsf:primaryData)[1]/@end" as="xs:integer" />

    

    
              <xd:doc type="xs:string"><xd:short><p>Textual content of the primary data file</p></xd:short></xd:doc>


    
<xsl:variable name="primary-data-text" select="replace((//xsf:textualContent, unparsed-text(replace(//*:primaryDataRef/@uri, '\\', '/'), ((//xsf:primaryDataRef/@encoding, 'UTF-8')[.!=''])[1]))[1], ' ', '')" as="xs:string" />

    

    
              <xd:doc type="document-node()"><xd:short><p>The variable stores the distinct elements included in the layers</p></xd:short></xd:doc>


    
<xsl:variable name="distinct-elements-in-layers">

        
<xsl:for-each select="//xsf:level">

            
<level xmlns="" xml:id="{@xml:id}" xsl:exclude-result-prefixes="#all">

                
<xsl:for-each select="xsf:layer">

                    
<xsl:variable name="namespace" select="namespace-uri((*)[1])" as="xs:anyURI?" />

                    
<xsl:variable name="distinct-elements" as="element()*">

                        
<xsl:for-each select="distinct-values(descendant::*/local-name())">

                            
<xsl:element name="{.}" namespace="{$namespace}">

                                
<xsl:attribute name="position" select="position()" />

                            
</xsl:element>

                        
</xsl:for-each>

                    
</xsl:variable>

                    
<layer ns="{$namespace}" longest-element-name="{max($distinct-elements/string-length(name()))}" xsl:exclude-result-prefixes="#all">

                        
<xsl:copy-of select="$distinct-elements" /> 

                    
</layer>

                
</xsl:for-each>

            
</level>

        
</xsl:for-each>

    
</xsl:variable>

    

    
              <xd:doc type="document-node()"><xd:short><p>The layers together with some additional information computed during the instantiation of this variable are stored here</p></xd:short></xd:doc>


    
<xsl:variable name="layers">

        
<xsl:for-each select="//xsf:layer">

            
<xsf:layer level-id="{../@xml:id}" level-position="{../position()}" abs-layer-position="{position()}" count-element-levels="{max(descendant::*[empty(*)]/(count(ancestor::*[ancestor::xsf:layer]) + 1) )}" distinct-elements="{string-join(distinct-values(descendant::*/local-name()), ' ')}">

                
<xsl:copy-of select="*" />

            
</xsf:layer>

        
</xsl:for-each>

    
</xsl:variable>

    

    
              <xd:doc type="element()+">

        
<xd:short><p>Storage of the lines from primary data in &lt;line&gt; elements.</p></xd:short>

        
<xd:detail><p>If the lines in primary data are too long for a adequate visualisation in element boxes, additional virtual linebreaks are computed.</p></xd:detail>        

    
</xd:doc>


    
<xsl:variable name="lines-primary-data" as="element()+">

        
<xsl:for-each select="tokenize($primary-data-text, '\n')">

            
<xsl:variable name="this-line" select="." as="xs:string" />

            
<xsl:variable name="position" select="position()" as="xs:integer" />

            
<xsl:variable name="preceding-lines" select="tokenize($primary-data-text, '\n')[position() &lt; $position]" as="xs:string*" />

            
<xsl:variable name="length" select="string-length(.)" as="xs:integer" />

            
<xsl:variable name="start-pos" select="sum(for $line in $preceding-lines return (string-length($line) + 1))" as="xs:integer" />

            
<xsl:choose>

                
<xsl:when test="$length = 0">

                    
<line n="{position()}" text="" count-chars="0" start="{$start-pos}" end="{$start-pos}" bar-height-per-pos="{$text-line-height - $element-vertical-dist}" xsl:exclude-result-prefixes="#all" />

                
</xsl:when>

                
<xsl:when test="$length &gt; $max-line-length">

                    
<!--split line into shorter ones ($max-line-length)-->

                    
<xsl:for-each select="0 to xs:integer(ceiling($length div $max-line-length) - 1)">

                        
<xsl:variable name="length" select="string-length(substring($this-line, (. * $max-line-length) + 1, $max-line-length))" as="xs:integer" />

                        
<xsl:variable name="start-pos" select="$start-pos + (. * $max-line-length)" as="xs:integer" />

                        
<line n="{$position}_{position()}" text="{substring($this-line, (. * $max-line-length) + 1, $max-line-length)}" count-chars="{$length}" start="{$start-pos}" end="{$start-pos + $length}" bar-height-per-pos="{(($text-line-height) div $length) - $element-vertical-dist}" xsl:exclude-result-prefixes="#all" />

                    
</xsl:for-each>

                
</xsl:when>

                
<xsl:otherwise>

                    
<line n="{position()}" text="{$this-line}" count-chars="{$length}" start="{$start-pos}" end="{$start-pos + $length}" bar-height-per-pos="{(($text-line-height) div $length) - $element-vertical-dist}" xsl:exclude-result-prefixes="#all" />

                
</xsl:otherwise>

            
</xsl:choose>

        
</xsl:for-each>

    
</xsl:variable>

    

    
              <xd:doc type="document-node()"><xd:short><p>For each distinct position from XSF segment the vertical position in the element bar overview is computed</p></xd:short></xd:doc>


    
<xsl:variable name="yPos">

        
<xsl:for-each select="distinct-values((//xsf:segment/@start, //xsf:segment/@end, //xsf:primaryData/@end))">

            
<yPos position="{.}" yPos="{double:get-yPos(.)}" xsl:exclude-result-prefixes="#all" />

        
</xsl:for-each>

    
</xsl:variable>

    

    
<!--##########################-->

    

    

    
<!--######## Templates ########-->

    
              <xd:doc>

        
<xd:short><p>Initial template matching document element</p></xd:short>

        
<xd:detail><p>In the initial template the main structure of the SVG is implemented, and in addition 

            information on style (CSS) and user interaction (JavaScript) is included
</p></xd:detail>

    
</xd:doc>
    

    
<xsl:template match="/">

        
<svg xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" xsl:exclude-result-prefixes="#all" height="{$top-dist + $distance-elem-overview-TO-options+ $options-height + key('yPos', xs:integer(//xsf:primaryData/@end), $yPos) + $text-line-height}" width="{$left-dist + (sum($layers/xsf:layer/@count-element-levels) * ($element-width + $element-horizontal-dist) + 50) + ($max-line-length * ($font-size div 2))}">

            
<xsl:namespace name="xlink" select="'http://www.w3.org/1999/xlink'" />

            
<xsl:namespace name="xsf" select="'http://www.xstandoff.net/2009/xstandoff/1.1'" />

            
<style type="text/css" id="svg_style">

                text { 
<xsl:value-of select="concat('font-size: ', $font-size, 'px;')" /> } 

                .pd, text.pd, text.pd_visited { 
<xsl:value-of select="concat('fill: ', $pd-text-color, ';')" /> } 

                .pd_active, text.pd_active { 
<xsl:value-of select="concat('fill: ', $pd-text-focus-color, ';')" /> } 

                .pd_visited{ }

                #element-names text, #options text { 
<xsl:value-of select="concat('font-size: ', $element-names-font-size, 'px;')" /> }

                #bar-switches polyline { fill:#bbbbbb; stroke:#666666; stroke-width:1; cursor: pointer; } 

                #element-names rect, #options rect { cursor: pointer; }

                #element-bars g rect{ stroke: black; stroke-width: 1; } 

            
</style>

            

            
<script type="text/javascript">

                barColors = new Array(
<xsl:value-of select="concat('''', string-join($bar-colors, ''','''), '''')" />);

                element_focus_color = '
<xsl:value-of select="$element-focus-color" />';

                focus_overlap_color = '
<xsl:value-of select="$focus-overlap-color" />';

                pd_text_focus_color = '
<xsl:value-of select="$pd-text-focus-color" />';

                pd_text_color = '
<xsl:value-of select="$pd-text-color" />';

                

                function deactivate(elem, elemName){

                    current_class_on = elem.getAttribute('class') == 'on';

                    elem.setAttribute('fill', ((current_class_on ) ? '#ffffff' : barColors[elemName.split('#')[0] - 1]));

                    var elem_bars = document.getElementById('element-bars');

                    var elem_bar_rects = elem_bars.getElementsByTagName('rect');

                    for (var i = 0; i &lt; elem_bar_rects.length; i++) {

                       if(elem_bar_rects[i].getAttribute('class').split(' ')[0] == elemName){

                            elem_bar_rects[i].style.display = ( current_class_on ) ? 'none' : 'block';

                        }

                    }

                    elem.setAttribute('class', (( current_class_on ) ? 'off' : 'on'));

                }

                

                function move_bar(bar, direction){

                    var bar_pos = parseInt(bar.substring(3));

                    var next_bar_pos = parseInt( ( direction == 'left' ) ? bar_pos - 1 : bar_pos + 1);

                    var bar_transform = document.getElementById('bar'+bar_pos).getAttribute('transform');

                    var next_bar_transform = document.getElementById('bar'+next_bar_pos).getAttribute('transform');

                    document.getElementById('bar'+bar_pos).setAttributeNS(null, 'transform', next_bar_transform);

                    document.getElementById('bar'+next_bar_pos).setAttributeNS(null, 'transform', bar_transform);

                    document.getElementById('bar'+bar_pos).setAttributeNS(null, 'id', 'temp_bar');

                    document.getElementById('bar'+next_bar_pos).setAttributeNS(null, 'id', 'bar'+bar_pos);

                    document.getElementById('temp_bar').setAttributeNS(null, 'id', 'bar'+next_bar_pos);

                }

                

                function focE(pos, bool){

                    var elem_bars = document.getElementById('element-bars');

                    var elem_bar_rects = elem_bars.getElementsByTagName('rect');

                    display_overlaps_on = document.getElementById('options_rect').getAttribute('class') == 'on';

                    for (var i = 0; i &lt; elem_bar_rects.length; i++) {

                        class = elem_bar_rects[i].getAttribute('class');

                        start = elem_bar_rects[i].getAttributeNS('http://www.xstandoff.net/2009/xstandoff/1.1', 'start');

                        end = elem_bar_rects[i].getAttributeNS('http://www.xstandoff.net/2009/xstandoff/1.1', 'end');

                        if(pos &gt; start &amp;&amp; pos &lt;= end){

                            elem_bar_rects[i].setAttributeNS(null, 'fill', (bool == 1) ? element_focus_color : (display_overlaps_on &amp;&amp; elem_bar_rects[i].getAttribute('class').split(' ')[1] == 'overlap') ? focus_overlap_color : barColors[class.split('#')[0] - 1]);

                        }

                    }

                }

                

                function focP(elem, IDs, bool){

                    id_array = IDs.split(',');

                    class = (elem.getAttribute('class') != null) ? elem.getAttribute('class') : '';

                    optionsRect_display_on = (document.getElementById('options_rect').getAttribute('class') != null) ? document.getElementById('options_rect').getAttribute('class') == 'on' : false;

                    elem_part_of_overlap = (elem.getAttribute('class').split(' ')[1] != null) ? elem.getAttribute('class').split(' ')[1] == 'overlap' : false;

                    display_overlaps_on = (optionsRect_display_on &amp;&amp; elem_part_of_overlap);

                    elem.setAttributeNS(null, 'fill', (bool == 1) ? element_focus_color : (display_overlaps_on) ? focus_overlap_color : barColors[class.split('#')[0] - 1]);

                    

                    for(var i = 0; i &lt; id_array.length; i++){

                        if(document.getElementById(id_array[i]) != null){

                            document.getElementById(id_array[i]).setAttributeNS(null, 'class', (bool == 1) ? 'pd_active' : 'pd_visited');

                        }

                    }

                    if(document.getElementById(class) != null){

                        document.getElementById(class).setAttributeNS(null, 'fill', (bool == 1) ? pd_text_focus_color : pd_text_color);

                    }

                }

                

                function display_overlaps(elem){

                    current_class_on = elem.getAttribute('class') == 'on';

                    elem.setAttribute('fill', ((current_class_on ) ? '#bbbbbb' : focus_overlap_color));

                    var elem_bars = document.getElementById('element-bars');

                    var elem_bar_rects = elem_bars.getElementsByTagName('rect');

                    for (var i = 0; i &lt; elem_bar_rects.length; i++) {

                        class = elem_bar_rects[i].getAttribute('class');

                        if(class.split(' ')[1] == 'overlap'){

                            elem_bar_rects[i].setAttributeNS(null, 'fill', (current_class_on) ? barColors[class.split('#')[0] - 1] : focus_overlap_color);

                        }

                    }

                    elem.setAttribute('class', (( current_class_on ) ? 'off' : 'on'));

                }

            
</script>

            
<g id="page" transform="translate({$left-dist},{$top-dist})">

                
<g id="head">

                    
<!--***** element overview *****-->

                    
<g id="element-overview" transform="translate(0,0)">

                        
<g id="element-names">

                            
<xsl:for-each select="$layers/xsf:layer">

                                
<xsl:variable name="current-layer-pos" select="@abs-layer-position" as="xs:integer" />

                                
<xsl:variable name="x-offset" select="(sum($layers/xsf:layer[@abs-layer-position &lt; $current-layer-pos]/max(for $elem-name in tokenize(@distinct-elements, ' ') return string-length($elem-name))) * $char-width-element-overview) + (($current-layer-pos - 1) * $element-overview-block-dist)" as="xs:double" />

                                
<xsl:for-each select="tokenize(@distinct-elements, ' ')">

                                    
<rect x="{$x-offset + $left-dist}" y="{(position() - 1) * $element-names-line-height}" width="10" height="10" rx="3" ry="3" fill="{$bar-colors[$current-layer-pos]}" stroke="black" stroke-width="1" class="on" onclick="deactivate(this, '{$current-layer-pos}#{.}');" />

                                    
<text x="{$x-offset + $left-dist + 18}" y="{(position() - 1) * $element-names-line-height + ($font-size div 2.5)}" id="{$current-layer-pos}#{.}" fill="{$pd-text-color}"><xsl:value-of select="." /></text>

                                
</xsl:for-each>

                            
</xsl:for-each>

                        
</g>

                    
</g>

                
</g>

                
<!--***** options *****-->

                
<g id="options" transform="translate(0,{$distance-elem-overview-TO-options})">

                    
<rect x="{$left-dist}" y="-11" width="10" height="10" rx="3" ry="3" fill="#bbbbbb" stroke="black" stroke-width="1" id="options_rect" class="off" onclick="display_overlaps(this);" />

                    
<text x="{$left-dist + 18}" y="0" fill="{$pd-text-color}">display overlaps</text>

                
</g>

                

                
<g id="body" transform="translate(0,{$distance-elem-overview-TO-options + $options-height})">

                    
<!--***** bar switches *****-->

                    
<g id="bar-switches" transform="translate(0,0)">

                        
<xsl:for-each select="1 to xs:integer(sum($layers//@count-element-levels))">

                            
<xsl:variable name="x1" select="position() * ($element-width + $element-horizontal-dist) + ($element-width div 2)" as="xs:double" />

                            
<xsl:variable name="x2" select="position() * ($element-width + $element-horizontal-dist) + ($element-width div 4)" as="xs:double" />

                            
<xsl:variable name="y" select="$font-size div 2" as="xs:double" />

                            
<xsl:variable name="length" select="$element-width div 4" as="xs:double" />

                            
<xsl:if test="position() != 1"><!--left-pointer-->

                                
<polyline points="{$x2 - $length},{$y} {$x2},{$y + (1.5 * $length)} {$x2},{$y - (1.5 * $length)} {$x2 - $length},{$y}" onclick="move_bar('bar{position()}','left')" />

                            
</xsl:if>

                            
<xsl:if test="position() != last()"><!--right-pointer-->

                                
<polyline points="{$x1 + $length},{$y} {$x1},{$y - (1.5 * $length)} {$x1},{$y + (1.5 * $length)} {$x1 + $length},{$y}" onclick="move_bar('bar{position()}','right')" />

                            
</xsl:if>

                        
</xsl:for-each>

                    
</g>

                    
<!--***** element bars *****-->

                    
<g id="element-bars" transform="translate(0,{$font-size})">

                        
<xsl:for-each select="//xsf:layer">

                            
<xsl:variable name="abs-layer-position" as="xs:integer">

                                
<xsl:number level="any" />

                            
</xsl:variable>

                            
<xsl:variable name="x-offset" select="sum($layers/xsf:layer[@abs-layer-position &lt; $abs-layer-position]/@count-element-levels) * ($element-width + $element-horizontal-dist)" as="xs:double" />

                            
<xsl:for-each-group select="descendant::*" group-by="count(ancestor::*[ancestor::xsf:layer])">

                                
<xsl:variable name="x-offset" select="$x-offset + (current-grouping-key() * ($element-width + $element-horizontal-dist))" as="xs:double" />

                                
<g id="bar{sum($layers/xsf:layer[@abs-layer-position &lt; $abs-layer-position]/@count-element-levels) + current-grouping-key() + 1}" transform="translate({$left-dist + $x-offset},0)">

                                    
<!--elements without @xsf:segment not included-->

                                    
<xsl:for-each select="current-group()[@xsf:segment]">

                                        
<xsl:variable name="name" select="local-name()" />

                                        
<xsl:variable name="start-end" select="key('seg-by-id', @xsf:segment)/(@start, @end)" as="xs:integer+" />

                                        
<xsl:variable name="y" select="key('yPos', xs:integer($start-end[1]), $yPos)" as="xs:double" />

                                        
<xsl:variable name="lines-included" select="$lines-primary-data[@start &gt;= $start-end[1] and @end &lt;= $start-end[2]]" as="element()*" />

                                        
<xsl:variable name="positions-not-included-in-complete-lines" as="xs:integer*" select="if(exists($lines-included)) then ((xs:integer($start-end[1] + 1) to xs:integer($lines-included[1]/@start )) , (xs:integer($lines-included[last()]/@end + 1) to $start-end[2])) else ($start-end[1] + 1) to $start-end[2]" />

                                        
<xsl:variable name="IDs" select="string-join(($lines-included/concat('pd-l', @n), (for $pos in $positions-not-included-in-complete-lines return concat('t_', $pos))), ',')" as="xs:string" />

                                        
<xsl:variable name="part-of-overlap" select="exists(root()//xsf:segment[(@start &lt; $start-end[1] and $start-end[1] &lt; @end and @end &lt; $start-end[2]) or ($start-end[1] &lt; @start and @start &lt; $start-end[2] and $start-end[2] &lt; @end)])" as="xs:boolean" />                                        

                                        
<!--not for emtpy elements-->

                                        
<xsl:if test="$start-end[1] &lt; $start-end[2]">

                                            
<rect y="{$y}" width="{$element-width}" fill="{$bar-colors[$abs-layer-position]}" class="{$abs-layer-position}#{$name}{' overlap'[$part-of-overlap]}" title="{$name}, {$start-end[1]}-{$start-end[2]}" onmouseover="focP(this,'{$IDs}',1);" onmouseout="focP(this,'{$IDs}',0);" height="{key('yPos', xs:integer($start-end[2]), $yPos) - $y - (if(($start-end[2]) = $lines-primary-data/@end) then $element-bars-line-break-height else 0)}" xsf:start="{$start-end[1]}" xsf:end="{$start-end[2]}" />

                                        
</xsl:if>

                                    
</xsl:for-each>

                                
</g>

                            
</xsl:for-each-group>

                        
</xsl:for-each>

                    
</g>

                    
<!--***** primary data *****-->

                    
<g id="primary-data" transform="translate({sum($layers/xsf:layer/@count-element-levels) * ($element-width + $element-horizontal-dist) + 50},{$font-size * 2})">

                        
<xsl:for-each select="$lines-primary-data">

                            
<text id="pd-l{@n}" x="0" y="{(position() - 1) * $text-line-height}" class="pd">

                                
<xsl:copy-of select="elem:slice-primaryData(@text, 0, @start)" />

                            
</text>

                        
</xsl:for-each>

                    
</g>

                
</g>

            
</g>

        
</svg>

    
</xsl:template>

    

        

    
              <xd:doc>

        
<xd:short><p>Computing the vertical position of an element (XSF segment) in the element bar overview</p></xd:short>

        
<xd:param name="segPos">Position from XSF segment</xd:param>

    
</xd:doc>
    

    
<xsl:function name="double:get-yPos" as="xs:double">

        
<xsl:param name="segPos" as="xs:integer" />

        
<!--find line containing char position $segPos-->

        
<xsl:variable name="own-line" select="($lines-primary-data[(@start to @end) = $segPos])[last()]" as="element()" />

        
<!--(preceding lines' height) + (height until $segPos in own line)-->

        
<xsl:value-of select="(count($lines-primary-data[(@end to $pd-end) = $segPos] except $own-line) * $text-line-height) + (($segPos - $own-line/@start) * ($own-line/@bar-height-per-pos + $element-vertical-dist))" />

    
</xsl:function>

    

    

    
              <xd:doc>

        
<xd:short><p>For each character in the supplied string ($text) there is a condition whether or not a &lt;tspan&gt;, containing additional 

            information, is output (depends on type of char)
</p></xd:short>

        
<xd:param name="text">String to be sliced</xd:param>

        
<xd:param name="iter">Parameter used for iteration</xd:param>

        
<xd:param name="start-this-line">Position of the first char in the supplied $text with regard to complete primary data</xd:param>

    
</xd:doc>
    

    
<xsl:function name="elem:slice-primaryData" exclude-result-prefixes="#all">

        
<xsl:param name="text" as="xs:string" />

        
<xsl:param name="iter" as="xs:integer" />

        
<xsl:param name="start-this-line" as="xs:integer" />

        
<xsl:variable name="first-char" select="substring($text, 1, 1)" as="xs:string" />

        
<xsl:variable name="abs-position" select="$start-this-line + $iter + 1" as="xs:integer" />

        
<xsl:choose>

            
<xsl:when test="matches($first-char, '\s')">

                
<xsl:choose>

                    
<xsl:when test="string-to-codepoints($first-char) = 13">

                        
<xsl:if test="substring($text, 2)">

                            
<xsl:copy-of select="elem:slice-primaryData(substring($text, 2), $iter, $start-this-line)" />

                        
</xsl:if>

                    
</xsl:when>

                    
<xsl:when test="string-to-codepoints($first-char) = 10">

                        
<xsl:if test="substring($text, 2)">

                            
<xsl:copy-of select="elem:slice-primaryData(substring($text, 2), $iter + 1, $start-this-line)" />

                        
</xsl:if>

                    
</xsl:when>

                    
<xsl:otherwise>

                        
<xsl:element name="tspan">

                            
<xsl:attribute name="id" select="concat('t_', $abs-position)" />

                            
<xsl:attribute name="onmouseover" select="concat('focE(', $abs-position, ',1)')" />

                            
<xsl:attribute name="onmouseout" select="concat('focE(', $abs-position, ',0)')" />

                            
<xsl:attribute name="xml:space" select="'preserve'" />

                            
<xsl:attribute name="title" select="concat(($abs-position - 1), '-', $abs-position)" />

                            
<xsl:text> </xsl:text>

                        
</xsl:element>

                        
<xsl:if test="substring($text, 2)">

                            
<xsl:copy-of select="elem:slice-primaryData(substring($text, 2), $iter + 1, $start-this-line)" />

                        
</xsl:if>

                    
</xsl:otherwise>

                
</xsl:choose>

            
</xsl:when>

            
<xsl:otherwise>

                
<xsl:element name="tspan">

                    
<xsl:attribute name="id" select="concat('t_', $abs-position)" />

                    
<xsl:attribute name="onmouseover" select="concat('focE(', $abs-position, ',1)')" />

                    
<xsl:attribute name="onmouseout" select="concat('focE(', $abs-position, ',0)')" />

                    
<xsl:attribute name="title" select="concat(($abs-position - 1), '-', $abs-position)" />

                    
<xsl:value-of select="$first-char" />

                
</xsl:element>

                
<xsl:if test="substring($text, 2)">

                    
<xsl:copy-of select="elem:slice-primaryData(substring($text, 2), $iter + 1, $start-this-line)" />

                
</xsl:if>

            
</xsl:otherwise>

        
</xsl:choose>

    
</xsl:function>

        

</xsl:stylesheet>













































































v