XQuery - выводит серию HTML-элементов с разделителем

В XQuery 3.1 я создаю HTML-таблицу. В одном элементе <td> я вывожу серию <a ref="">.

Итак, на данный момент это простое for:

 <td>
   {
     for $b in collection($globalvar:URIdata)/tei:TEI/tei:text//tei:seg[@type="dep_event" 
                           and @corresp = $a/data(@corresp)
                           and @xml:id != $a/data(@xml:id)] 

     order by $b/data(@xml:id)

     return <a href="{concat($globalvar:URLdoc,$b/ancestor::tei:TEI/tei:text/@xml:id)}">{$b/data(@xml:id)}</a>                        
    }
 </td>

Выводит это:

     <td>
      <a href="http://localhost:8081/exist/apps/deheresi/doc/MS609-0006">MS609-0006-8</a>
      <a href="http://localhost:8081/exist/apps/deheresi/doc/MS609-0419">MS609-0419-5</a>
      <a href="http://localhost:8081/exist/apps/deheresi/doc/MS609-0613">MS609-0613-4</a>
    </td>

Но я бы хотел, чтобы он выводил список из <a href=""> через запятую:

     <td>
      <a href="http://localhost:8081/exist/apps/deheresi/doc/MS609-0006">MS609-0006-8</a>, 
      <a href="http://localhost:8081/exist/apps/deheresi/doc/MS609-0419">MS609-0419-5</a>, 
      <a href="http://localhost:8081/exist/apps/deheresi/doc/MS609-0613">MS609-0613-4</a>
    </td>

РЕДАКТИРОВАТЬ: ниже работает ... но не выводит результаты в желаемом порядке, и я не могу заставить order by $b/data(@xml:id) работать с ним из-за проблемы "мощности" (которая не всплывала в оригинале).

    let $coll := collection($globalvar:URIdata)/tei:TEI/tei:text//tei:seg[@type="dep_event" 
                     and @corresp = $a/data(@corresp)
                     and @xml:id != $a/data(@xml:id)] 

     let $last := count($coll)

     for $b at $position in $coll 

     return (<a href="{concat($globalvar:URLdoc,$b/ancestor::tei:TEI/tei:text/@xml:id)}">{$b/data(@xml:id)}</a>,
           if ($position ne $last) then ', ' else '')

Большое спасибо за любой совет.


person jbrehr    schedule 06.11.2018    source источник


Ответы (1)


Я не уверен, есть ли в XQuery общая идиома для этого, но я думаю, что используя

 for $b in collection($globalvar:URIdata)/tei:TEI/tei:text//tei:seg[@type="dep_event" 
                       and @corresp = $a/data(@corresp)
                       and @xml:id != $a/data(@xml:id)] 

 order by $b/data(@xml:id)
 count $p
 let $a := <a href="{concat($globalvar:URLdoc,$b/ancestor::tei:TEI/tei:text/@xml:id)}">{$b/data(@xml:id)}</a>
 return 
   if ($p > 1)
   then (',', $a)
   else $a

это возможный способ, как и старый подход XSLT, иметь <xsl:for-each select="$nodes"><xsl:if test="position() > 1">,</xsl:if><xsl:copy-of select="."/></xsl:for-each>. Ближе к этому вы также можете попробовать

 (
 for $b in collection($globalvar:URIdata)/tei:TEI/tei:text//tei:seg[@type="dep_event" 
                       and @corresp = $a/data(@corresp)
                       and @xml:id != $a/data(@xml:id)] 

 order by $b/data(@xml:id)

 return <a href="{concat($globalvar:URLdoc,$b/ancestor::tei:TEI/tei:text/@xml:id)}">{$b/data(@xml:id)}</a>
 ) ! (if (position() > 1) then (',', .) else .)  

Это также можно было бы записать как

 (
 for $b in collection($globalvar:URIdata)/tei:TEI/tei:text//tei:seg[@type="dep_event" 
                       and @corresp = $a/data(@corresp)
                       and @xml:id != $a/data(@xml:id)] 

 order by $b/data(@xml:id)

 return <a href="{concat($globalvar:URLdoc,$b/ancestor::tei:TEI/tei:text/@xml:id)}">{$b/data(@xml:id)}</a>
 ) ! (if (position() > 1) then ',' else (), .) 

немного ближе ко второй попытке.

person Martin Honnen    schedule 06.11.2018
comment
Я только что отредактировал в своем вопросе что-то подобное, используя xquery for $x at $position in $y - count - это функция, которая переходит в назначение переменной. order by теперь странным образом отвергается XQuery как проблема мощности. - person jbrehr; 06.11.2018
comment
Тогда это было бы еще одной проблемой, вы не показали, где вы разместили заказ в своей новой попытке. Оба моих предложения не изменили ваш исходный код, а просто включили их в более крупные выражения. - person Martin Honnen; 06.11.2018
comment
Я только что попробовал ваш второй, и он работает. Это захватывающее решение, которое я понимаю лишь наполовину. Что ! делает, что позволяет (if (position() > 1) then (',', .) else .) работать? - person jbrehr; 06.11.2018
comment
! - это так называемый оператор карты w3.org/TR/xquery- 31 / # id-map-operator, введенный в XPath 3, соответственно, XQuery 3 для сопоставления каждого элемента последовательности слева с выражением справа. - person Martin Honnen; 06.11.2018
comment
Итак, простым языком, query result - это последовательность (слева от !), и этому результату сопоставлен (справа) XSLT position(), чтобы определить, следует ли что-то делать на основе этого? - person jbrehr; 06.11.2018
comment
Ваше выражение for .. return <a>...</a> создает последовательность узлов a элементов, а выражение карты for .. return <a>...</a> ! (if (position() > 1) then (',', .) else .) оценивает правую часть, выражение if, для каждого элемента a и возвращает новую последовательность с результатом выражения if, примененного к каждому элементу a. Для первого элемента a выражение if возвращает этот элемент a, для других элементов оно оценивается как последовательность из двух элементов: строка с запятой и элемент a. - person Martin Honnen; 06.11.2018
comment
@jbrehr Возможно, вы столкнулись с отсутствием поддержки eXist (пока) предложения count. Функция map operator + position() - это одна замена; другой вариант - использовать предложение at в FLWOR. Надеюсь, мы скоро добавим пункт count! - person Joe Wicentowski; 08.11.2018