module Text.XML.Cursor.Generic
(
Cursor
, Axis
, toCursor
, node
, child
, parent
, precedingSibling
, followingSibling
, ancestor
, descendant
, orSelf
, preceding
, following
, (&|)
, (&/)
, (&//)
, (&.//)
, ($|)
, ($/)
, ($//)
, ($.//)
, (>=>)
) where
import Data.Maybe (maybeToList)
import Data.List (foldl')
import Control.Monad ((>=>))
type DiffCursor node = [Cursor node] -> [Cursor node]
type Axis node = Cursor node -> [Cursor node]
data Cursor node = Cursor
{ parent' :: Maybe (Cursor node)
, precedingSibling' :: DiffCursor node
, followingSibling' :: DiffCursor node
, child :: [Cursor node]
, node :: node
}
instance Show node => Show (Cursor node) where
show Cursor { node = n } = "Cursor @ " ++ show n
toCursor :: (node -> [node])
-> node
-> Cursor node
toCursor cs = toCursor' cs Nothing id id
toCursor' :: (node -> [node])
-> Maybe (Cursor node) -> DiffCursor node -> DiffCursor node -> node -> Cursor node
toCursor' cs par pre fol n =
me
where
me = Cursor par pre fol chi n
chi' = cs n
chi = go id chi' []
go _ [] = id
go pre' (n':ns') =
(:) me' . fol'
where
me' = toCursor' cs (Just me) pre' fol' n'
fol' = go (pre' . (:) me') ns'
parent :: Axis node
parent = maybeToList . parent'
precedingSibling :: Axis node
precedingSibling = ($ []) . precedingSibling'
followingSibling :: Axis node
followingSibling = ($ []) . followingSibling'
preceding :: Axis node
preceding c =
go (precedingSibling' c []) (parent c >>= preceding)
where
go x y = foldl' (flip go') y x
go' x rest = foldl' (flip go') (x : rest) (child x)
following :: Axis node
following c =
go (followingSibling' c) (parent c >>= following)
where
go x z = foldr go' z (x [])
go' x rest = x : foldr go' rest (child x)
ancestor :: Axis node
ancestor = parent >=> (\p -> p : ancestor p)
descendant :: Axis node
descendant = child >=> (\c -> c : descendant c)
orSelf :: Axis node -> Axis node
orSelf ax c = c : ax c
infixr 1 &|
infixr 1 &/
infixr 1 &//
infixr 1 &.//
infixr 1 $|
infixr 1 $/
infixr 1 $//
infixr 1 $.//
(&|) :: (Cursor node -> [a]) -> (a -> b) -> (Cursor node -> [b])
f &| g = map g . f
(&/) :: Axis node -> (Cursor node -> [a]) -> (Cursor node -> [a])
f &/ g = f >=> child >=> g
(&//) :: Axis node -> (Cursor node -> [a]) -> (Cursor node -> [a])
f &// g = f >=> descendant >=> g
(&.//) :: Axis node -> (Cursor node -> [a]) -> (Cursor node -> [a])
f &.// g = f >=> orSelf descendant >=> g
($|) :: Cursor node -> (Cursor node -> a) -> a
v $| f = f v
($/) :: Cursor node -> (Cursor node -> [a]) -> [a]
v $/ f = child v >>= f
($//) :: Cursor node -> (Cursor node -> [a]) -> [a]
v $// f = descendant v >>= f
($.//) :: Cursor node -> (Cursor node -> [a]) -> [a]
v $.// f = orSelf descendant v >>= f