module Text.XML.Cursor
(
Cursor
, Axis
, fromDocument
, fromNode
, cut
, parent
, CG.precedingSibling
, CG.followingSibling
, child
, node
, CG.preceding
, CG.following
, CG.ancestor
, descendant
, orSelf
, check
, checkNode
, checkElement
, checkName
, anyElement
, element
, laxElement
, content
, attribute
, laxAttribute
, hasAttribute
, attributeIs
, (CG.&|)
, (CG.&/)
, (CG.&//)
, (CG.&.//)
, (CG.$|)
, (CG.$/)
, (CG.$//)
, (CG.$.//)
, (CG.>=>)
, Boolean(..)
, force
, forceM
) where
import Control.Exception (Exception)
import Control.Monad
import Control.Monad.Trans.Resource (MonadThrow, throwM)
import Data.Function (on)
import qualified Data.Map as Map
import Data.Maybe (maybeToList)
import qualified Data.Text as T
import Text.XML
import Text.XML.Cursor.Generic (child, descendant, node, orSelf,
parent)
import qualified Text.XML.Cursor.Generic as CG
type Axis = Cursor -> [Cursor]
class Boolean a where
bool :: a -> Bool
instance Boolean Bool where
bool :: Bool -> Bool
bool = forall a. a -> a
id
instance Boolean [a] where
bool :: [a] -> Bool
bool = Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a. Foldable t => t a -> Bool
null
instance Boolean (Maybe a) where
bool :: Maybe a -> Bool
bool (Just a
_) = Bool
True
bool Maybe a
_ = Bool
False
instance Boolean (Either a b) where
bool :: Either a b -> Bool
bool (Left a
_) = Bool
False
bool (Right b
_) = Bool
True
type Cursor = CG.Cursor Node
cut :: Cursor -> Cursor
cut :: Cursor -> Cursor
cut = Node -> Cursor
fromNode forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall node. Cursor node -> node
CG.node
fromDocument :: Document -> Cursor
fromDocument :: Document -> Cursor
fromDocument = Node -> Cursor
fromNode forall b c a. (b -> c) -> (a -> b) -> a -> c
. Element -> Node
NodeElement forall b c a. (b -> c) -> (a -> b) -> a -> c
. Document -> Element
documentRoot
fromNode :: Node -> Cursor
fromNode :: Node -> Cursor
fromNode =
forall node. (node -> [node]) -> node -> Cursor node
CG.toCursor Node -> [Node]
cs
where
cs :: Node -> [Node]
cs (NodeElement (Element Name
_ Map Name Text
_ [Node]
x)) = [Node]
x
cs Node
_ = []
check :: Boolean b => (Cursor -> b) -> Axis
check :: forall b. Boolean b => (Cursor -> b) -> Axis
check Cursor -> b
f Cursor
c = [Cursor
c | forall a. Boolean a => a -> Bool
bool forall a b. (a -> b) -> a -> b
$ Cursor -> b
f Cursor
c]
checkNode :: Boolean b => (Node -> b) -> Axis
checkNode :: forall b. Boolean b => (Node -> b) -> Axis
checkNode Node -> b
f = forall b. Boolean b => (Cursor -> b) -> Axis
check (Node -> b
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall node. Cursor node -> node
node)
checkElement :: Boolean b => (Element -> b) -> Axis
checkElement :: forall b. Boolean b => (Element -> b) -> Axis
checkElement Element -> b
f Cursor
c = case forall node. Cursor node -> node
node Cursor
c of
NodeElement Element
e -> [Cursor
c | forall a. Boolean a => a -> Bool
bool forall a b. (a -> b) -> a -> b
$ Element -> b
f Element
e]
Node
_ -> []
checkName :: Boolean b => (Name -> b) -> Axis
checkName :: forall b. Boolean b => (Name -> b) -> Axis
checkName Name -> b
f = forall b. Boolean b => (Element -> b) -> Axis
checkElement (Name -> b
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. Element -> Name
elementName)
anyElement :: Axis
anyElement :: Axis
anyElement = forall b. Boolean b => (Element -> b) -> Axis
checkElement (forall a b. a -> b -> a
const Bool
True)
element :: Name -> Axis
element :: Name -> Axis
element Name
n = forall b. Boolean b => (Name -> b) -> Axis
checkName (forall a. Eq a => a -> a -> Bool
== Name
n)
laxElement :: T.Text -> Axis
laxElement :: Text -> Axis
laxElement Text
n = forall b. Boolean b => (Name -> b) -> Axis
checkName (forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
on forall a. Eq a => a -> a -> Bool
(==) Text -> Text
T.toCaseFold Text
n forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> Text
nameLocalName)
content :: Cursor -> [T.Text]
content :: Cursor -> [Text]
content Cursor
c = case forall node. Cursor node -> node
node Cursor
c of
(NodeContent Text
v) -> [Text
v]
Node
_ -> []
attribute :: Name -> Cursor -> [T.Text]
attribute :: Name -> Cursor -> [Text]
attribute Name
n Cursor
c =
case forall node. Cursor node -> node
node Cursor
c of
NodeElement Element
e -> forall a. Maybe a -> [a]
maybeToList forall a b. (a -> b) -> a -> b
$ forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Name
n forall a b. (a -> b) -> a -> b
$ Element -> Map Name Text
elementAttributes Element
e
Node
_ -> []
laxAttribute :: T.Text -> Cursor -> [T.Text]
laxAttribute :: Text -> Cursor -> [Text]
laxAttribute Text
n Cursor
c =
case forall node. Cursor node -> node
node Cursor
c of
NodeElement Element
e -> do
(Name
n', Text
v) <- forall k a. Map k a -> [(k, a)]
Map.toList forall a b. (a -> b) -> a -> b
$ Element -> Map Name Text
elementAttributes Element
e
forall (f :: * -> *). Alternative f => Bool -> f ()
guard forall a b. (a -> b) -> a -> b
$ (forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
on forall a. Eq a => a -> a -> Bool
(==) Text -> Text
T.toCaseFold) Text
n (Name -> Text
nameLocalName Name
n')
forall (m :: * -> *) a. Monad m => a -> m a
return Text
v
Node
_ -> []
hasAttribute :: Name -> Axis
hasAttribute :: Name -> Axis
hasAttribute Name
n Cursor
c =
case forall node. Cursor node -> node
node Cursor
c of
NodeElement (Element Name
_ Map Name Text
as [Node]
_) -> forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (forall a b. a -> b -> a
const [Cursor
c]) forall a b. (a -> b) -> a -> b
$ forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Name
n Map Name Text
as
Node
_ -> []
attributeIs :: Name -> T.Text -> Axis
attributeIs :: Name -> Text -> Axis
attributeIs Name
n Text
v Cursor
c =
case forall node. Cursor node -> node
node Cursor
c of
NodeElement (Element Name
_ Map Name Text
as [Node]
_) -> [ Cursor
c | forall a. a -> Maybe a
Just Text
v forall a. Eq a => a -> a -> Bool
== forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Name
n Map Name Text
as]
Node
_ -> []
force :: (Exception e, MonadThrow f) => e -> [a] -> f a
force :: forall e (f :: * -> *) a.
(Exception e, MonadThrow f) =>
e -> [a] -> f a
force e
e [] = forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM e
e
force e
_ (a
x:[a]
_) = forall (m :: * -> *) a. Monad m => a -> m a
return a
x
forceM :: (Exception e, MonadThrow f) => e -> [f a] -> f a
forceM :: forall e (f :: * -> *) a.
(Exception e, MonadThrow f) =>
e -> [f a] -> f a
forceM e
e [] = forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM e
e
forceM e
_ (f a
x:[f a]
_) = f a
x