2012-01-06 99 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