在haskell中生成html表的最简单方法是什么?

时间:2014-03-26 08:28:21

标签: html haskell

我想以html格式输出一个表格。 基本上我想要像:

[[a]] -> <table> 

最简单的方法是什么?

2 个答案:

答案 0 :(得分:7)

生成Html的最简单方法可能是blaze

import Text.Blaze.Html5 (table, td, tr, toHtml, ToMarkup, Html)
import Control.Monad (forM_, mapM_)

myTable :: (ToMarkup a) => [[a]] -> Html
myTable xs = table $ forM_ xs (tr . mapM_ (td . toHtml))

请注意,您需要使用renderHtml中的Text.Blaze.Renderer.*来获取ByteStringStringText

答案 1 :(得分:3)

编辑:在撰写答案期间,@ Zeta已使用blaze-html发布了更好的解决方案。所以我建议使用他的解决方案(参见&#34;警告词&#34;听取这个解决方案的缺点......); - )

这是一个实现:

-- file test.hs:

insideTag :: String -> String -> String
insideTag tag content = "<" ++ tag ++ ">" ++ content ++ "</" ++ tag ++ ">"

toTable :: Show a => [[a]] -> String
toTable = insideTag "table" . concatMap (insideTag "tr") . map (concatMap (insideTag "td" . show))

main :: IO ()
main = do
    putStrLn $ toTable [[1,2,3],[4,5,6],[7,8,9]]
    return ()

命令runhaskell test.hs现在将打印

<table><tr><td>1</td><td>2</td><td>3</td></tr><tr><td>4</td><td>5</td><td>6</td></tr><tr><td>7</td><td>8</td><td>9</td></tr></table>

代码说明

insideTag将内容封装在html标记内:

ghci> let insideTag tag content = "<" ++ tag ++ ">" ++ content ++ "</" ++ tag ++ ">"
ghci> insideTag "h1" "hello world"
"<h1>hello world</h1>"

map (concatMap (insideTag "td" . show)) list将内部元素封装到<td>标记中并将它们连接起来:

ghci> map (concatMap (insideTag "td" . show)) [[1,2], [3,4]]
["<td>1</td><td>2</td>","<td>3</td><td>4</td>"]

外部列表也可以这样做:

ghci> concatMap (insideTag "tr") ["<td>1</td><td>2</td>","<td>3</td><td>4</td>"]
"<tr><td>1</td><td>2</td></tr><tr><td>3</td><td>4</td></tr>"

最后一个字符串只需封装到<table>标记中:

ghci> insideTag "table" "<tr><td>1</td><td>2</td></tr><tr><td>3</td><td>4</td></tr>"
"<table><tr><td>1</td><td>2</td></tr><tr><td>3</td><td>4</td></tr></table>"

警告字

上面的代码使用普通的[Char]类型表示不具有内存效率的字符串。因此,如果您处理大表格,我建议您使用Data.Text toTable保持不变,您只需将show更改为pack . show; insideTagData.Text)重新实现。

表内容也没有HTML转义!!! 因此上述代码容易受到XSS attacts的攻击。因此,如果生成的HTML应包含在网站中(特别是如果网站用户对表格内容有影响),请不要使用上述代码!