module Text.XML.HaXml.Xtract.Combinators where
import Text.XML.HaXml.Types
import Text.XML.HaXml.Combinators (CFilter)
import qualified Text.XML.HaXml.Combinators as C
type DFilter i = Content i -> Content i -> [Content i]
local,global :: CFilter i -> DFilter i
local f = \xml sub-> f sub
global f = \xml sub-> f xml
dfilter :: DFilter i -> CFilter i
dfilter f = \xml-> f xml xml
cfilter :: DFilter i -> CFilter i
cfilter f = \xml -> f undefined xml
liftLocal, liftGlobal :: (CFilter i->CFilter i) -> (DFilter i->DFilter i)
liftLocal ff = \df-> \xml sub-> (ff (df xml)) sub
liftGlobal ff = \df-> \xml sub-> (ff (df xml)) xml
o :: DFilter i -> DFilter i -> DFilter i
g `o` f = \xml-> concatMap (g xml) . (f xml)
(|>|) :: (a->b->[c]) -> (a->b->[c]) -> (a->b->[c])
f |>| g = \xml sub-> let first = f xml sub in
if null first then g xml sub else first
union :: (a->b->[c]) -> (a->b->[c]) -> (a->b->[c])
union = lift (++)
where
lift f g h = \x y-> f (g x y) (h x y)
with, without :: DFilter i -> DFilter i -> DFilter i
f `with` g = \xml-> filter (not.null.g xml) . f xml
f `without` g = \xml-> filter (null.g xml) . f xml
keep, none :: DFilter i
keep = \xml sub-> [sub]
none = \xml sub-> []
children, elm, txt :: DFilter i
children = local C.children
elm = local C.elm
txt = local C.txt
applypred :: CFilter i -> DFilter i -> CFilter i
applypred f p = \xml-> (const f `with` p) xml xml
iffind :: String -> (String -> DFilter i) -> DFilter i -> DFilter i
iffind key yes no xml c@(CElem (Elem _ as _) _) =
case (lookup key as) of
Nothing -> no xml c
(Just v@(AttValue _)) -> yes (show v) xml c
iffind key yes no xml other = no xml other
ifTxt :: (String->DFilter i) -> DFilter i -> DFilter i
ifTxt yes no xml c@(CString _ s _) = yes s xml c
ifTxt yes no xml c = no xml c
cat :: [a->b->[c]] -> (a->b->[c])
cat fs = \xml sub-> concat [ f xml sub | f <- fs ]
(/>) :: DFilter i -> DFilter i -> DFilter i
f /> g = g `o` children `o` f
(</) :: DFilter i -> DFilter i -> DFilter i
f </ g = f `with` (g `o` children)
deep, deepest, multi :: DFilter i -> DFilter i
deep f = f |>| (deep f `o` children)
deepest f = (deepest f `o` children) |>| f
multi f = f `union` (multi f `o` children)