2012-01-06 70 views
0

我有一个返回电话号码的函数。它返回这个格式使用XQuery生成动态表格行

<td>#phone</td> 

该函数可以返回任意数量的值。 我想显示他们像一个网格结构。 即具有10列的表格。 (所以如果该函数返回26条记录,那么我将有3行:两行10列,第三行6列。)

我无法理解for语句中的计数器逻辑在XQuery中(for statement with关键字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行。以及下一行中的其余数据。

+0

你可以显示你正在使用的实际XQuery代码吗? – grtjn 2012-01-06 12:05:27

+0

@grtjn请检查,我已经在问题 – satsamsk 2012-01-07 05:25:54

回答

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仍然没有。

+0

感谢Ranon。你发现了。我确实被困在“函数编程陷阱”中。这有助于理解计数器背后的逻辑。 – satsamsk 2012-01-09 08:06:08

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> 
+0

Treemonkey中添加了代码。我一直在寻找XSL作为第二选择,但无论如何感谢您的回应,并感谢帮助! – satsamsk 2012-01-09 08:07:51

+0

您的非常欢迎:)感谢评论 – Treemonkey 2012-01-09 09:23:45

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!

+0

谢谢。这对理解计数器逻辑非常有帮助。感谢帮助。 – satsamsk 2012-01-09 08:03:31