Commit 686440eb authored by Jerome Chauveau's avatar Jerome Chauveau
Browse files

Merge branch 'pyb/index' into 'dev'

Modification du module d'indexation, ead_backet et ead_search

See merge request pdn-certic/MaX!64
parents a2b58f39 287f2261
Loading
Loading
Loading
Loading
+122 −122
Original line number Diff line number Diff line
@@ -80,7 +80,7 @@ declare
%output:method("html")
%rest:path("/{$projectId}/porte-documents.html")
function max.plugin.ead_basket:basket($projectId){
    max.html:render($projectId, "porte document", <section class="porte-documents">
    max.html:render($projectId, "porte-documents", <section class="porte-documents">
        <h2>Porte-documents</h2>
        <p>
            Votre porte-documents regroupe tous les documents que vous avez mis de côté pendant votre visite.
+12 −5
Original line number Diff line number Diff line
@@ -95,7 +95,7 @@ function max.plugin.ead_search:searchPage($project){
            <div id="ead-search-results"></div>
        </section>

    return max.html:render($project, 'search', $datalists)
    return max.html:render($project, 'rechercher', $datalists)
};


@@ -139,7 +139,7 @@ function max.plugin.ead_search:runSearch($project as xs:string, $indexes as xs:s

    return <section>
            <h3>Résultats - {count($html/li/@id)}</h3>
            <h4>XQuery = {$fullQuery} - (db = {$dbPath})</h4>
            <!--<h4>XQuery = {$fullQuery} - (db = {$dbPath})</h4>-->
            {$html}
           </section>
    }
@@ -149,9 +149,16 @@ function max.plugin.ead_search:runSearch($project as xs:string, $indexes as xs:s
};
declare %private function max.plugin.ead_search:formatSearchResult($c as node(), $n as xs:integer){
    <li class="ead-search-result" id="{$n}">{
        let $titles := for $i in $c/ancestor-or-self::*:c
        (: let $titles := for $i in $c/ancestor-or-self::*:c
            return (string-join($i/*:did/*:unitid/text(),''))
        return string-join($titles, " &#x25B8; ")
        return string-join($titles, " &#x25B8; ") :)

        for $i in $c
        let $id := $i/self::*:c/@*:id
        let $baseuriXml := base-uri($c)
        let $baseuri := base-uri($id)
        return <a href='{$baseuri}/{$id}.html'>{(string-join($i/ancestor-or-self::*:c/*:did/*:unitid/text(),' &#x25B8; '))}</a> 
        
    }</li>
(:    for $c in :)
(:    <li>{$c/*:did/*:unitid/text()} | <em>{string($c/*:did/*:unitdate[1]/@normal)}</em></li>:)
+52 −57
Original line number Diff line number Diff line
@@ -3,76 +3,71 @@
module namespace max.plugin.index = 'pddn/max/plugin/index';
import module namespace max.config = 'pddn/max/config' at '../../rxq/config.xqm';
import module namespace max.html = 'pddn/max/html' at '../../rxq/html.xqm';
import module namespace max.util = 'pddn/max/util' at '../../rxq/util.xqm';
import module namespace max.i18n = 'pddn/max/i18n' at '../../rxq/i18n.xqm';

declare variable $max.plugin.index:PLUGIN_ID := "index";

(:
returns index fragment if exists (already generated)
returns a news generated one if not
returns a new generated one if not
:)
declare
%rest:GET
%output:method("html")
%rest:path("/editions/{$project}/index")
function max.plugin.index:index($project){
  let $indexFilePath :=file:parent(file:parent(file:parent(static-base-uri()))) || '/editions/'||$project||'/fragments/index.frag.html'
%output:html-version("5.0")
%output:indent("no")
%output:encoding("UTF-8")
%rest:path("/{$project}/index/{$type}.html")
function max.plugin.index:index($project,$type){
  let $projectLang := max.i18n:getLang($project)
  let $indexFilePath :=file:parent(file:parent(file:parent(static-base-uri()))) || '/editions/'||$project||'/fragments/'||$projectLang||'/index_'||$type||'.frag.html'
  return
    if(file:exists($indexFilePath))
    then 
          let $content := <div id='content'>{doc($indexFilePath)}</div>
      let $content := fetch:xml($indexFilePath, map {'chop' : false()})
      let $content := <div id='content'>{$content}</div> 
          (:~ let $content := <div id='content'>{doc($indexFilePath)}</div>~:)
          return max.html:render($project, 'index', $content) 
    else max.plugin.index:generateIndex($project)
    else max.plugin.index:generateIndex($project,$type,$projectLang)
};

declare function max.plugin.index:generateIndex($project){
  try{
    let $indexFilePath :=file:parent(file:parent(file:parent(static-base-uri()))) || '/editions/'||$project||'/fragments/index.frag.html'
    let $dbPath := max.config:getProjectDBPath($project)
    let $backToTextPath := max.config:getPluginParameterValue($project, 'index', 'backToText')
    let $persons := <listPerson>
    {
      for $i at $p in collection($dbPath)//*:name[@*:type='personne' and @*:ref]
        group by $ref:=$i/@*:ref
        return if(starts-with($ref,'http'))
        then ()
        else
        let $id := substring-after($ref,'#')
        return if(not($id))
                         then error(xs:QName('max.error'),'ID IS -' || $ref)
                else
                let $url := max.config:getPluginParameterValue($project, 'index', 'url') || $id ||'.xml'
                let $request :=
                <http:request href='{$url}' 
                  method='post' username="{max.config:getPluginParameterValue($project, 'index', 'login')}"
                  password="{max.config:getPluginParameterValue($project, 'index', 'password')}" send-authorization='true'>
                  <http:body media-type='application/xml'>
                    <query xmlns="http://basex.org/rest">
                      <text><![CDATA[
                          <person xml:id='{//*:TEI/@xml:id/string()}'>{//*:TEI//*:person}
                          </person>
                          ]]></text>
                    </query>
                  </http:body>
                </http:request>
               let $person := http:send-request($request)
               let $occurs:=
                       <div type='occurs'>{
                         for $n at $j in collection($dbPath)//*:name[@*:type='personne' and @*:ref=$ref]
                           let $target:=substring-after(base-uri($n),$dbPath)||'/'||xquery:eval($backToTextPath, map { '': $n})
                           return <a target="./{$target}">{$j}</a>
                         }
                       </div>
               return
                 <item>{$person}{$occurs}</item>
declare function max.plugin.index:generateIndex($project,$type,$lang){  
let $indexFilePath :=file:parent(file:parent(file:parent(static-base-uri()))) || '/editions/'||$project||'/fragments/'||$lang||'/index_'||$type||'.frag.html'

let $custXQ := file:parent(file:parent(file:parent(static-base-uri())))||"editions/"||$project||"/xq/index_"||$type||".xq"
let $custXSL := file:parent(file:parent(file:parent(static-base-uri())))||"editions/"||$project||"/ui/xsl/index_"||$type||".xsl"

let $HTMLIndex := if (file:exists($custXQ) and file:exists($custXSL))
                  then max.plugin.index:loadIndex($project,$type,$custXQ,$custXSL,$lang)
                  else "error"

let $res := switch ($HTMLIndex)
        case "error"
           return "XQ and/or XSL file not found"
        default
           return file:write($indexFilePath, <div class='index'>{$HTMLIndex}</div>)(: , max.plugin.index:index($project,$type) :)
           
     }</listPerson>
     let $HTMLIndex := xslt:transform($persons, 'indexing.xsl', ())
     (:return file:write($indexFilePath, <div class='index'>{$HTMLIndex}</div>), max.plugin.index:index($project):)
     return  max.html:render($project, 'index', <div class='index'>{$HTMLIndex}</div>)
   }
   catch experr:HC0001{<div>Check your Index Plugin Config- TRACE:  {$err:description} -  {$err:module} - {$err:line-number}</div>}      
return if (file:exists($indexFilePath)) then max.plugin.index:index($project,$type)
       else $res
};

declare function max.plugin.index:loadIndex($edition,$type,$xq,$xsl,$lang) {
  let $dbPath := max.config:getProjectDBPath($edition)
  let $projectIndex := if($type='typesdocs')
                       then <index type="typesdocs">{
                         for $idx in collection($dbPath)//*:controlaccess/*:genreform
                         order by $idx/text()
                         let $cId := $idx/ancestor::*:c[1]/@id
                         let $cOtherlevel := $idx/ancestor::*:c[1]/@otherlevel
                         let $cUnitid := $idx/ancestor::*:c[1]/descendant::*:unitid[1]/text()
                         let $result := <marker id="{$cId}" otherlevel="{$cOtherlevel}"><entry>{$cUnitid}</entry><value>{$idx/text()}</value></marker>
                         return $result}</index>
                       else xquery:eval(xs:anyURI($xq)) 

declare %private function max.plugin.index:generateIndexToDonwload($project){
  let $HTMLProjectIndex := if($type='typesdocs')
                             then xslt:transform($projectIndex, 'indexing.xsl', ())
                           else xslt:transform($projectIndex, $xsl, ( map {'project' : $edition, 'locale' : $lang})) 

  ()
  return $HTMLProjectIndex
};
+31 −59
Original line number Diff line number Diff line
@@ -4,63 +4,35 @@
-->

<xsl:stylesheet	version="2.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns="urn:isbn:1-931666-22-9"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:xlink="http://www.w3.org/1999/xlink"
  xmlns:xinclude="http://www.w3.org/2001/XInclude"
  xmlns:xhtml="http://www.w3.org/TR/xhtml/strict"
  xmlns:tei="http://www.tei-c.org/ns/1.0"
                exclude-result-prefixes="tei xsl">
  xmlns:ns="urn:isbn:1-931666-22-9"
  xmlns:hfp="http://www.w3.org/2001/XMLSchema-hasFacetAndProperty"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  
  exclude-result-prefixes="tei xsl xsi xs xlink xinclude xhtml tei ns hfp">
  
  <xsl:output method="xml" encoding="utf-8"/>
<xsl:template match='/'>  
  <ul>
    <xsl:for-each-group select="//tei:person" group-by="substring(normalize-space(string-join(.//tei:persName//text(),'')),1,1)">
      <xsl:sort select="current-grouping-key()" />
      <li class="index-letter-block">
        <h2><xsl:value-of select="current-grouping-key()"/></h2>
            <ul>
              <xsl:for-each select="current-group()">
                <xsl:sort select="." />          
                <li class='index-block'><h3><xsl:value-of select="./ancestor::*:person[last()]/@xml:id"/></h3>
                  <ul>
                    <xsl:apply-templates />
                  </ul>
                  <xsl:apply-templates select="./ancestor::*:item[last()]/*:div[@*:type='occurs']"/>
                </li>
             </xsl:for-each>
           </ul>
        </li>
    </xsl:for-each-group>
  </ul>
</xsl:template>
     
<xsl:template match='tei:persName'>
  <xsl:variable name='class'><xsl:value-of select="@xml:lang"/></xsl:variable>
  <!--<xsl:if test="$class='fr'">
    <li>ID = <xsl:value-of select="./ancestor::*:person[last()]/@xml:id"/></li>
  </xsl:if>-->
  <li class='{$class}'><xsl:value-of select="."/><span class='lang'> [<xsl:value-of select="$class"/>]</span></li>
</xsl:template>     
     
<xsl:template match='tei:birth'>
  <li class='birth'>Né(e) le <xsl:value-of select="."/></li>
</xsl:template> 
<xsl:template match='tei:death'>
  <li class='death'>Décédé(e) le <xsl:value-of select="."/></li>
</xsl:template>
  
<xsl:template match='div'>
  <div class='occurs'><xsl:apply-templates /></div>
</xsl:template>
<xsl:template match='a'>
  <a class='index-link' href='{./@target}'><xsl:value-of select="."/></a>
  <xsl:template match="/index[@type='typesdocs']">
    <div class="{./@type}">
      <h1>Type de documents</h1>
      <xsl:for-each-group select="./descendant::marker" group-by="./value">
        <h2>
          <xsl:value-of select="current-grouping-key()"/>
        </h2>
        <div class="entries">
          <xsl:value-of select="current-group()/entry" separator="&#160;; "/>
        </div>
      </xsl:for-each-group>
    </div>
  </xsl:template>
  
<xsl:template match='tei:occupation | tei:note'>
<!-- TODO -->
  <xsl:template match="index">
    <xsl:copy-of select="."/>
  </xsl:template>


<!--  
           
<xsl:for-each-group select="record" group-by="info/date">
</xsl:for-each-group>
  -->
</xsl:stylesheet>
 No newline at end of file
+166 −0
Original line number Diff line number Diff line
# Plugin d'indexation #

Ce plugin propose une route unique pour tous les index.

Les index sont trop spécifiques pour permettre la mise en place d'un traitement par défaut satisfaisant.

Ce plugin propose donc une solution pour systématiser la production des index ainsi que les routes correspondantes.
Il permet de limiter les temps de calcul en stockant les fragments html de chaque page d'index.

La route associée à un index est `projet/index/typeindex.html``typeindex` est une valeur choisie par l'utilisateur. 

Ce plugin propose une route de base pour les types de documents en EAD (voir `index.xqm` et `indexing.xsl`).

Exemple de configuration du fichier xquery pour la génération d'un index des personnes (fichier à placer dans `PROJET/xq/index_personnes.xq`) :

```
<index type="personnes">
	{for $idx in collection("bvmsm")//*:persname
  	let $cId := $idx/ancestor::*:c[1]/@id
		let $baseuri := base-uri($idx)
    let $cOtherlevel := $idx/ancestor::*:c[1]/@otherlevel
    let $role := $idx/@role
		let $initiale := substring($idx/@normal,1,1) 
    let $cUnitid := $idx/ancestor::*:c[1]/descendant::*:unitid[1]/text()
    let $result := 
			<marker id="{$cId}" otherlevel="{$cOtherlevel}" role="{$role}">
   			<entry>{$cUnitid}</entry>
				<value>{data($idx/@normal)}</value>
				<baseuri>{$baseuri}</baseuri>
				<initiale>{$initiale}</initiale>
			</marker>
		return $result
	}
</index>

```

Exemple de traitement XSL associé (fichier à placer dans `PROJET/ui/xsl/index_personnes.xsl`) :

```
<xsl:stylesheet version="2.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:xlink="http://www.w3.org/1999/xlink"
  xmlns:xinclude="http://www.w3.org/2001/XInclude"
  xmlns:xhtml="http://www.w3.org/TR/xhtml/strict"
  xmlns:tei="http://www.tei-c.org/ns/1.0"
  xmlns:ead="urn:isbn:1-931666-22-9"
  xmlns:hfp="http://www.w3.org/2001/XMLSchema-hasFacetAndProperty"
  xmlns:max="https://max.unicaen.fr"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="max ead tei xsl xsi xs xlink xinclude xhtml tei hfp">
  <!--pour importer le i18n-->
  <xsl:import href="../../../../ui/xsl/i18n.xsl"/>
  <xsl:output method="xhtml" encoding="utf-8" indent="no"/>
  
  <xsl:preserve-space elements="*:*"/>
  
<!--variables pour le i18n-->
  <xsl:param name="project"/>
  <xsl:param name="locale"/>
  <xsl:param name="key"/>
  <xsl:template match="*:index[@type='personnes']">

    <div class="{./@type}">
      <h1>Index des personnes</h1>
      <xsl:for-each-group select="./descendant::*:marker" group-by="@role">
        <xsl:sort select="@role" order="ascending"/>
        <div class="subindex" id="{current-grouping-key()}">
          <h2 class="collapsible">
            <xsl:choose>
              <xsl:when test="@role='auteur'">
                <!-- pour avoir une variante de titre selon la langue -->
                  <xsl:value-of select="max:i18n($project,'label.index_auteur',$locale)"/>
                
              </xsl:when>
              <xsl:when test="@role='annotateur'">
                <xsl:text>Annotateurs</xsl:text>
              </xsl:when>
              <xsl:when test="@role='commanditaire'">
                <xsl:text>Commanditaires</xsl:text>
              </xsl:when>
              <xsl:when test="@role='commentateur'">
                <xsl:text>Commentateurs</xsl:text>
              </xsl:when>
              <xsl:when test="@role='conservateur'">
                <xsl:text>Conservateurs</xsl:text>
              </xsl:when>
              <xsl:when test="@role='dedicataire'">
                <xsl:text>Dédicataires</xsl:text>
              </xsl:when>
              <xsl:when test="@role='donateur'">
                <xsl:text>Donateurs</xsl:text>
              </xsl:when>
              <xsl:when test="@role='editeur_sci'">
                <xsl:text>Éditeurs scientifiques</xsl:text>
              </xsl:when>
              <xsl:when test="@role='graveur'">
                <xsl:text>Graveurs</xsl:text>
              </xsl:when>
              <xsl:when test="@role='illustrateur'">
                <xsl:text>Illustrateurs</xsl:text>
              </xsl:when>
              <xsl:when test="@role='imprimeur-libraire'">
                <xsl:text>Imprimeurs-libraires</xsl:text>
              </xsl:when>
              <xsl:when test="@role='possesseur'">
                <xsl:text>Possesseurs</xsl:text>
              </xsl:when>
              <xsl:when test="@role='scribe'">
                <xsl:text>Scribes</xsl:text>
              </xsl:when>
              <xsl:when test="@role='traducteur'">
                <xsl:text>Traducteurs</xsl:text>
              </xsl:when>
              <xsl:otherwise>
                <xsl:value-of select="current-grouping-key()"/>
              </xsl:otherwise>
            </xsl:choose>

          </h2>
          <div class="developper">

            <xsl:for-each-group select="current-group()" group-by="./*:initiale">
              <xsl:sort select="./*:initiale" order="ascending"/>
              <fieldset id="{@role}{./*:initiale}">
                <legend class="collapsible">
                  <xsl:value-of select="./*:initiale"/>
                </legend>
                <div class="developper">
                  <xsl:for-each-group select="current-group()" group-by="./*:value">
                    <xsl:sort select="./*:value" order="ascending"/>
                    <p class="entries">
                      <xsl:text>–&#160;</xsl:text>
                      <span class="persname">
                        <xsl:value-of select="*:value"/>
                      </span>
                      <xsl:text>&#160;:&#160;</xsl:text>
                      <xsl:for-each select="current-group()">
                        <a target="_blank">
                          <xsl:attribute name="href">
                            <xsl:value-of select="./*:baseuri[1]"/>
                            <xsl:text>/</xsl:text>
                            <xsl:value-of select="./@id"/>
                            <xsl:text>.html</xsl:text>
                          </xsl:attribute>
                          <xsl:value-of select="./*:entry"/>
                        </a>
                        <xsl:if test="not(position()=last())">
                          <xsl:text>&#160;; </xsl:text>
                        </xsl:if>
                      </xsl:for-each>
                    </p>
                  </xsl:for-each-group>
                </div>
              </fieldset>
            </xsl:for-each-group>
          </div>
        </div>
      </xsl:for-each-group>
    </div>
  </xsl:template>

</xsl:stylesheet>
```  

Un fichier html est généré lors du premier accès à cette page, la requête XQUERY et le traitement XSL associé sont exécutés lors de ce premier appel. Pour générer à nouveau la page d'index il suffit de supprimer le fichier `PROJET/fragments/LOCALE/index_typeindex.frag.html` souhaité.