これが1つのアプローチです(私のタイプはもう少し一般的で、XPathを使用していません):
{-# LANGUAGE Arrows #-}
module Main where
import qualified Data.Map as M
import Text.XML.HXT.Arrow
classes :: (ArrowXml a) => a XmlTree (M.Map String String)
classes = listA (divs >>> divs >>> pairs) >>> arr M.fromList
where
divs = getChildren >>> hasName "div"
pairs = proc div -> do
cls <- getAttrValue "class" -< div
val <- deep getText -< div
returnA -< (cls, val)
getValues :: (ArrowXml a) => [String] -> a XmlTree [(String, Maybe String)]
getValues cs = classes >>> arr (zip cs . lookupValues cs)
where lookupValues cs m = map (flip M.lookup m) cs
main = do
let xml = "<div><div class='c1'>a</div><div class='c2'>b</div>\
\<div class='c3'>123</div><div class='c4'>234</div></div>"
print =<< runX (readString [] xml >>> getValues ["c1", "c2", "c3", "c4"])
おそらく矢印を実行してマップを取得してからルックアップを実行しますが、この方法でも機能します。
listA:に関する質問に答えるにdivs >>> divs >>> pairsは、タイプがリストの矢印a XmlTree (String, String)です。つまり、XMLツリーを取得し、文字列のペアを返す非決定論的な計算です。
arr M.fromListタイプがありa [(String, String)] (M.Map String String)ます。divs >>> divs >>> pairsこれは、タイプが一致しないため、で構成することはできないことを意味します。
listAこの問題を解決します。タイプが決定論的なバージョンに崩壊 します。これはまさに私たちが必要としているものです。divs >>> divs >>> pairsa XmlTree [(String, String)]