view software/eXist/webapp/mpdl/_stuff/oxygen-projects/monte-project/archimedes-xml-fragment.xsl @ 7:5589d865af7a

Erstellung XQL/XSL Applikation
author Josef Willenborg <jwillenborg@mpiwg-berlin.mpg.de>
date Tue, 08 Feb 2011 15:16:46 +0100
parents
children
line wrap: on
line source

<xsl:stylesheet version="2.0" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
 xmlns:xlink="http://www.w3.org/1999/xlink"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:functx="http://www.functx.com"
 xmlns:text="http://www.mpiwg-berlin.mpg.de/ns/mpdl/text">

<xsl:output method="html"/>

<!-- siehe unter http://www.xsltfunctions.com     -->
<xsl:function name="functx:contains-any-of" as="xs:boolean">
  <xsl:param name="arg" as="xs:string?"/> 
  <xsl:param name="searchStrings" as="xs:string*"/> 
  <xsl:sequence select="some $searchString in $searchStrings satisfies contains($arg,$searchString)"/>
</xsl:function>

<!-- Highlight all term occurrences for the fulltext query. It recognizes the first occorrence and then does 
this function recursive with the first substring before the first term cut off.
Result is a sequence of text and highlight nodes:
Example:
LE<lb></lb>
<span ...>MECHANICHE</span>
...<lb></lb>
...<lb></lb>
<span ...>MECHANICHE</span>
...<lb></lb>
...<lb></lb>
...
 -->
<xsl:function name="text:highlight">
  <xsl:param name="inputString" />
  <xsl:param name="luceneQuery" as="xs:string" />
  <xsl:param name="mode" as="xs:string" />
  <!-- Translation from Lucene fulltext query to text query  -->  
  <xsl:variable name="textQuery">
    <xsl:choose>
      <xsl:when test="$mode = 'phrase'">
        <xsl:value-of select="substring-before(substring-after($luceneQuery, '&quot;'), '&quot;')"/>
      </xsl:when>
      <xsl:when test="$mode = 'fakeWord'">
        <xsl:value-of select="$luceneQuery"/>
      </xsl:when>
      <xsl:when test="$mode = 'word'">
        <xsl:value-of select="$luceneQuery"/>
      </xsl:when>
      <xsl:otherwise><xsl:value-of select="''"/></xsl:otherwise>
    </xsl:choose>
  </xsl:variable>
  <!-- Word delimiter: not tested yet -->
  <xsl:variable name="wordDelimRegExpr" select="'[\s\(\)\[\]\.\\\{\}\$\^\+\?\!\* ยง%:,;=/]+'"/>   <!-- TODO: bol, eol, ", &, <, >    --> 
  <!-- Recognizes the beginning of the line with ^ and the substring up to the query term -->
  <xsl:variable name="queryRegExprSubstringBefore">
    <xsl:choose>
      <xsl:when test="$mode = 'phrase'">
        <xsl:value-of select="concat('^.*?', $textQuery)"/>
      </xsl:when>
      <xsl:when test="$mode = 'fakeWord'">
        <xsl:value-of select="concat('^.*?', $textQuery)"/>
      </xsl:when>
      <xsl:when test="$mode = 'word'">
        <xsl:value-of select="concat('^.*?', $wordDelimRegExpr, $textQuery, '(',  $wordDelimRegExpr, ')')"/>
      </xsl:when>
      <xsl:otherwise><xsl:value-of select="''"/></xsl:otherwise>
    </xsl:choose>
  </xsl:variable>
  <!-- Recognizes the substring after the query term -->
  <xsl:variable name="queryRegExprSubstringAfter">
    <xsl:choose>
      <xsl:when test="$mode = 'phrase'">
        <xsl:value-of select="concat($textQuery, '.*')"/>
      </xsl:when>
      <xsl:when test="$mode = 'fakeWord'">
        <xsl:value-of select="concat($textQuery, '.*')"/>
      </xsl:when>
      <xsl:when test="$mode = 'word'">
        <xsl:value-of select="concat('(', $wordDelimRegExpr, ')', $textQuery, $wordDelimRegExpr, '.*')"/>
      </xsl:when>
      <xsl:otherwise><xsl:value-of select="''"/></xsl:otherwise>
    </xsl:choose>
  </xsl:variable>
  <!-- Deletes the substring up to the query term -->
  <xsl:variable name="substringBefore" select="replace($inputString, $queryRegExprSubstringAfter, '$1', 'i')"/>
  <!-- Deletes the substring after the query term -->
  <xsl:variable name="substringAfter" select="replace($inputString, $queryRegExprSubstringBefore, '$1', 'i')"/>
  <xsl:choose>
    <xsl:when test="matches($inputString, $queryRegExprSubstringBefore, 'i')">
      <!-- Prints the original part of the substring up to the first occurrence of the query term -->
      <xsl:value-of select="$substringBefore"/>
      <!-- Highlight the query term -->
      <xsl:variable name="matchQueryTermRegExpr">
        <xsl:choose>
          <xsl:when test="$mode = 'phrase'">
            <xsl:value-of select="concat('^.*?', '(', $textQuery, ')', '.*')"/>
          </xsl:when>
          <xsl:when test="$mode = 'fakeWord'">
            <xsl:value-of select="concat('^.*?', '(', $textQuery, ')', '.*')"/>
          </xsl:when>
          <xsl:when test="$mode = 'word'">
            <xsl:value-of select="concat('^.*?', $wordDelimRegExpr, '(', $textQuery, ')', $wordDelimRegExpr, '.*')"/>
          </xsl:when>
          <xsl:otherwise><xsl:value-of select="''"/></xsl:otherwise>
        </xsl:choose>
      </xsl:variable>
      <xsl:variable name="matchQueryTerm" select="replace($inputString, $matchQueryTermRegExpr, '$1', 'i')"/>
      <span style="background-color: yellow;">
        <xsl:value-of select="$matchQueryTerm"/>
      </span>
      <!-- Recursive call of this function with the substring after the first occurrence of the term: further occurrences of the query 
      term  -->
      <xsl:sequence select="text:highlight($substringAfter, $luceneQuery, $mode)"/>
    </xsl:when>
    <!-- if no occurrence of the query term could be found the whole string is printed -->
    <xsl:otherwise>
      <xsl:value-of select="$inputString"/>
      </xsl:otherwise>
  </xsl:choose>
