<xsl:stylesheet xmlns:attr="http://www.xstandoff.net/2009/functions/attr" xmlns:bool="http://www.xstandoff.net/2009/functions/bool" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:doc="http://www.xstandoff.net/2009/functions/doc" xmlns:double="http://www.xstandoff.net/2009/functions/double" xmlns:all="http://www.xstandoff.net/2009/all" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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:undef="http://www.xstandoff.net/2009/functions/undef" xmlns:elem="http://www.xstandoff.net/2009/functions/elem" version="2.0" exclude-result-prefixes="string undef elem attr double xs bool doc all xsf xd">

    

    

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

    
              <xd:doc type="stylesheet">

        
<xd:author>Daniel Jettka; daniel.jettka@uni-bielefeld.de; Project Sekimo (A2), DFG Research Group 437</xd:author>

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

        
<xd:short><p><b>mergeXSF.xsl - Merging standoff XSF files</b></p></xd:short>

        
<xd:detail>

            
<p><b>Version 04.03.2011, 16:50 (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>Due to the frequent use of the ID/IDREF mechanism in XStandoff, a manual merging of XStandoff files seems quite unpromising. 

                The XSLT stylesheet mergeXSF.xsl file is provided as the input file of the transformation, the second file's name has to be included 

                via the stylesheet parameter merge-with.
</p>

            
<p>The main problem which is solved by the stylesheet is to adapt the segments from the involved XStandoff files to each other. On the 

                one hand there are segments in the different files spanning over the same string of the primary data, but having distinct IDs. In this 

                case the two segments have to be replaced by one. On the other hand there will be segments with the same ID, but spanning over 

                different character positions. These have to get new unequal IDs. The merging of the XStandoff files in general leads to a complete 

                reorganization of the segment list making it necessary to update the segment references of the elements in the XStandoff layers. 

                After fulfilling this duty, the XStandoff layers are included in the new XStandoff file.
</p>

            
<p>The reorganization of the segment list can be disabled by configuring the stylesheet parameter keep-segments. Specifying the value 

                '1' causes the perpetuation of the segments of the input XStandoff file. However, the segments of the file provided by merge-with 

                have to be subject of a reorganization.
</p>

            
<p>In addition, the stylesheet handles the optional output of the 'all-layer'. The stylesheet parameter all-layer, in case it is set to '1', 

                evokes the inclusion of the layer which contains the elements that are present in all annotation layers. It is irrelevant if there was 

                an 'all-layer' present in the input files or not. Though it might happen that no such layer is returned, namely if there are no elements 

                in the several layers which share the required features.
</p>

            
<p>Currently the stylesheet only supports the merging of two single XStandoff files. Naturally this allows for a successive merging of 

                more than two files. However it would be more straightforward to have the possibility of merging more than two XStandoff files with 

                a single transformation. The update of the stylesheet to support this is in preparation.
</p>

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

            
<p><b>Additional file (required):</b> a second XSF instance which should be merged with the first one</p>

            
<p><b>Stylesheet parameters:</b> 

                
<ul>

                    
<li>merge-with=$xsf-file - name of the second XSF file</li>

                    
<li>keep-segments=xs:boolean - segments of the input file (the first XSF instance) remain unchanged, new segments (of the second file) are appended at the end</li>

                    
<li>all-layer=xs:boolean - determines the return of a layer containing elements that appear in all layers</li>

                    
<li>nest-by=xs:string('measure' | 'priority') - heuristics for nesting elements with same start and end positions; default 'measure' leads statistical measuring</li>

                
</ul>

            
</p>

            
<p><b>Execution via command line (XSLT processor Saxon9):</b> java -jar saxon9.jar [optional Saxon Parameters] -o [XML output filename] [XSF input filename] mergeXSF.xsl merge-with=[2nd XSF instance] [optional Stylesheet Parameters]</p>

            
<p>

                
<b>Known problems:</b>

                
<ul>

                    
<li>different character encodings used for primary data file and input XML file (first XSF instance) can cause problems</li>

                
</ul>

            
</p>

        
</xd:detail>

    
</xd:doc>


    

    

    
<xsl:output indent="yes" method="xml" encoding="UTF-8" />

    

    
<!--#####Stylesheet Parameters#####-->

    
              <xd:doc type="xs:string"><xd:short><p>Relative path to the primary data instance</p></xd:short></xd:doc>


    
<xsl:param name="merge-with" as="xs:string" required="yes" />

    

    
              <xd:doc type="xs:boolean"><xd:short><p>Keeping the segments of the transformation basis? Default: false</p></xd:short></xd:doc>


    
<xsl:param name="keep-segments" select="false()" as="xs:boolean" />

    

    
              <xd:doc type="xs:boolean"><xd:short><p>Determines the return of a layer containing elements that appear in all layers.  Default: false</p></xd:short></xd:doc>


    
<xsl:param name="all-layer" select="false()" as="xs:boolean" />

    

    
              <xd:doc type="xs:string">

        
<xd:short><p>Determination of heuristics to nest elements with the same boundary position into one another.</p></xd:short>

        
<xd:detail><p>The default value for the nesting heuristics is 'measure' which calls a statistical analysis and nests elements into 

            one another by measuring the embedding relation. The value 'priority' evokes the nesting by the attribute @priority which is optional

            for every layer element. By this means the nesting can be determined manually.
</p></xd:detail>

    
</xd:doc>


    
<xsl:param name="nest-by" select="'measure'" as="xs:string" />

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

    

    

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

    
              <xd:doc><xd:short><p>Find elements by their ID attribute; no matter which namespace @id is bound by</p></xd:short></xd:doc>


    
<xsl:key name="elem-by-id" match="*" use="((if($is-schema-aware) then attribute(*, xs:ID) else @*:id), generate-id())[1]" />

    

    
              <xd:doc><xd:short><p>Find elements by their element name → name()</p></xd:short></xd:doc>


    
<xsl:key name="elem-by-name" match="*" use="name()" />

    

    
              <xd:doc><xd:short><p>Find elements by a combination of their local-name and the segment reference given by @xsf:segment</p></xd:short></xd:doc>


    
<xsl:key name="elem-by-local-name-and-segRef" match="*" use="concat(local-name(), '#', @xsf:segment)" />

    

    
              <xd:doc><xd:short><p>Find elements by their segment reference @xsf:segment</p></xd:short></xd:doc>


    
<xsl:key name="elem-by-segRef" match="*" use="@xsf:segment" />

    

    
              <xd:doc><xd:short><p>Find elements named "measure" by the concatenation of their attributes @parent and @child; applied to temporary tree created by <i>doc:inclusion-measures()</i></p></xd:short></xd:doc>


    
<xsl:key name="measure" match="measure" use="concat(@parent, @child)" />

    

    
              <xd:doc>Find element by the value of its attribute @XSF1ID</xd:doc>


    
<xsl:key name="seg-by-XSF1ID" match="*:segment" use="@XSF1ID" />

    

    
              <xd:doc>Find element by the value of its attribute @XSF2ID</xd:doc>


    
<xsl:key name="seg-by-XSF2ID" match="*:segment" use="@XSF2ID" />    

    

    
              <xd:doc>Find element by the value of its attribute @XSF2ID</xd:doc>


    
<xsl:key name="seg-id-by-start-and-end" match="xsf:segment/@xml:id" use="../concat(@start, '#', @end)" />

    

    
              <xd:doc>Find an element xsf:segment using the value of its attribute @XSF1ID and @*[contains(., $all-layer-namespace)]/local-name()</xd:doc>


    
<xsl:key name="seg-containing-all-layer-elem" match="xsf:segment" use="@XSF1ID, @*[contains(., $all-layer-namespace)]/local-name()" />

    

    
              <xd:doc>Index of IDs which occur with same value in $XSF1 and $XSF2</xd:doc>


    
<xsl:key name="concurrent-IDs" match="concurrent-ID" use="@old-id" />

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

    

    

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

    
              <xd:doc><xd:short><p>URI of the "all-layer" namespace.</p></xd:short></xd:doc>


    
<xsl:variable name="all-layer-namespace" select="xs:anyURI('http://www.xstandoff.net/2009/all')" as="xs:anyURI" />

    

    
              <xd:doc><xd:short><p>Directory location of the current stylesheet.</p></xd:short></xd:doc>


    
<xsl:variable name="stylesheet-directory" select="concat(string-join(tokenize(static-base-uri(), '/')[position()!=last()], '/'), '/')" as="xs:string" />

    

    
              <xd:doc><xd:short><p>Making $merge-with usable as URI for document().</p></xd:short></xd:doc>


    
<xsl:variable name="merge-with-file" select="replace($merge-with, '\\', '/')" as="xs:string" />

    

    
              <xd:doc><xd:short><p>Root of the first XSF file to be merged (XML transformation input).</p></xd:short></xd:doc>


    
<xsl:variable name="XSF1" select="/" />

    

    
              <xd:doc><xd:short><p>Root of the second XSF file to be merged (provided by $merge-with).</p></xd:short></xd:doc>


    
<xsl:variable name="XSF2" select="document( if(doc-available($merge-with-file)) then $merge-with-file else ( if(doc-available(concat('../', $merge-with-file))) then concat('../', $merge-with-file) else error((), concat('***ERROR: no file ', $merge-with-file, ' existing (provide path from ', $stylesheet-directory, ')!.')) ))" />

    

    
<!---->

    
              <xd:doc><xd:short><p>Namespaces of the layers appearing in the XSF files (all but "all-layer") - input XML file</p></xd:short></xd:doc>


    
<xsl:variable name="XSF1-namespaces" select="distinct-values($XSF1//xsf:layer/(*)[1]/namespace-uri()[.!=$all-layer-namespace])" as="xs:anyURI+" />

    

    
              <xd:doc><xd:short><p>Namespaces of the layers appearing in the XSF files (all but "all-layer") - $merge-with file</p></xd:short></xd:doc>


    
<xsl:variable name="XSF2-namespaces" select="distinct-values($XSF2//xsf:layer/(*)[1]/namespace-uri()[.!=$all-layer-namespace])" as="xs:anyURI+" />

    

    
              <xd:doc><xd:short><p>Primary data with automatic encoding detection (input XML file)</p></xd:short></xd:doc>


    
<xsl:variable name="XSF1-primaryData" select="( (:#1:) //xsf:primaryData/xsf:textualContent/text(), (:#2:) unparsed-text(concat($stylesheet-directory, replace(//xsf:primaryDataRef/@uri, '\\', '/')), ((//xsf:primaryDataRef/@encoding, 'UTF-8')[.!=''])[1])[1], (:#3:) error((), 'No primary data found for 1st XSF-file (transformation base)'))[1]" as="xs:string" />

    

    
              <xd:doc><xd:short><p>Primary data with automatic encoding detection (file from $merge-with)</p></xd:short></xd:doc>


    
<xsl:variable name="XSF2-primaryData" select="( (:#1:) $XSF2//xsf:primaryData/xsf:textualContent/text(), (:#2:) unparsed-text(concat($stylesheet-directory, replace($XSF2//xsf:primaryDataRef/@uri, '\\', '/')), (($XSF2//xsf:primaryDataRef/@encoding, 'UTF-8')[.!=''])[1])[1], (:#3:) error((), concat('No primary data found for 2nd XSF-file (', $merge-with, ')')))[1]" as="xs:string" />

    

    
              <xd:doc><xd:short><p>Contains segments occuring in both XSF files</p></xd:short></xd:doc>


    
<xsl:variable name="newSegments">

        
<xsl:copy-of select="elem:merge-segments()" />

    
</xsl:variable>

    

    
              <xd:doc><xd:short><p>Variable contains the "all-layer" which was created by <i>elem:process-layer()</i> if $all-layer=true()</p></xd:short></xd:doc>


    
<xsl:variable name="all-layer-doc">

        
<xsl:copy-of select="if($all-layer) then elem:process-layer(($XSF1//xsf:layer[(*)[1]/namespace-uri()=$all-layer-namespace], ($XSF1//xsf:layer)[1])[1]/*, $all-layer-namespace, 'XSF1') else ()" />

    
</xsl:variable>

    

    
              <xd:doc><xd:short><p>The several namespaces present in the XSF files.</p></xd:short></xd:doc>


    
<xsl:variable name="namespaces" as="element()+">

        
<xsl:for-each select="$XSF1-namespaces">

            
<ns uri="{.}" prefix="{( prefix-from-QName(($XSF1//*[namespace-uri() = current()])[1]/node-name(.)), concat('ns1-', position()) )[1]}" source="XSF1" />

        
</xsl:for-each>

        
<xsl:for-each select="$XSF2-namespaces">

            
<ns uri="{.}" prefix="{( prefix-from-QName(($XSF2//*[namespace-uri() = current()])[1]/node-name(.)), concat('ns2-', position()) )[1]}" source="XSF2" />

        
</xsl:for-each>

    
</xsl:variable>

    

    
              <xd:doc><xd:short><p>Test for same IDs in input files. Contains the generated IDs of layers which contain ID-attributes which are also present in other layer(s).</p></xd:short></xd:doc>


    
<xsl:variable name="concurrent-IDs" as="document-node()">

        
<xsl:document>

            
<xsl:if test="$is-schema-aware">

                
<xsl:for-each select="$XSF2//xsf:layer//attribute(*, xs:ID)[. = $XSF1//xsf:layer//attribute(*, xs:ID)]">

                    
<xsl:variable name="pos-level">

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

                            
<xsl:number level="any" />

                        
</xsl:for-each>

                    
</xsl:variable>c

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

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

                            
<xsl:number level="single" />

                        
</xsl:for-each>

                    
</xsl:variable>

                    
<concurrent-ID old-id="{.}" new-id="{concat('l', $pos-level, 'l', $pos-layer, '_', .)}" />

                
</xsl:for-each>

            
</xsl:if>

        
</xsl:document>

    
</xsl:variable>

    

    
              <xd:doc><xd:short><p>Indicator if current transformation shall be schema-aware. Can be overwritten if "mergeXSF.xsl" is imported by "mergeXSF-sa.xsl".</p></xd:short></xd:doc>


    
<xsl:variable name="is-schema-aware" select="false()" as="xs:boolean" />

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

    

    

    
              <xd:doc>

        
<xd:short><p>Template matching the root of the document to be transformed.</p></xd:short>

        
<xd:detail>

            
<p>

                The initial template is naturally the starting point of the transformation. In this special case, it just calls 

                the template named 'main' which incorporates the first steps of the transformation.

            
</p>

            
<p>

                This strategy contributes to the schema-aware version of this stylesheet ('mergeXSF-sa.xsl') which validates the 

                input XSF instances and allows for the caption and handling of multiple IDs in the resulting merged XSF instance.

            
</p>

        
</xd:detail>

    
</xd:doc>


    
<xsl:template match="/">

        
<xsl:message select="''" />

        
<xsl:message select="' Merging XSF instances (NON-schema-aware stylesheet version)'" />

        
<xsl:call-template name="main" />

    
</xsl:template>

    

    

    
              <xd:doc>

        
<xd:short><p>Template called by initial template (matching '/').</p></xd:short>

        
<xd:detail>

            
<p>

                
<ul>

                    
<li>Returning messages on supplied stylesheet parameters → <i>undef:param-messages()</i></li>

                    
<li>Checking and returning of primary data → <i>undef:test-and-return-pd()</i></li>

                    
<li>Creation of a new merged segment list (&lt;xsf:segmentation&gt;) using $newSegments</li>

                    
<li>

                        Returning the several layers of the two XSF instances into one &lt;xsf:annotation&gt;. Therefore they have to 

                        be compared for uniqueness and elements have to be supplied by updated segment references.

                    
</li>

                
</ul>

                Detailed information on the several processing steps is available at the documentation of the individual templates and functions called. 

            
</p>

        
</xd:detail>

    
</xd:doc>


    
<xsl:template name="main">

        

        
<xsl:copy-of select="undef:param-messages()" />

        

        
<!--########for analyzing bugs only########-->

        

         
<!--   

             <xsl:result-document href="logs/new-segments.xml"><seg><xsl:copy-of select="$newSegments//*"/></seg></xsl:result-document>

            <xsl:result-document href="logs/namespaces.xml"><ns><xsl:copy-of select="$namespaces"/></ns></xsl:result-document>

            <xsl:result-document href="logs/all-layer.xml"><all><xsl:copy-of select="$all-layer-doc"/></all></xsl:result-document>

            <xsl:result-document href="logs/measures.xml"><measures><xsl:copy-of select="doc:inclusion-measures()"/></measures></xsl:result-document>

         
-->

        

        
<xsf:corpusData xmlns="http://www.xstandoff.net/2009/xstandoff/1.1" xsfVersion="1.1" xml:id="{concat(//xsf:corpusData/@xml:id, '-', $XSF2//xsf:corpusData/@xml:id)}">

            
<xsl:copy-of select="//xsf:corpusData/@*[name()!='xsfVersion' and name()!='xml:id']" />

            

            
<!--testing whether there are layers in distinct files with same IDs-->

            
<xsl:copy-of select="undef:check-layer-IDs()" />

            

            
<!--testing primary data identity and in case everything is okay, returning if primary data information-->

            
<xsl:copy-of select="undef:test-and-return-pd()" />

            

            
<!--merged segments of the XSF files-->

            
<xsf:segmentation>

                
<xsl:for-each select="$newSegments//*">

                    
<xsl:copy>

                        
<xsl:copy-of select="@xml:id, @type, @start, @end" />

                    
</xsl:copy>

                
</xsl:for-each>

            
</xsf:segmentation>

            

            
<!--##########distinction of ID'ed annotations/levels/layers and those without##############-->

            
<xsf:annotation>

                

                
<!--returning the level for elements in all layers (the 'all-layer')-->

                
<xsl:if test="$all-layer and exists($all-layer-doc/*)">

                    
<xsf:level xml:id="all-level">

                        
<xsf:layer priority="0" xsi:schemaLocation="{concat($all-layer-namespace, ' xsf.xsd')}">

                            
<xsl:namespace name="all" select="$all-layer-namespace" />

                            
<xsl:for-each select="$XSF1-namespaces">

                                
<xsl:namespace name="{( prefix-from-QName(($XSF1//*[namespace-uri() = current()])[1]/node-name(.)), concat('ns1-', position()) )[1]}" select="." />

                            
</xsl:for-each>

                            
<xsl:for-each select="$XSF2-namespaces">

                                
<xsl:namespace name="{( prefix-from-QName(($XSF2//*[namespace-uri() = current()])[1]/node-name(.)), concat('ns2-', position()) )[1]}" select="." />

                            
</xsl:for-each>

                            
<xsl:message select="concat(' # Processing layer (namespace URI: ', $all-layer-namespace, ')')" />

                            
<!-- OLD VERSION (use for debug): <xsl:message select="' *** Processing layer (elem:process-layer()) /', $all-layer-namespace"/>-->

                            
<xsl:copy-of select="$all-layer-doc" />

                        
</xsf:layer>

                    
</xsf:level>

                
</xsl:if>

                

                
<!--returning <xsf:level> elements for other namespaces-->

                
<xsl:for-each select="distinct-values(($XSF1|$XSF2)//xsf:annotation/xsf:level[(*)[1]/namespace-uri()!=$all-layer-namespace]/string:get-id(.))">

                    
<xsf:level xml:id="{.}">

                        
<xsl:variable name="level-id" select="." as="xs:string" />

                        
<xsl:for-each select="'XSF1', 'XSF2'">

                            
<xsl:variable name="current-XSF-instance" select="." as="xs:string" />

                            
<xsl:for-each select="key('elem-by-id', $level-id, (if(. = 'XSF1') then $XSF1 else $XSF2))/xsf:layer">

                                
<xsl:variable name="layer-prefix" as="xs:string">

                                    
<xsl:variable name="pos-level">

                                        
<xsl:for-each select="..">

                                            
<xsl:number level="any" />

                                        
</xsl:for-each>

                                    
</xsl:variable>

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

                                        
<xsl:number level="single" />

                                    
</xsl:variable>

                                    
<xsl:value-of select="concat('l', $pos-level, 'l', $pos-layer)" />

                                
</xsl:variable>

                                
<xsl:copy>

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

                                    
<!--different handling of layers due to presence of $all-layer in input XSF instances-->

                                    
<xsl:choose>

                                        
<!--if there is no all-layer in the corresponding input ($XSF1 or $XSF2), the output of the layer can be based on the actual input annotation-->

                                        
<xsl:when test="empty((if($current-XSF-instance = 'XSF1') then $XSF1 else $XSF2)//xsf:layer/((*)[1])[namespace-uri()=$all-layer-namespace])">

                                            
<xsl:message select="concat(' # Processing layer (namespace URI: ', ((*)[1]/namespace-uri()[. != ''], 'no namespace')[1], ')')" />

                                            
<!-- OLD VERSION (use for debug): <xsl:message select="' *** Processing layer (elem:process-layer()) /', ((*)[1]/namespace-uri()[. != ''], 'no namespace')[1]"/>-->

                                            
<xsl:copy-of select="elem:process-layer(*, (element())[1]/namespace-uri(), $current-XSF-instance)" />

                                        
</xsl:when>

                                        
<!--The following strategy applies if there is a need for checking if an element already was output for the 'all-layer' -->

                                        
<xsl:otherwise>

                                            
<xsl:message select="concat(' # Processing layer (namespace URI: ', (*)[1]/namespace-uri(), ')')" />

                                            
<!-- OLD VERSION (use for debug): <xsl:message select="' *** Processing layer (elem:segments2inline()) /', (*)[1]/namespace-uri()"/>-->

                                            
<xsl:copy-of select="elem:segments2inline($newSegments//*, (*)[1]/namespace-uri(), $current-XSF-instance, prefix-from-QName((*)[1]/node-name(.)))" />

                                        
</xsl:otherwise>

                                    
</xsl:choose>

                                    
<!--

                                        <xsl:call-template name="copyNodes">

                                        <xsl:with-param name="source" select="$current-XSF" as="xs:string"/>

                                        </xsl:call-template>

                                    
-->

                                
</xsl:copy>

                            
</xsl:for-each>

                        
</xsl:for-each>

                    
</xsf:level>

                
</xsl:for-each>

            
</xsf:annotation>

        
</xsf:corpusData>

    
</xsl:template>

    

    

    
              <xd:doc>

        
<xd:short><p>Template copies child elements of the context node recursively and replaces old IDs by new ones (from $newSegments)</p></xd:short>

        
<xd:param name="source">Name of the root of the context element ('XSF1' or 'XSF2')</xd:param>

    
</xd:doc>


    
<xsl:template name="copyNodes">

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

        
<xsl:for-each select="*">

            
<xsl:copy copy-namespaces="no">

                
<xsl:copy-of select="@*[name()!='xsf:segment']" />

                
<!--u.U. gibt es (leere) Elemente, die gar kein @xsf:segment enthalten. Das soll so bleiben-->

                
<xsl:if test="@xsf:segment">

                    
<xsl:attribute name="xsf:segment" select="$newSegments//*[@*[name()=concat($source, 'ID')]=current()/@xsf:segment]/@xml:id" />

                
</xsl:if>

                
<xsl:call-template name="copyNodes">

                    
<xsl:with-param name="source" select="$source" as="xs:string" />

                
</xsl:call-template>

            
</xsl:copy>

        
</xsl:for-each>

    
</xsl:template>

    

    

    
              <xd:doc><xd:short><p>Combining the segments from both XSF files</p></xd:short></xd:doc>


    
<xsl:function name="elem:merge-segments" as="element()+">

        
<xsl:message select="' # Merging segments from files'" />

        
<!--Segmente der ersten XSF-Datei (Transformationsbasis)-->

        
<xsl:variable name="XSF1segments" as="element(xsf:segment)*">

            
<xsl:for-each select="$XSF1//xsf:segment">

                
<xsf:segment XSF1ID="{@xml:id}" XSF2ID="{key('seg-id-by-start-and-end', concat(@start, '#', @end), $XSF2)}">

                    
<xsl:copy-of select="@*[name()!='xml:id']" />

                
</xsf:segment>

            
</xsl:for-each>

        
</xsl:variable>

        
<!--Segmente der zweiten XSF-Datei ($merge-with)-->

        
<xsl:variable name="XSF2segments" as="element(xsf:segment)*">

            
<xsl:for-each select="$XSF2//xsf:segment">

                
<xsf:segment XSF2ID="{@xml:id}">

                    
<xsl:copy-of select="@* except @xml:id" />

                
</xsf:segment>

            
</xsl:for-each>

        
</xsl:variable>

        
<!--Segmente, die mit gleichen Start- und Endpositionen in beiden Dateien vorkommen-->

        
<xsl:variable name="commonSegments">

            
<xsl:copy-of select="$XSF1segments[@XSF2ID!='']" />

        
</xsl:variable>

        
<xsl:choose>

            
<!--für den Fall, dass die Segmente der zweiten Datei angehängt werden sollen-->

            
<xsl:when test="$keep-segments">

                
<xsl:message select="' - keeping segments from first XSF file'" />

                
<xsl:variable name="keeping-segments" as="element(xsf:segment)*">

                    
<xsl:for-each select="$XSF1segments">

                        
<xsf:segment xml:id="{@XSF1ID}">

                            
<xsl:copy-of select="@* except @xml:id" />

                        
</xsf:segment>

                    
</xsl:for-each>

                    
<xsl:variable name="count-XSF1-segments" select="count($XSF1segments)" as="xs:integer" />

                    
<xsl:for-each select="$XSF2segments[empty(key('seg-by-XSF2ID', @XSF2ID, $commonSegments))]">

                        
<xsf:segment xml:id="{concat('seg', string(position() + $count-XSF1-segments))}">

                            
<xsl:copy-of select="@* except @xml:id" />

                        
</xsf:segment>

                    
</xsl:for-each>

                
</xsl:variable>

                
<xsl:copy-of select="elem:copy-segments-with-new-ID-and-elem-info(elem:sort-segments( $keeping-segments ))" />

            
</xsl:when>

            
<!--für den Fall, dass neue Segmente aus beiden zusammengestellt werden sollen-->

            
<xsl:otherwise>

                
<xsl:copy-of select="elem:copy-segments-with-new-ID-and-elem-info(elem:sort-segments( (:###gemeinsame Segmente werden mit nicht-gemeinsamen zusammengeführt###:) ($XSF1segments[@XSF2ID=''], $XSF2segments[empty(key('seg-by-XSF2ID', @XSF2ID, $commonSegments))], $commonSegments//xsf:segment) ))" />

            
</xsl:otherwise>

        
</xsl:choose>

        
<xsl:message select="' - segments merged.'" />

    
</xsl:function>

    

    

    
              <xd:doc>

        
<xd:short><p>Deriving first distinct char of two unequal strings </p></xd:short>

        
<xd:param name="string1">First string which shall be compared to second</xd:param>

        
<xd:param name="string2">Second string; to be compared to $string1</xd:param>

        
<xd:param name="position">Position counter for recursive calling of this funtion on substrings of the two strings</xd:param>

    
</xd:doc>


    
<xsl:function name="string:first-distinct-char" as="xs:string+">

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

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

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

        
<xsl:choose>

            
<xsl:when test="($string1 != $string2) and ((string-length($string1) + string-length($string2)) &gt; 0)">

                
<xsl:choose>

                    
<xsl:when test="substring($string1, 1, 100) != substring($string2, 1, 100)">

                        
<xsl:variable name="string1" select="substring($string1, 1, 100)" as="xs:string" />

                        
<xsl:variable name="string2" select="substring($string2, 1, 100)" as="xs:string" />

                        
<xsl:choose>

                            
<xsl:when test="string-length($string1) = 0">

                                
<xsl:value-of select="concat('$XSF2-primaryData (', string-length($XSF2-primaryData), ') is longer than $XSF1-primaryData (', string-length($XSF1-primaryData), ').')" />

                            
</xsl:when>

                            
<xsl:when test="string-length($string2) = 0">

                                
<xsl:value-of select="concat('$XSF1-primaryData (', string-length($XSF1-primaryData), ') is longer than $XSF2-primaryData (', string-length($XSF2-primaryData), ').')" />

                            
</xsl:when>

                            
<xsl:when test="substring($string1, 1, 1) != substring($string2, 1, 1)">

                                
<xsl:value-of select="concat('Position ', $position, ': ', substring($string1, 1, 1), '!=', substring($string2, 1, 1))" />

                            
</xsl:when>

                            
<xsl:otherwise>

                                
<xsl:value-of select="string:first-distinct-char(substring($string1, 2), substring($string2, 2), $position+1)" />

                            
</xsl:otherwise>

                        
</xsl:choose>

                    
</xsl:when>

                    
<xsl:otherwise>

                        
<xsl:value-of select="string:first-distinct-char(substring($string1, 100), substring($string2, 100), $position+100)" />

                    
</xsl:otherwise>

                
</xsl:choose>

            
</xsl:when>

            
<xsl:otherwise>

                
<xsl:value-of select="'string:first-distinct-char() untersucht Texte mit identischem Zeicheninhalt'" />

            
</xsl:otherwise>

        
</xsl:choose>

    
</xsl:function>

    

    

    
              <xd:doc>

        
<xd:short><p>Segments get new IDs and are returned; the temporary information (@XSF1ID und @XSF2ID) is being kept; additionally information on elements spanning over this segment is returned</p></xd:short>

        
<xd:param name="segments">Segments which are supplied with updated IDs.</xd:param>

    
</xd:doc>


    
<xsl:function name="elem:copy-segments-with-new-ID-and-elem-info" as="element(xsf:segment)*">

        
<xsl:param name="segments" as="element(xsf:segment)*" />

        
<xsl:message select="' - generating new segment IDs'" />

        
<xsl:for-each select="$segments">

            
<xsl:variable name="new-seg" select="concat('seg', position())" as="xs:string" />

            
<xsf:segment xml:id="{$new-seg}">

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

                
<xsl:variable name="XSF1-elems-this-seg" select="key('elem-by-segRef', @XSF1ID, $XSF1)" as="element()*" />

                
<xsl:variable name="XSF2-elems-this-seg" select="key('elem-by-segRef', @XSF2ID, $XSF2)" as="element()*" />

                
<xsl:for-each select="distinct-values(($XSF1-elems-this-seg, $XSF2-elems-this-seg)/local-name())">

                    
<xsl:variable name="namespaces-this-elem-name" as="xs:anyURI+" select="distinct-values( for $current-source in ('XSF1', 'XSF2') return ( for $elem in (if($current-source='XSF1') then $XSF1-elems-this-seg else $XSF2-elems-this-seg)[local-name()=current()] return ( if($elem/namespace-uri()!=$all-layer-namespace) then $elem/namespace-uri() else (if($current-source='XSF1') then $XSF1-namespaces else $XSF2-namespaces) ) ) )" />

                    
<!--<xsl:message select="$new-seg, ' ## XSF1-elems-this-seg:', $XSF1-elems-this-seg/local-name(), ' XSF2-elems-this-seg:', $XSF2-elems-this-seg/local-name(), ' $namespaces-this-elem-name', $namespaces-this-elem-name, '###'"/>-->

                    
<xsl:attribute name="{.}" select="if($all-layer) then (:###ADDED (16.09.2010): ''and (count(($XSF1-namespaces, $XSF2-namespaces)) = count($namespaces-this-elem-name))''###:) if(every $ns in ($XSF1-namespaces, $XSF2-namespaces) satisfies ($ns=$namespaces-this-elem-name) and (count(($XSF1-namespaces, $XSF2-namespaces)) = count($namespaces-this-elem-name))) then $all-layer-namespace else string-join($namespaces-this-elem-name, ' ') else string-join($namespaces-this-elem-name, ' ')" />

                
</xsl:for-each>

            
</xsf:segment>

        
</xsl:for-each>

    
</xsl:function>

    

    

    
              <xd:doc>

        
<xd:short><p>Sorting segments on the basis of their attributes @start and @end</p></xd:short>

        
<xd:param name="segments">Segments which are sorted in this function.</xd:param>

    
</xd:doc>


    
<xsl:function name="elem:sort-segments" as="element(xsf:segment)*">

        
<xsl:param name="segments" as="element(xsf:segment)*" />

        
<xsl:message select="' - sorting segments'" />

        
<xsl:for-each select="$segments">

            
<xsl:sort select="@start" data-type="number" order="ascending" />  

            
<xsl:sort select="@end" data-type="number" order="descending" />

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

        
</xsl:for-each>

    
</xsl:function>

    

    

    
              <xd:doc><xd:short><p>Checking for primary data identity by comparing the content of the &lt;xsf:primaryData&gt; of the input annotations</p></xd:short></xd:doc>


    
<xsl:function name="undef:test-and-return-pd">

        
<xsl:message select="' # Testing primary data identity'" />

        
<xsl:variable name="XSF1start-EQ-XSF2start" select="$XSF1//xsf:primaryData/@start = $XSF2//xsf:primaryData/@start" as="xs:boolean" />

        
<xsl:variable name="XSF1end-EQ-XSF2end" select="$XSF1//xsf:primaryData/@end = $XSF2//xsf:primaryData/@end" as="xs:boolean" />

        
<xsl:choose>

            
<xsl:when test="deep-equal($XSF1-primaryData, $XSF2-primaryData) and $XSF1start-EQ-XSF2start and $XSF1end-EQ-XSF2end">

                
<xsl:copy-of select="$XSF1//xsf:primaryData" />

            
</xsl:when>

            
<xsl:otherwise>

                
<xsl:message select="'--------------------'" />

                
<xsl:message select="' *** ERROR: Elements xsf:primaryData contain different information.'" />

                
<xsl:message select="if( not($XSF1start-EQ-XSF2start) or not($XSF1end-EQ-XSF2end) ) then ' Different @start or @end!' else ' Please check textual content!'" />

                
<xsl:message terminate="yes" select="if( not($XSF1start-EQ-XSF2start) or not($XSF1end-EQ-XSF2end) ) then (if($XSF1//xsf:primaryData/@start!=$XSF2//xsf:primaryData/@start) then concat('XSF1-start: ', $XSF1//xsf:primaryData/@start, ' XSG2-start: ', $XSF2//xsf:primaryData/@start) else concat('XSF1-end: ', $XSF1//xsf:primaryData/@end, ' XSF2-end: ', $XSF2//xsf:primaryData/@end)) else concat(' ', string:first-distinct-char($XSF1-primaryData, $XSF2-primaryData, 1))" />

            
</xsl:otherwise>

        
</xsl:choose>

        
<xsl:message select="' - done.'" />

    
</xsl:function>

    

    

    
              <xd:doc><xd:short><p>Checking for layers from input annotations which have same IDs</p></xd:short></xd:doc>


    
<xsl:function name="undef:check-layer-IDs">

        
<xsl:variable name="same-ID" select="$XSF1//xsf:layer/@xml:id[.=$XSF2//xsf:layer/@xml:id]" as="xs:string*" />

        
<xsl:if test="$same-ID">

            
<xsl:message select="concat(' *** WARNING: layers in different files having same ID (', $same-ID, ')')" />

        
</xsl:if>

    
</xsl:function>

   

    

    
<!--not used in this version-->

    
<!--

    <xd:doc>

        <xd:short><p>Generating of a layer containing elements which are present in all layers provided by the input annotations.</p></xd:short>

        <xd:param name="layers">These are all the layers from the input XSF files.</xd:param>

        <xd:param name="all-layer">This is the all-layer</xd:param>

    </xd:doc>

    <xsl:function name="elem:generate-all-layer" as="element(xsf:layer)?">

        <xsl:param name="layers" as="element(xsf:layer)+"/>

        <xsl:param name="all-layer" as="element(xsf:layer)?"/>

        <xsl:choose>

            <xsl:when test="$all-layer">

                <xsl:copy-of select="$all-layer"/>

            </xsl:when>

            <xsl:when test="count($layers)=1">

                

            </xsl:when>

            <xsl:otherwise>

                <xsf:layer priority="0"

                    xsi:schemaLocation="{concat($all-layer-namespace, ' xsf.xsd')}">

                    <xsl:namespace name="all" select="$all-layer-namespace"/>

                    <xsl:copy-of select="elem:return-elements-in-all-layer($layers[1]/*, $layers[position() &gt; 1])"/>

                </xsf:layer>

            </xsl:otherwise>

        </xsl:choose>

    </xsl:function>
-->

    

    

    
              <xd:doc>

        
<xd:short><p>Returning of elements which are present in every layer into a common all-layer.</p></xd:short>

        
<xd:param name="base-layer-elems">Layer serving as the basis of the all-layer. Due to the fact that the all-layer is defined by 

            containing the elements which are present in every single layer, this can be any layer from the input.
</xd:param>

        
<xd:param name="ref-layers">Layers which are examined on containing elements which are present in all other layers.</xd:param>

    
</xd:doc>


    
<xsl:function name="elem:return-elements-in-all-layer" as="element()*">

        
<xsl:param name="base-layer-elems" as="element()*" />

        
<xsl:param name="ref-layers" as="element(xsf:layer)+" />

        
<xsl:for-each select="$base-layer-elems">

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

            
<xsl:variable name="segment" select="@xsf:segment" as="xs:string" />

            
<xsl:choose>

                
<xsl:when test="every $layer in $ref-layers satisfies exists($layer/descendant::*[local-name()=$local-name and @xsf:segment=$segment])">

                    
<xsl:element name="all:{$local-name}">

                        
<xsl:copy-of select="$ref-layers/descendant::*[local-name()=$local-name and @xsf:segment=$segment]/@*[name()!='xsf:segment']" />

                        
<xsl:copy-of select="elem:return-elements-in-all-layer(*, $ref-layers)" />

                    
</xsl:element>

                
</xsl:when>

            
</xsl:choose>

        
</xsl:for-each>

    
</xsl:function>

    

    

    
              <xd:doc>

        
<xd:short><p>Getting the string value of the ID of an element which can either be an attribute(*, xs:ID), in case of schema-aware transformation, or @*:id (basic processor), or the generation of an ID by generate-id()</p></xd:short>

        
<xd:param name="self">Element whose ID shall be returned.</xd:param>

    
</xd:doc>


    
<xsl:function name="string:get-id" as="xs:string">

        
<xsl:param name="self" as="element()" />

        
<xsl:value-of select="$self/((if($is-schema-aware) then attribute(*, xs:ID) else @*:id), generate-id(.))[1]" />

    
</xsl:function>

    

    

    
              <xd:doc><xd:short><p>Returning messages containing information on supplied stylesheet parameters.</p></xd:short></xd:doc>


    
<xsl:function name="undef:param-messages">

        
<xsl:message select="'--------------------'" />

        
<xsl:message select="' Provided stylesheet parameters:'" />

        
<xsl:message select="concat(' merge-with=', $merge-with)" />

        
<xsl:message select="concat(' keep-segments=', $keep-segments)" />

        
<xsl:message select="concat(' all-layer=', $all-layer)" />

        
<xsl:message select="'--------------------'" />

    
</xsl:function>

    

    

    
              <xd:doc>

        
<xd:short><p>Returns the contents of a layer. The @xsf:segment are updated.</p></xd:short>

        
<xd:param name="layer-content">Descendant elements of the current layer.</xd:param>

        
<xd:param name="ns-to-be-inlined">Namespace URI of the elements which shall be included in the resulting inline annotation.</xd:param>

        
<xd:param name="root-name-name-of-layer">Name of the root of the layer ('XSF1' or 'XSF2').</xd:param>

    
</xd:doc>


    
<xsl:function name="elem:process-layer" as="element()*">

        
<xsl:param name="layer-content" as="element()*" />

        
<xsl:param name="ns-to-be-inlined" as="xs:anyURI" />

        
<xsl:param name="root-name-of-layer" as="xs:string" />

        
<xsl:for-each select="$layer-content">

            
<xsl:choose>

                
<!--condition ADDED (16.09.2010)-->

                
<xsl:when test="tokenize(key(concat('seg-by-', $root-name-of-layer, 'ID'), @xsf:segment, $newSegments)/@*[local-name() = current()/local-name()], ' ') = $ns-to-be-inlined">

                    
<xsl:element name="{if($ns-to-be-inlined = $all-layer-namespace) then concat('all:', local-name()) else string(node-name(.))}" namespace="{$ns-to-be-inlined}">

                        
<xsl:if test="@xsf:segment">

                            
<xsl:attribute name="xsf:segment" select="key(concat('seg-by-', $root-name-of-layer, 'ID'), @xsf:segment, $newSegments)/@xml:id" />

                        
</xsl:if>

                        
<!--<xsl:message select="'current:', name(), ' seg: ', @xsf:segment"/>

                            <xsl:message select="key('elem-by-local-name-and-segRef', concat(local-name(), '#', @xsf:segment), $XSF1)/@*|

                            key('elem-by-local-name-and-segRef', concat(local-name(), '#', @xsf:segment), $XSF2)/@*"/>
-->

                        
<!--get attributes from the current element in $XSF1 and $XSF2-->

                        
<xsl:choose>

                            
<!--if layer to be processed is the all-layer, then every attribute has to be qualified with its corresponding's layer's namespace and a prefix--> 

                            
<xsl:when test="$ns-to-be-inlined = $all-layer-namespace">

                                
<xsl:for-each select="( key('elem-by-local-name-and-segRef', concat(local-name(), '#', @xsf:segment), $XSF1) | key('elem-by-local-name-and-segRef', concat(local-name(), '#', @xsf:segment), $XSF2) ) /@*[name()!='xsf:segment' ]">

                                    
<!--<xsl:message select="."/>-->

                                    
<!--PROBLEM: how to decide which ns-prefix from $namespaces if several prefixes for same namespace-uri?-->

                                    
<xsl:attribute name="{concat( $namespaces[@uri=current()/../namespace-uri()][@source = (if(root(.) = $XSF1) then 'XSF1' else 'XSF2')][1]/@prefix, ':', local-name() )}" select="." namespace="{../namespace-uri()}" />

                                
</xsl:for-each>

                            
</xsl:when>

                            
<!--if the processed layer is not the all-layer, then attributes can be returnd unchanged-->

                            
<xsl:otherwise>

                                
<!--avoiding output of concurrent IDs-->

                                
<xsl:choose>

                                    
<xsl:when test="$is-schema-aware">

                                        
<xsl:for-each select="attribute(*, xs:ID), attribute(*, xs:IDREF), attribute(*, xs:IDREFS)">

                                            
<xsl:copy-of select="attr:avoid-concurrent-IDs(., $root-name-of-layer)" />

                                        
</xsl:for-each>

                                        
<xsl:copy-of select="@* except (@xsf:segment, attribute(*, xs:ID), attribute(*, xs:IDREF), attribute(*, xs:IDREFS))" />

                                    
</xsl:when>

                                    
<xsl:otherwise>

                                        
<xsl:copy-of select="@* except @xsf:segment" />

                                    
</xsl:otherwise>

                                
</xsl:choose>

                            
</xsl:otherwise>

                        
</xsl:choose>

                        
<xsl:copy-of select="elem:process-layer(*, $ns-to-be-inlined, $root-name-of-layer)" />

                    
</xsl:element>

                
</xsl:when>

                
<xsl:otherwise>

                    
<xsl:copy-of select="elem:process-layer(*, $ns-to-be-inlined, $root-name-of-layer)" />

                
</xsl:otherwise>

            
</xsl:choose>

        
</xsl:for-each>

    
</xsl:function>

    

    

    
              <xd:doc>

        
<xd:short><p>Creating an inline annotation on the basis of a segment list</p></xd:short>

        
<xd:param name="segments">Segments whose referenced elements shall be included in the resulting annotation.</xd:param>

        
<xd:param name="ns-to-be-inlined">Namespace URI of the elements which shall be included in the resulting inline annotation.</xd:param>

        
<xd:param name="root-name">Name of the root of the current annotation (XSF1 or XSF2).</xd:param>

        
<xd:param name="layer-prefix">Prefix of the namespace whose elements are to be inlined.</xd:param>

    
</xd:doc>


    
<xsl:function name="elem:segments2inline" as="element()*">

        
<xsl:param name="segments" as="element(xsf:segment)*" />

        
<xsl:param name="ns-to-be-inlined" as="xs:anyURI" />

        
<xsl:param name="root-name-of-layer" as="xs:string" />

        
<xsl:param name="layer-prefix" as="xs:string" />

        
<!--Finding segments in $segments which have the outermost start and end positions-->

        
<xsl:variable name="this-level-segments" select="$segments[ for $this-seg in . return empty($segments[@xml:id != $this-seg/@xml:id][number(@start) &lt;= number($this-seg/@start) and number(@end) &gt;= number($this-seg/@end)])]" as="element()*" />

        
<xsl:for-each select="$this-level-segments">

            
<!--<xsl:message select="'this segment: ', ."/>

            <xsl:message select="$root-name, @*[local-name()=concat($root-name, 'ID')]"/>
-->

            
<!--Getting elements from the input annotation having the current segment reference-->

            
<xsl:variable name="elems-this-segment" select="key('elem-by-segRef', @*[local-name()=concat($root-name-of-layer, 'ID')], (if($root-name-of-layer = 'XSF1') then $XSF1 else $XSF2)) [namespace-uri() = ($ns-to-be-inlined, $all-layer-namespace)]" as="element()*" />

            
<!--<xsl:message select="'seg: ', @xml:id, '$elems-this-segment: ', $elems-this-segment/name()"/>-->

            
<xsl:variable name="this-segment" select="." as="element()" />

            
<xsl:variable name="nested-elems" select="elem:segments2inline( $segments[@xml:id = $this-segment/@xml:id]/following-sibling::*[ ( number(@start) &gt;= number($this-segment/@start) and number(@end) &lt;= number($this-segment/@end) ) ], $ns-to-be-inlined, $root-name-of-layer, $layer-prefix )" />

            
<xsl:choose>

                
<!--if there is no element in the annotation for this segment, then only the descendant elements are processed-->

                
<xsl:when test="empty($elems-this-segment)">

                    
<xsl:copy-of select="$nested-elems" />

                
</xsl:when>

                
<!--if there is exactly one corresponding element for this segment-->

                
<xsl:when test="count($elems-this-segment) = 1">

                    
<xsl:choose>

                        
<!--testing if element is in new all-layer-->

                        
<xsl:when test="key( 'elem-by-local-name-and-segRef', $elems-this-segment / concat( local-name(), '#', key(concat('seg-by-', $root-name-of-layer, 'ID'), @xsf:segment, $newSegments)/@xml:id ), $all-layer-doc )">

                            
<!--if element is in new all-layer, descendant elements are processed further-->

                            
<xsl:copy-of select="$nested-elems" />

                        
</xsl:when>

                        
<!--if element is not in new all-layer-->

                        
<xsl:otherwise>

                            
<xsl:for-each select="$elems-this-segment[if($all-layer) then empty(key('elem-by-local-name-and-segRef', concat(local-name(), '#', @xml:id), $all-layer-doc)) else true()]">

                                
<xsl:element name="{$layer-prefix}:{local-name()}" namespace="{$ns-to-be-inlined}">

                                    
<!--avoiding output of concurrent IDs-->

                                    
<xsl:choose>

                                        
<xsl:when test="$is-schema-aware">

                                            
<xsl:for-each select="attribute(*, xs:ID), attribute(*, xs:IDREF), attribute(*, xs:IDREFS)">

                                                
<xsl:copy-of select="attr:avoid-concurrent-IDs(., $root-name-of-layer)" />

                                            
</xsl:for-each>

                                            
<!--processing other attributes-->

                                            
<xsl:copy-of select="@* except (@xsf:segment, attribute(*, xs:ID), attribute(*, xs:IDREF), attribute(*, xs:IDREFS))" />

                                        
</xsl:when>

                                        
<xsl:otherwise>

                                            
<!--processing other attributes-->

                                            
<xsl:for-each select="(@* except @xsf:segment)[namespace-uri() = ('http://www.xstandoff.net/2009/xstandoff/1.1', $ns-to-be-inlined)]">

                                                
<xsl:attribute name="{$layer-prefix}:{local-name()}" select="." namespace="{$ns-to-be-inlined}" />

                                            
</xsl:for-each>

                                        
</xsl:otherwise>

                                    
</xsl:choose>

                                    
<xsl:copy-of select="$nested-elems" />

                                
</xsl:element>

                            
</xsl:for-each>

                        
</xsl:otherwise>

                    
</xsl:choose>

                
</xsl:when>

                
<xsl:otherwise>

                    
<!--heuristics for inclusion measures has to be rebuilt-->

                    
<!--<xsl:copy-of select="undef:multiple-inline-annotations(elem:sort-elems-by-nesting($elems-this-segment, $nest-by), $nested-elems)"/>-->

                    
<!--until then the elements are not sorted-->

                    
<xsl:copy-of select="undef:multiple-inline-annotations($elems-this-segment, $nested-elems, $ns-to-be-inlined, $layer-prefix, $root-name-of-layer)" />

                
</xsl:otherwise>

            
</xsl:choose>

        
</xsl:for-each>

    
</xsl:function>

    

    

    
              <xd:doc>

        
<xd:short><p>Nesting elements with same segment reference by heuristics given by <i>func:sort-elems()</i></p></xd:short>

        
<xd:param name="elems-this-segment">Elements referencing the same segment.</xd:param>

        
<xd:param name="nested-elems">Elements which are descendants of the $elems-this-segment. They are simply copied into the $elems-this-segment when the embedding relations are resolved.</xd:param>

        
<xd:param name="ns-to-be-inlined">Namespace URI the elements of which shall be included in the resulting inline annotation.</xd:param>

        
<xd:param name="layer-prefix">Prefix of the namespace whose elements are to be inlined.</xd:param>

        
<xd:param name="root-name">Name of the root of the current annotation (XSF1 or XSF2).</xd:param>

    
</xd:doc>


    
<xsl:function name="undef:multiple-inline-annotations">

        
<xsl:param name="elems-this-segment" as="element()*" />

        
<xsl:param name="nested-elems" />

        
<xsl:param name="ns-to-be-inlined" as="xs:anyURI" />

        
<xsl:param name="layer-prefix" as="xs:string" />

        
<xsl:param name="root-name-of-layer" as="xs:string" />

        
<xsl:variable name="new-elements-this-segment" select="subsequence($elems-this-segment, 2)" as="element()*" />

        
<xsl:for-each select="$elems-this-segment[1]">

            
<xsl:choose>

                
<!--if the element is stored in the all-layer already, the following elements are tested-->

                
<xsl:when test="key( 'elem-by-local-name-and-segRef', $elems-this-segment / concat( local-name(), '#', key(concat('seg-by-', $root-name-of-layer, 'ID'), @xsf:segment, $newSegments)/@xml:id ), $all-layer-doc )">

                    
<xsl:copy-of select="( if(empty($new-elements-this-segment)) then $nested-elems else undef:multiple-inline-annotations($new-elements-this-segment, $nested-elems, $ns-to-be-inlined, $layer-prefix, $root-name-of-layer) )" />

                
</xsl:when>

                
<!--if there is no corresponding element in the all-layer, this one is copied and the following elements are tested-->

                
<xsl:otherwise>

                    
<xsl:element name="{$layer-prefix}:{local-name()}" namespace="{$ns-to-be-inlined}">

                        
<xsl:for-each select="@*[namespace-uri() = ('http://www.xstandoff.net/2009/xstandoff/1.1', $ns-to-be-inlined)]">

                            
<xsl:attribute name="{$layer-prefix}:{local-name()}" select="." namespace="{$ns-to-be-inlined}" />

                        
</xsl:for-each>

                        
<xsl:copy-of select="( if(empty($new-elements-this-segment)) then $nested-elems else undef:multiple-inline-annotations($new-elements-this-segment, $nested-elems, $ns-to-be-inlined, $layer-prefix, $root-name-of-layer) )" />

                    
</xsl:element>

                
</xsl:otherwise>

            
</xsl:choose>

        
</xsl:for-each>

    
</xsl:function>

    

    

    
              <xd:doc>

        
<xd:short><p>

            Sorting elements which refer to the same segment

            either by priority of their xsf:level ($sort-type='priority') or 

            by measurement of their inclusion relations ($sort-type='measure').

        
</p></xd:short>

        
<xd:param name="elems-same-seg">Elements referring the same segment.</xd:param>

        
<xd:param name="sort-type">

            There are two possible sort types: 'priority' and 'measure'. The value 'priority' evokes a sorting by using the @priority of the corresponding &lt;xsf:level&gt;. 

            The value 'measure' calls a statistical analysis of the overall embedding relations of the specific elements in $elems-same-seg.

        
</xd:param>

    
</xd:doc>


    
<xsl:function name="elem:sort-elems-by-nesting" as="element()*">

        
<xsl:param name="elems-same-seg" as="element()*" />

        
<xsl:param name="sort-type" as="xs:string" />

        
<xsl:for-each select="$elems-same-seg">

            
<xsl:sort select="if($sort-type='priority') then (ancestor::xsf:level/@priority) else if($sort-type='measure') then double:multiply-int-sequence(for $child in ($elems-same-seg except .) return xs:double(key('measure', concat(name(), $child/name()), doc:inclusion-measures())/@value), 1) else error((), 'missing $sort-type at elem:sort-elems()')" data-type="number" order="descending" />

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

        
</xsl:for-each>

    
</xsl:function>

    

    

    
              <xd:doc><xd:short><p>Calculation of inclusion relations of elements</p></xd:short></xd:doc>


    
<xsl:function name="doc:inclusion-measures" as="document-node()">

        
<xsl:document>

            
<xsl:for-each select="distinct-values(($XSF1|$XSF2)//xsf:layer/descendant::*/name())">

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

                
<xsl:for-each select="distinct-values(($XSF1|$XSF2)//xsf:layer/descendant::*/name())">

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

                    
<measure parent="{$parent-name}" child="{$child-name}">

                        
<xsl:attribute name="value" select="if($child-name = $parent-name) then 1 else (::::::::::count elements with a child named $child-name and get a relative distribution measure:::::::) count( (:##parent-elements##:) (key('elem-by-name', $parent-name, $XSF1), key('elem-by-name', $parent-name, $XSF2)) [ for $parent-seg in key(concat('seg-by-', (if(root(.) = $XSF1) then 'XSF1' else 'XSF2'), 'ID'), @xsf:segment, root(.)) return exists( key(concat('seg-by-', (if(root(.) = $XSF1) then 'XSF1' else 'XSF2'), 'ID'), key('elem-by-name', $child-name, root(.))/@xsf:segment, $newSegments) [(number(@start) &gt;= number($parent-seg/@start)) and (number(@end) &lt;= number($parent-seg/@end))] ) ] ) div count((key('elem-by-name', $parent-name, $XSF1), key('elem-by-name', $parent-name, $XSF2)))" />

                    
</measure>

                
</xsl:for-each>

            
</xsl:for-each>

        
</xsl:document>

    
</xsl:function>

    

    

    
              <xd:doc>

        
<xd:short><p>Multiplication of all numbers from a sequence.</p></xd:short>

        
<xd:param name="sequence">Sequence of numbers which are multiplicated recursively.</xd:param>

        
<xd:param name="temp-result">Storation of the temporary result while numbers exist that were not already used for multiplication.</xd:param>

    
</xd:doc>


    
<xsl:function name="double:multiply-int-sequence" as="xs:double">

        
<xsl:param name="sequence" as="xs:double*" />

        
<xsl:param name="temp-result" as="xs:double" />

        
<xsl:copy-of select="if(count($sequence) = 1) then ($sequence[1] * $temp-result) else double:multiply-int-sequence(subsequence($sequence, 2), $sequence[1] * $temp-result)" />

    
</xsl:function>

    

    

    
              <xd:doc>

        
<xd:short><p>Test for concurrent ID/IDREF/IDREFS information in attributes and escaping by predefined prefix.</p></xd:short>

        
<xd:param name="attribute">The attribute to be tested.</xd:param>

        
<xd:param name="root-name-of-layer">Name of the root of the layer containing this attribute ('XSF1' vs. 'XSF2').</xd:param>

    
</xd:doc>


    
<xsl:function name="attr:avoid-concurrent-IDs" as="attribute()">

        
<xsl:param name="attribute" as="attribute()" />

        
<xsl:param name="root-name-of-layer" as="xs:string" />

        
<xsl:choose>

            
<xsl:when test="if(($attribute instance of attribute(*, xs:ID)) or ($attribute instance of attribute(*, xs:IDREF))) then exists(key('concurrent-IDs', $attribute, $concurrent-IDs)) and ($root-name-of-layer = 'XSF2') else exists(for $ID in $attribute return key('concurrent-IDs', $ID, $concurrent-IDs)) and ($root-name-of-layer = 'XSF2')">

                
<xsl:attribute name="{concat((concat(prefix-from-QName(node-name($attribute)), ':')[prefix-from-QName(node-name($attribute))], '')[1], $attribute/local-name())}" select="if(($attribute instance of attribute(*, xs:ID)) or ($attribute instance of attribute(*, xs:IDREF))) then key('concurrent-IDs', $attribute, $concurrent-IDs)/@new-id else string-join((for $ID in tokenize(string($attribute), ' ') return (key('concurrent-IDs', $ID, $concurrent-IDs)/@new-id, $ID)[1]), ' ')" />

            
</xsl:when>

            
<xsl:otherwise>

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

            
</xsl:otherwise>

        
</xsl:choose>

    
</xsl:function>

    

    

</xsl:stylesheet>













































































v