HXT跳过错误的元素

时间:2014-04-17 11:19:27

标签: haskell hxt

我正在遍历表的列表并在proc内部我正在使用可能抛出异常的函数(我无法改变其行为):

parseThing :: ArrowXml a => a XmlTree Thing
parseThing = deep (hasName "table") &&& deep (hasName "h3") >>> proc (table, h3) -> do
  name <- getText <<< getChildren -< h3
  info -< listA parseTable -< table

  returnA $ mkThing name info -- may throw an exception

其中parseTable :: ArrowXml a => a XmlTree (String, String)<tr><td>key</td><td>value</td></tr>解析为(key, value)元组,并mkThing :: String -> [(String, String)] -> Thingnameinfo构建Thing并可能抛出异常(它取决于名称和信息)

如何跳过处理无法构建的东西?如果我保留未捕获的异常,它会以某种方式转换为字符串并进入输出。

1 个答案:

答案 0 :(得分:2)

您可以使用catchA箭头来处理管道内的异常。在这种情况下,parseThing需要具有更具体的IO感知类型,如IOSArrow

要跳过例外,catchA 被赋予none箭头作为异常处理程序。

以下是完整示例(我从parseThing_aux中提取parseThing以提高可读性:

{-# LANGUAGE Arrows #-}
import Control.Arrow.ArrowExc (catchA)
import Text.XML.HXT.Core


data Thing = Thing String [(String,String)] deriving Show


main :: IO ()
main = do
  xml <- getContents
  res <- runX $ readString [] xml >>> parseThing
  mapM_ print res


parseThing :: IOSArrow XmlTree Thing
parseThing
  = deep (hasName "table") &&& deep (hasName "h3")
  >>> catchA parseThing_aux none


parseThing_aux :: IOSArrow (XmlTree, XmlTree) Thing
parseThing_aux = proc (table, h3) -> do
    name <- getText <<< getChildren -< h3
    info <- listA parseTable -< table
    returnA -< mkThing name info


parseTable :: ArrowXml a => a XmlTree (String, String)
parseTable = error "Not implemented"


mkThing :: String -> [(String,String)] -> Thing
mkThing n i = Thing n i

旁注1

如果您想要压缩表格和标题而不是制作它们的交叉产品,可以将parseThing更改为

parseThing
  = (listA $ deep $ hasName "table") &&& (listA $ deep $ hasName "h3")
  >>> arr2 zip >>> unlistA
  >>> catchA parseThing_aux none

旁注2

以无点样式编写parseThing_aux

更简洁一点
parseThing_aux
  = (getChildren >>> getText) *** listA parseTable
  >>^ uncurry mkThing

(您可以通过更改uncurry来取消mkThing来消除{{1}}。