</xsl:function>

<!--
<xsl:function name="text:limitHighligthedString">
  <xsl:param name="inputString" />
  <xsl:param name="countChar" as="xs:integer"/>
  <xsl:variable name="substringBeforeHighlight" select="substring-before($inputString, '&lt;span')"/>
  <xsl:variable name="substringAfterHighlight" select="substring-after($inputString, '&lt;span&gt;>')"/>
  <xsl:variable name="result">
  ... <xsl:value-of select="substring($substringBeforeHighlight, string-length($substringBeforeHighlight) - $countChar)"/><span style="background-color: yellow;"><xsl:value-of select="' BlaBla '"/></span><xsl:value-of select="substring($substringAfterHighlight, 0, $countChar)"/> ...
  </xsl:variable>
  <xsl:sequence select="$result"/>
</xsl:function>
-->

<xsl:function name="text:limitHighligthedString">
  <xsl:param name="inputSequence" as="node()*"/>
  <xsl:param name="countChar" as="xs:integer"/>
  <xsl:variable name="before" select="$inputSequence[1]"/>
  <xsl:variable name="beforeLimited" select="substring($before, string-length($before) - $countChar)"/>  
  <xsl:variable name="firstSpan" select="$inputSequence[2]"/>
  <xsl:variable name="after" select="$inputSequence[position() > 2]"/>
  <xsl:variable name="afterLimited" select="substring($after, 0, $countChar)"/>  
  <xsl:variable name="result">
  ... <xsl:sequence select="$before"/><xsl:sequence select="$firstSpan"/><xsl:sequence select="$after"/> ...
  </xsl:variable>
  <xsl:sequence select="$result"/>
</xsl:function>

