質問

Haskell XML Toolkit、HXTを使用してこれまで見たすべての例は使用しています runX パーサーを実行します。 runX IO Monad内で走ります。 IO以外でこのXMLパーサーを使用する方法はありますか?私にとっては純粋な手術のようです。なぜ私がIOの中にいることを余儀なくされているのか理解していません。

役に立ちましたか?

解決

HXTを使用できます xread 一緒に runLA 外側のXML文字列を解析します IO.

xread 次のタイプがあります。

xread :: ArrowXml a => a String XmlTree

これは、タイプのあらゆる矢印で作曲できることを意味します (ArrowXml a) => a XmlTree Whatever を取得する a String Whatever.

runLA のようなものです runX, 、しかし、タイプのもののために LA:

runLA :: LA a b -> a -> [b]

LA のインスタンスです ArrowXml.

これをすべてまとめるために、次のバージョンの 私の答え 以前の質問にHXTを使用して、整形式のXMLを含む文字列を解析するために IO 関与:

{-# 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 >>> 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) >>> unlistA
  where lookupValues cs m = map (flip M.lookup m) cs

xml = "<div><div class='c1'>a</div><div class='c2'>b</div>\
      \<div class='c3'>123</div><div class='c4'>234</div></div>"

values :: [(String, Maybe String)]
values = runLA (xread >>> getValues ["c1", "c2", "c3", "c4"]) xml

main = print values

classesgetValues 以前のバージョンに似ており、予想される入力と出力に合わせていくつかの小さな変更があります。主な違いは、ここで使用していることです xreadrunLA それ以外の readStringrunX.

怠zyのようなものを読むことができるのはいいことです ByteString 同様の方法では、私が知っている限り、これは現在HXTでは不可能です。


他のいくつかのこと:あなた できる この方法で文字列を解析します IO, 、しかし、おそらく使用する方が良いでしょう runX できる限り:パーサーの構成、エラーメッセージなどをより強く制御できます。

また:例のコードを簡単で簡単に拡張しようとしましたが、コンビネーターは Control.ArrowControl.Arrow.ArrowList 必要に応じて、より簡潔に矢印で作業できるようにします。以下は同等の定義です classes, 、 例えば:

classes = (getChildren >>> hasName "div" >>> pairs) >. M.fromList
  where pairs = getAttrValue "class" &&& deep getText

他のヒント

トラビス・ブラウンの答えはとても役に立ちました。ここに独自のソリューションを追加したいだけです。これはもう少し一般的だと思います(同じ機能を使用して、問題固有の問題を無視するだけです)。

私は以前に抑えていませんでした:

upIO      :: XmlPickler a => String -> IO [a]
upIO str   = runX $ readString [] str >>> arrL (maybeToList . unpickleDoc xpickle)

私はこれに変更することができました:

upPure    :: XmlPickler a => String -> [a]
upPure str = runLA (xreadDoc >>> arrL (maybeToList . unpickleDoc xpickle)) str

私は彼に完全に同意します。これを行うと、パーサーなどの構成を制御できなくなりますが、残念です。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top