首页 > 解决方案 > Xquery 中的 XSLT 风格的小型转换?

问题描述

目前在 Xquery 3.1(在 eXist 4.7)中,我收到如下所示的 XML 片段(来自 eXist 的 Lucene 全文搜索):

let $text :=

 <tei:text>
   <front>
     <tei:div>
        <tei:listBibl>
            <tei:bibl>There is some</tei:bibl>
            <tei:bibl>text in certain elements</tei:bibl>
        </tei:listBibl>
     </tei:div>
     <tei:div>
        <tei:listBibl>
            <tei:bibl>which are subject <exist:match>to</exist:match> a Lucene search</tei:bibl>
            <tei:bibl></tei:bibl>
        <tei:listBibl>
     </tei:div>
   <tei:front>
   <tei:body>
     <tei:p>and often produces</tei:p>
     <tei:p>a hit.</tei:p>
   <tei:body>
 <tei:text> 

目前,我让 Xquery 将此片段发送到 XSLT 样式表,以便将其转换为 HTML,如下所示:

<td>...elements which are subject <span class="search-hit">to</span> a Lucene search and often p...

样式表的工作是返回前后 30 个字符的文本,<exist:match/>并将内容<exist:match/>放入一个跨度中。<exist:match/>每次转换只有一个。

这一切都很好。但是,我想到这是一项非常小的工作,实际上只有一个元素的单个转换,其余的是一种字符串连接。因此,我想知道这是否不能在 Xquery 中有效地完成。

在尝试执行此操作时,我似乎无法找到一种方法来处理字符串内容直到.<exist:match/>之后的字符串内容<exist:match/>。我的想法是,在伪代码中,输出如下结果:

let $textbefore := some function to get the text before <exist:match/>
let $textafter := some function to get text before <exist:match/>
return <td>...{$textbefore} 
        <span class="search-hit">
          {$text//exist:match/text()}
        </span> {$textafter}...</td>

这甚至值得在 Xquery 与当前的 Xquery -> 我拥有的 XSLT 管道中做吗?

非常感谢。

标签: xqueryexist-db

解决方案


我认为可以这样做

declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";

declare namespace tei = "http://example.com/tei";
declare namespace exist = "http://example.com/exist";

declare option output:method 'html';

let $text :=

 <tei:text>
   <tei:front>
     <tei:div>
        <tei:listBibl>
            <tei:bibl>There is some</tei:bibl>
            <tei:bibl>text in certain elements</tei:bibl>
        </tei:listBibl>
     </tei:div>
     <tei:div>
        <tei:listBibl>
            <tei:bibl>which are subject <exist:match>to</exist:match> a Lucene search</tei:bibl>
            <tei:bibl></tei:bibl>
        </tei:listBibl>
     </tei:div>
   </tei:front>
   <tei:body>
     <tei:p>and often produces</tei:p>
     <tei:p>a hit.</tei:p>
   </tei:body>
 </tei:text> 
 , 
 $match := $text//exist:match,
 $text-before-all := normalize-space(string-join($match/preceding::text(), ' ')),
 $text-before := substring($text-before-all, string-length($text-before-all) - 30),
 $text-after := substring(normalize-space(string-join($match/following::text(), ' ')), 1, 30)
return 
 <td>...{$text-before} 
        <span class="search-hit">
          {$match/text()}
        </span> {$text-after}...</td>

这在 XQuery 中也不是一个真正的查询,而只是一些 XPath 选择加上一些可能昂贵的字符串连接和在前后轴上的提取。


推荐阅读