<xsl:variable name="ftQueryName" select="/result/ft-query/name"/>
<xsl:variable name="ftQueryStr" select="concat('&amp;', 'ft-query=', $ftQueryName)"/>
<xsl:variable name="ftQueryMode">
  <xsl:choose>
  <xsl:when test="matches($ftQueryName, concat('&quot;', '.*', '&quot;'))">
    <xsl:value-of select="'phrase'"/>
  </xsl:when>
  <xsl:when test="string-length($ftQueryName) = 0">
    <xsl:value-of select="'false'"/>
  </xsl:when>
  <!-- Because there are  problems in recognizing words (in mode word) this fake mode is used (same as phrase mode)  -->
  <xsl:otherwise><xsl:value-of select="'fakeWord'"/></xsl:otherwise>
  </xsl:choose>
</xsl:variable>
<xsl:variable name="ftQueryValue">
  <xsl:choose>
  <xsl:when test="/result/ft-query[node()]"><xsl:value-of select="$ftQueryStr"/></xsl:when>
  <xsl:otherwise><xsl:value-of select="''"/></xsl:otherwise>
  </xsl:choose>
</xsl:variable>

<xsl:template match="result">
  <html><body>
    <xsl:variable name="ft-query-name" select="/result/ft-query/name"/>
    <xsl:for-each select="document-description">
      <h2>
      <xsl:for-each select="info">
        <xsl:value-of select="author"/>.
        <xsl:value-of select="title"/>.
        <xsl:value-of select="place"/>, 
        <xsl:value-of select="date"/>
      </xsl:for-each>
      </h2>
    </xsl:for-each>
    <form action="" method="get"></form>
    <xsl:for-each select="page">
      <xsl:variable name="documentName" select="/result/document-description/document-name"/>
      <xsl:variable name="countPages" select="/result/document-description/count-pages"/>
      <xsl:variable name="number" select="number(number)"/>
      <xsl:variable name="documentValue" select="concat('document=', $documentName)"/>
      <xsl:variable name="pnValue" select="concat('pn=', $number)"/>
      <xsl:variable name="modeImageValue" select="concat('mode=', 'image')"/>
      <xsl:variable name="modeXmlValue" select="concat('mode=', 'xml')"/>
      <xsl:variable name="modeTextValue" select="concat('mode=', 'text')"/>
      <xsl:variable name="imageLink" select="concat($documentValue, '&amp;', $pnValue, '&amp;', $modeImageValue, $ftQueryValue)"/>
      <xsl:variable name="textLink" select="concat($documentValue, '&amp;', $pnValue, '&amp;', $modeTextValue, $ftQueryValue)"/>
      <xsl:variable name="xmlLink" select="concat($documentValue, '&amp;', $pnValue, '&amp;', $modeXmlValue, $ftQueryValue)"/>
      <table width="100%">
        <colgroup>
          <col width="30%"/>
          <col width="70%"/>
        </colgroup>
        <tr>
        <td align="left" nowrap="true">
          [<a href="?{$textLink}">Text</a>] 
          [<a href="?{$imageLink}">Image</a>]
          [XML] 
        </td>
        <td align="right" nowrap="true">
          <td>
            <xsl:choose>
              <xsl:when test="$number &gt; 1">
                <a href="?{$documentValue}&amp;pn={$number - 1}&amp;{$modeXmlValue}{$ftQueryValue}"><img src="images/left.gif" alt="page-down" border="0"/></a>
              </xsl:when>
              <xsl:otherwise>
                <a href="?{$xmlLink}"><img src="images/left.gif" alt="page-down" border="0"/></a>
              </xsl:otherwise>
            </xsl:choose>
          </td>
          <td nowrap="true">
            <xsl:value-of select="$number"/> / <xsl:value-of select="$countPages"/> 
          </td>
          <td>
            <xsl:choose>
              <xsl:when test="$number &lt; $countPages">
                <a href="?{$documentValue}&amp;pn={$number + 1}&amp;{$modeXmlValue}{$ftQueryValue}"><img src="images/right.gif" alt="page-up" border="0"/></a>
              </xsl:when>
              <xsl:otherwise>
                <a href="?{$xmlLink}"><img src="images/right.gif" alt="page-down" border="0"/></a>
              </xsl:otherwise>
            </xsl:choose>
          </td>
          <td nowrap="true">
            <input type="hidden" name="document" value="{$documentName}"/>
            Page: <input type="text" size="3" name="pn" value="{$number}"/> 
            <input type="hidden" name="mode" value="xml"/>
            <xsl:if test="/result/ft-query[node()]">
              <input type="hidden" name="ft-query" value="{$ftQueryName}"/>
            </xsl:if>
          </td>
        </td>
        </tr>
      </table>
      <hr/>   
      <table align="middle" width="100%">
        <colgroup>
          <col width="70%"/>
          <col width="30%"/>
        </colgroup>
        <tr>
          <td align="left" valign="top">
            <xsl:for-each select="content">
              <xsl:apply-templates/>
            </xsl:for-each>
          </td>
          <xsl:if test="$ftQueryValue!=''">
          <td align="left" valign="top">
            <b><xsl:value-of select="/result/ft-query/result/size"/> Hits: "<xsl:value-of select="$ftQueryName"/>"</b>
            <ol>
              <xsl:for-each select="/result/ft-query/result/hits/hit">
              <li>
                <xsl:variable name="hitPN" select="pn"/>
                <xsl:variable name="hitPosOfS" select="pos-of-s"/>
                <a href="?{$documentValue}&amp;pn={$hitPN}&amp;{$modeXmlValue}{$ftQueryValue}">Page <xsl:value-of select="$hitPN"/>, Sentence <xsl:value-of select="$hitPosOfS"/></a>:<br></br>
                <!-- Highlight the query terms in each hit  -->
                <xsl:variable name="highlightedSentenceSeq" select="text:highlight(s, $ftQueryName, $ftQueryMode)"/>
                <xsl:sequence select="text:limitHighligthedString($highlightedSentenceSeq, 100)"/>
              </li>
              </xsl:for-each>
            </ol>
          </td>
          </xsl:if>
        </tr>
      </table>
      <hr/>
      Elapsed time:  <xsl:value-of select="/result/document-description/performance"/> ms, Back to <a href="query.xql">query page</a>, see the <a href="page-query-result.xql?_source=yes">XQuery source</a> and <a href="/exist/rest/db/xsl/archimedes-xml-fragment.xsl?_source=yes">XSL source</a> of this page
      <br/>
      [<a href="page-query-result.xql?{$xmlLink}">fast mechanism (file system search)</a>] [<a href="page-query-result-old.xql?{$xmlLink}">slower mechanism (XQL search)</a>]
    </xsl:for-each>
  </body></html>
