генерировать динамические строки таблицы с использованием XQuery - PullRequest
1 голос
/ 06 января 2012

У меня есть функция, которая возвращает телефонные номера.Возвращается в этом формате

<td>#phone</td>

Функция может возвращать любое количество значений.Я хочу отобразить их в виде сетки.т.е. таблица, в которой есть, скажем, 10 столбцов.(Поэтому, если функция возвращает 26 записей, у меня будет 3 строки: две строки с 10 столбцами и третья строка с 6 столбцами.)

Я не могу понять логику счетчика для оператора for в XQuery (длязаявление с ключевым словом в).Любая помощь будет принята.

Вызов функции подобен этому (любая модификация вызова функции также высоко ценится):

Фактический код такой:

declare function local:table-construct(
  $areacode as xs:string, 
  $uniquekey as $xs:string, 
  $doc as xs:element) as xs:element?
{
  for $phno in $doc/users[$areacode eq $code and $uniquekey eq $thiskey]
  return <td>{$phno/phone}</td>
}

let $doc := <an xml doc from a database>
let $areacode := "somestring"
let $uniquekey := "somekey"
return 
  <html>
    <body>
      <table>
        <tr>{local:table-construct($areacode, $uniquekey, $doc)}</tr>
      </table>
    </body>
  </html>

В текущем формате все номера телефонов указаны в одном ряду.Я хочу, чтобы таблица показывала только 10 строк.а остальные данные в следующих строках.

Ответы [ 3 ]

1 голос
/ 06 января 2012

Поскольку вы не предоставили никакого кода, я могу только догадываться, что вы попали в ловушку "функционального программирования".XQuery - это функциональный язык без переменных, известных в императивных языках, лучше думать о них как о константах.

let $x := 1 to 10
let $sum := 0
for $i in $x
let $sum := $sum+$i (: here we cover $sum from line 2, do not change it :)
return $sum

Вывод этого кода - 1 2 3 4 5 6 7 8 9 10, что может быть неожиданным.В строке 4 мы всегда добавляем $i (от 1 до 10) и $sum (0), но мы не обновляем $sum, а покрываем его.Для следующего $i, $sum снова будет 0.

Если это проблема, подумайте об использовании некоторого шаблона, подобного следующему:

let $seq := 1 to 15
let $dividor := 4
for $i in 1 to ceiling(count($seq) div $dividor) cast as xs:integer
return <tr>{
  for $td in subsequence($seq, ($i -1)*$dividor + 1, $dividor)
  return <td>{$td}</td>
}</tr>

Возможно, вам придется подгонять егок вашему коду, но идея должна быть в порядке.

РЕДАКТИРОВАТЬ: Если ваш процессор запросов поддерживает его, вы также можете использовать скользящее окно .Начиная с версии 5.0.2, Marklogic по-прежнему этого не делает.

0 голосов
/ 07 января 2012

Ключевое слово at в выражении FLWOR здесь вам мало поможет. Вам нужно взять 10 столбцов за раз и поместить их в свои <tr>. Наиболее простой способ сделать это в MarkLogic заключается в следующем:

declare function local:wrap-columns($columns, $width) {
  let $nrrows := ceiling(count($columns) div $width)
  for $row in 1 to $nrrows
  let $start := ($row - 1) * $width + 1
  let $end := $row * $width
  return
    <tr>{$columns[$start to $end]}</tr>
};

let $columns :=
  for $i in 1 to 26
  return <td>{$i}</td>
return
  local:wrap-columns($columns, 10)

На второй взгляд, оно напоминает решение Ranon (совпадение, честно), хотя и заключено в функцию, облегчающую интеграцию и повторное использование.

Решение в XSLT также будет работать, но если вы еще не используете XSLT, тогда, я думаю, использование XQuery имеет больше смысла.

НТН!

0 голосов
/ 06 января 2012

Возможно, это поможет вам, вы можете выполнить группировку в соответствии с вашим запросом внутри xslt!

<xsl:stylesheet version="1.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:variable name="Columns" select="10"/>

  <xsl:template match="/*">
    <xsl:copy>
      <xsl:apply-templates select="phone[position() mod $Columns= 1]"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="phone">
    <tr>
      <xsl:apply-templates mode="copy" select=". | following-sibling::phone[position() &lt; $Columns]"/>
    </tr>
  </xsl:template>

  <xsl:template match="line" mode="copy">
    <td><xsl:copy-of select="."/><td>
  </xsl:template>
</xsl:stylesheet>
...