使用XQuery生成动态表行

时间:2012-01-06 09:01:30

标签: xslt xquery marklogic

我有一个返回电话号码的功能。它以这种格式返回

<td>#phone</td>

该函数可以返回任意数量的值。 我想以类似网格的结构显示它们。 即一张表中有10列的表格。 (因此,如果函数返回26条记录,那么我将有3行:两行10列,第三行6列。)

我无法理解XQuery中for语句中的计数器逻辑(对于带有关键字at的语句)。任何帮助将不胜感激。

函数调用是这样的(函数调用的任何修改也非常受欢迎):

实际代码如下:

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 个答案:

答案 0 :(得分:1)

因为你没有提供任何代码,我只能猜到你被困在“函数式编程”陷阱中。 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>

您可能需要将其与您的代码相匹配,但这个想法应该没问题。

编辑:如果您的查询处理器支持它,您也可以使用sliding window。从版本5.0.2开始,Marklogic仍然没有。

答案 1 :(得分:0)

mabe这可以提供帮助,您可以根据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>

答案 2 :(得分:0)

FLWOR语句的at关键字在这里对你没什么帮助。您需要一次取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会更有意义。

HTH!

相关问题