</xsl:template>


<xsl:template match="attribute()|element()|text()|comment()|processing-instruction()">
  <xsl:copy>
    <xsl:apply-templates select="attribute()|element()|text()|comment()|processing-instruction()"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="element()|text()|comment()|processing-instruction()">
  <xsl:variable name="elementName" select="name()"/>
  <span style="color: brown;">&lt;<xsl:value-of select="$elementName"/><xsl:apply-templates select="attribute()"/>&gt;</span>
    <xsl:apply-templates select="element()|text()|comment()|processing-instruction()"/>
  <span style="color: brown;">&lt;/<xsl:value-of select="$elementName"/>&gt;</span>
  <br/>
</xsl:template>

<xsl:template match="attribute()">
  <xsl:variable name="attributeName" select="name()"/>
  <xsl:text> </xsl:text><xsl:value-of select="$attributeName"/>=<xsl:value-of select="."/>
    <xsl:apply-templates select="attribute()"/>
</xsl:template>

<!-- If ft-query is set then highlight all term occurrences for the fulltext query else show the text -->
<xsl:template match="text()">
  <xsl:choose>
  <xsl:when test="$ftQueryMode != 'false'">
    <xsl:sequence select="text:highlight(., $ftQueryName, $ftQueryMode)"/>
  </xsl:when>
  <xsl:otherwise>
    <xsl:value-of select="."/>
  </xsl:otherwise>
  </xsl:choose>
</xsl:template>

</xsl:stylesheet>