module Text.XML.Pugi
(
Document_, Document, MutableDocument
, D.ParseConfig(..), D.ParseException(..)
, parse, D.parseFile
, D.PrettyConfig(..)
, D.prettyFile, pretty
, Node_, Node, MutableNode
, NodeKind(..)
, HasName, HasValue, HasAttribute, HasChildren
, M, NodeLike(..)
, Modify
, create, modify
, MutableNodeLike(..)
, appendAttrs
, setOrAppendAttr
, appendElement, prependElement
, appendDeclaration, prependDeclaration
, appendPCData, prependPCData
, appendCData, prependCData
, appendComment, prependComment
, appendDoctype, prependDoctype
, appendPi, prependPi
, XPath
, X.EvalXPath
, X.xpath
, NodeSet, XPathNode, Attribute
, X.nodeSetSize
, nodeSetIndex
, X.nodeSetMapM, X.nodeSetMapM_, nodeSetMap, nodeSetToList
, module Text.XML.Pugi.Const
, def
) where
import Control.Applicative
import Control.Monad
import Foreign.C.Types
import Text.XML.Pugi.Const
import Text.XML.Pugi.Foreign.Types
import qualified Text.XML.Pugi.Foreign.Document as D
import qualified Text.XML.Pugi.Foreign.Node as N
import qualified Text.XML.Pugi.Foreign.XPath as X
import qualified Text.XML.Pugi.Foreign.XPath.Node as X
import qualified Data.ByteString as S
import qualified Data.ByteString.Lazy as L
import qualified Data.ByteString.Lazy.Char8 as L8
import Data.Default.Class
import System.IO.Unsafe
import Unsafe.Coerce
parse :: D.ParseConfig -> S.ByteString
-> Either D.ParseException Document
parse cfg str = unsafePerformIO $ D.parse cfg str
pretty :: D.PrettyConfig -> Document -> L.ByteString
pretty cfg doc = unsafeDupablePerformIO $ D.pretty cfg doc
instance Show (Node_ k Immutable) where
show = ("Node " ++) . L8.unpack . prettyNode def {D.prettyFlags = formatRaw} 0
instance Show (Document_ k Immutable) where
show = ("Document " ++) . L8.unpack . prettyNode def {D.prettyFlags = formatRaw} 0
instance Eq (Node_ k Immutable) where
(==) = nodeEqual
instance Eq (Document_ k Immutable) where
(==) = nodeEqual
type family M (m :: MutableFlag) a
type instance M Immutable a = a
type instance M Mutable a = Modify a
class NodeLike n m where
asNode :: n k m -> M m (Node_ k m)
nodeEqual :: n k m -> n l o -> M m Bool
forgetNodeKind :: n k m -> n Unknown m
forgetNodeKind = unsafeCoerce
prettyNode :: D.PrettyConfig -> Int -> n k m -> M m L.ByteString
hashValue :: n k m -> M m CSize
nodeType :: n k m -> M m NodeType
getName :: HasName k => n k m -> M m S.ByteString
getValue :: HasValue k => n k m -> M m S.ByteString
parent :: n k m -> M m (Maybe (Node_ Unknown m))
firstChild :: HasChildren k => n k m -> M m (Maybe (Node_ Unknown m))
lastChild :: HasChildren k => n k m -> M m (Maybe (Node_ Unknown m))
nextSibling :: n k m -> M m (Maybe (Node_ Unknown m))
prevSibling :: n k m -> M m (Maybe (Node_ Unknown m))
child :: HasChildren k => S.ByteString -> n k m -> M m (Maybe (Node_ Unknown m))
attribute :: HasAttribute k => S.ByteString -> n k m -> M m (Maybe S.ByteString)
nextSiblingByName :: S.ByteString -> n k m -> M m (Maybe (Node_ Unknown m))
prevSiblingByName :: S.ByteString -> n k m -> M m (Maybe (Node_ Unknown m))
findChildByNameAndAttr :: HasChildren k
=> S.ByteString
-> S.ByteString
-> S.ByteString
-> n k m -> M m (Maybe (Node_ Unknown m))
findChildByAttr :: HasChildren k
=> S.ByteString
-> S.ByteString
-> n k m -> M m (Maybe (Node_ Unknown m))
childValue :: HasChildren k => n k m -> M m S.ByteString
childValueByName :: HasChildren k => S.ByteString -> n k m -> M m S.ByteString
text :: n k m -> M m S.ByteString
findAttribute :: (S.ByteString -> S.ByteString -> Bool) -> n k m -> M m (Maybe Attribute)
findChild :: (Node -> Bool) -> n k m -> M m (Maybe (Node_ Unknown m))
findNode :: (Node -> Bool) -> n k m -> M m (Maybe (Node_ Unknown m))
mapSibling :: (Node_ Unknown m -> a) -> n k m -> M m [a]
mapAttrs :: HasAttribute k => (S.ByteString -> S.ByteString -> a) -> n k m -> M m [a]
path :: Char -> n k m -> M m S.ByteString
firstElementByPath :: Char -> S.ByteString -> n k m -> M m (Maybe (Node_ Unknown m))
root :: n k m -> M m (Maybe (Node_ Unknown m))
evaluate :: X.EvalXPath r => XPath r -> n k m -> M m r
selectSingleNode :: XPath (NodeSet m) -> n k m -> M m (XPathNode m)
selectNodes :: XPath (NodeSet m) -> n k m -> M m (NodeSet m)
instance NodeLike Document_ Immutable where
asNode = unsafeDupablePerformIO . N.asNode
nodeEqual a = unsafeDupablePerformIO . N.nodeEqual a
prettyNode cfg dph = unsafeDupablePerformIO . N.prettyNode cfg dph
hashValue = unsafeDupablePerformIO . N.hashValue
nodeType = unsafeDupablePerformIO . N.nodeType
getName = unsafeDupablePerformIO . N.getName
getValue = unsafeDupablePerformIO . N.getValue
parent = unsafeDupablePerformIO . N.parent
firstChild = unsafeDupablePerformIO . N.firstChild
lastChild = unsafeDupablePerformIO . N.lastChild
nextSibling = unsafeDupablePerformIO . N.nextSibling
prevSibling = unsafeDupablePerformIO . N.prevSibling
child n = unsafeDupablePerformIO . N.child n
attribute n = unsafeDupablePerformIO . N.attribute n
nextSiblingByName n = unsafeDupablePerformIO . N.nextSiblingByName n
prevSiblingByName n = unsafeDupablePerformIO . N.prevSiblingByName n
findChildByNameAndAttr nn an av =
unsafeDupablePerformIO . N.findChildByNameAndAttr nn an av
findChildByAttr an av = unsafeDupablePerformIO . N.findChildByAttr an av
childValue = unsafeDupablePerformIO . N.childValue
childValueByName n = unsafeDupablePerformIO . N.childValueByName n
text = unsafeDupablePerformIO . N.text
findAttribute f = unsafeDupablePerformIO . N.findAttribute f
findChild f = unsafeDupablePerformIO . N.findChild f
findNode f = unsafeDupablePerformIO . N.findNode f
mapSibling f = unsafeDupablePerformIO . N.mapSiblingM (return . f)
mapAttrs f = unsafeDupablePerformIO . N.mapAttrsM (\k v -> return $ f k v)
path c = unsafeDupablePerformIO . N.path c
firstElementByPath c p = unsafeDupablePerformIO . N.firstElementByPath c p
root = unsafeDupablePerformIO . N.root
evaluate x = unsafeDupablePerformIO . X.evaluateXPath x
selectSingleNode x = unsafeDupablePerformIO . N.selectSingleNode x
selectNodes x = unsafeDupablePerformIO . N.selectNodes x
instance NodeLike Node_ Immutable where
asNode = unsafeDupablePerformIO . N.asNode
nodeEqual a = unsafeDupablePerformIO . N.nodeEqual a
prettyNode cfg dph = unsafeDupablePerformIO . N.prettyNode cfg dph
hashValue = unsafeDupablePerformIO . N.hashValue
nodeType = unsafeDupablePerformIO . N.nodeType
getName = unsafeDupablePerformIO . N.getName
getValue = unsafeDupablePerformIO . N.getValue
parent = unsafeDupablePerformIO . N.parent
firstChild = unsafeDupablePerformIO . N.firstChild
lastChild = unsafeDupablePerformIO . N.lastChild
nextSibling = unsafeDupablePerformIO . N.nextSibling
prevSibling = unsafeDupablePerformIO . N.prevSibling
child n = unsafeDupablePerformIO . N.child n
attribute n = unsafeDupablePerformIO . N.attribute n
nextSiblingByName n = unsafeDupablePerformIO . N.nextSiblingByName n
prevSiblingByName n = unsafeDupablePerformIO . N.prevSiblingByName n
findChildByNameAndAttr nn an av =
unsafeDupablePerformIO . N.findChildByNameAndAttr nn an av
findChildByAttr an av = unsafeDupablePerformIO . N.findChildByAttr an av
childValue = unsafeDupablePerformIO . N.childValue
childValueByName n = unsafeDupablePerformIO . N.childValueByName n
text = unsafeDupablePerformIO . N.text
findAttribute f = unsafeDupablePerformIO . N.findAttribute f
findChild f = unsafeDupablePerformIO . N.findChild f
findNode f = unsafeDupablePerformIO . N.findNode f
mapSibling f = unsafeDupablePerformIO . N.mapSiblingM (return . f)
mapAttrs f = unsafeDupablePerformIO . N.mapAttrsM (\k v -> return $ f k v)
path c = unsafeDupablePerformIO . N.path c
firstElementByPath c p = unsafeDupablePerformIO . N.firstElementByPath c p
root = unsafeDupablePerformIO . N.root
evaluate x = unsafeDupablePerformIO . X.evaluateXPath x
selectSingleNode x = unsafeDupablePerformIO . N.selectSingleNode x
selectNodes x = unsafeDupablePerformIO . N.selectNodes x
instance NodeLike Document_ Mutable where
asNode = Modify . fmap Right . N.asNode
nodeEqual a = Modify . fmap Right . N.nodeEqual a
prettyNode cfg dph = Modify . fmap Right . N.prettyNode cfg dph
hashValue = Modify . fmap Right . N.hashValue
nodeType = Modify . fmap Right . N.nodeType
getName = Modify . fmap Right . N.getName
getValue = Modify . fmap Right . N.getValue
parent = Modify . fmap Right . N.parent
firstChild = Modify . fmap Right . N.firstChild
lastChild = Modify . fmap Right . N.lastChild
nextSibling = Modify . fmap Right . N.nextSibling
prevSibling = Modify . fmap Right . N.prevSibling
child n = Modify . fmap Right . N.child n
attribute n = Modify . fmap Right . N.attribute n
nextSiblingByName n = Modify . fmap Right . N.nextSiblingByName n
prevSiblingByName n = Modify . fmap Right . N.prevSiblingByName n
findChildByNameAndAttr nn an av =
Modify . fmap Right . N.findChildByNameAndAttr nn an av
findChildByAttr an av = Modify . fmap Right . N.findChildByAttr an av
childValue = Modify . fmap Right . N.childValue
childValueByName n = Modify . fmap Right . N.childValueByName n
text = Modify . fmap Right . N.text
findAttribute f = Modify . fmap Right . N.findAttribute f
findChild f = Modify . fmap Right . N.findChild f
findNode f = Modify . fmap Right . N.findNode f
mapSibling f = Modify . fmap Right . N.mapSiblingM (return . f)
mapAttrs f = Modify . fmap Right . N.mapAttrsM (\k v -> return $ f k v)
path c = Modify . fmap Right . N.path c
firstElementByPath c p = Modify . fmap Right . N.firstElementByPath c p
root = Modify . fmap Right . N.root
evaluate x = Modify . fmap Right . X.evaluateXPath x
selectSingleNode x = Modify . fmap Right . N.selectSingleNode x
selectNodes x = Modify . fmap Right . N.selectNodes x
instance NodeLike Node_ Mutable where
asNode = Modify . fmap Right . N.asNode
nodeEqual a = Modify . fmap Right . N.nodeEqual a
prettyNode cfg dph = Modify . fmap Right . N.prettyNode cfg dph
hashValue = Modify . fmap Right . N.hashValue
nodeType = Modify . fmap Right . N.nodeType
getName = Modify . fmap Right . N.getName
getValue = Modify . fmap Right . N.getValue
parent = Modify . fmap Right . N.parent
firstChild = Modify . fmap Right . N.firstChild
lastChild = Modify . fmap Right . N.lastChild
nextSibling = Modify . fmap Right . N.nextSibling
prevSibling = Modify . fmap Right . N.prevSibling
child n = Modify . fmap Right . N.child n
attribute n = Modify . fmap Right . N.attribute n
nextSiblingByName n = Modify . fmap Right . N.nextSiblingByName n
prevSiblingByName n = Modify . fmap Right . N.prevSiblingByName n
findChildByNameAndAttr nn an av =
Modify . fmap Right . N.findChildByNameAndAttr nn an av
findChildByAttr an av = Modify . fmap Right . N.findChildByAttr an av
childValue = Modify . fmap Right . N.childValue
childValueByName n = Modify . fmap Right . N.childValueByName n
text = Modify . fmap Right . N.text
findAttribute f = Modify . fmap Right . N.findAttribute f
findChild f = Modify . fmap Right . N.findChild f
findNode f = Modify . fmap Right . N.findNode f
mapSibling f = Modify . fmap Right . N.mapSiblingM (return . f)
mapAttrs f = Modify . fmap Right . N.mapAttrsM (\k v -> return $ f k v)
path c = Modify . fmap Right . N.path c
firstElementByPath c p = Modify . fmap Right . N.firstElementByPath c p
root = Modify . fmap Right . N.root
evaluate x = Modify . fmap Right . X.evaluateXPath x
selectSingleNode x = Modify . fmap Right . N.selectSingleNode x
selectNodes x = Modify . fmap Right . N.selectNodes x
newtype Modify a = Modify { runModify :: IO (Either String a) }
deriving Functor
instance Applicative Modify where
pure = Modify . return . Right
mf <*> ma = Modify $ runModify mf >>= \case
Left e -> return (Left e)
Right f -> runModify ma >>= \case
Left e -> return (Left e)
Right a -> return (Right (f a))
instance Monad Modify where
return = pure
ma >>= g = Modify $ runModify ma >>= \case
Left e -> return (Left e)
Right a -> runModify $ g a
fail = Modify . return . Left
instance Alternative Modify where
empty = Modify . return $ Left "empty"
ma <|> mb = Modify $ runModify ma >>= \case
Left _ -> runModify mb
Right a -> return $ Right a
instance MonadPlus Modify where
mzero = empty
mplus = (<|>)
mLiftIO :: IO a -> Modify a
mLiftIO io = Modify $ Right <$> io
create :: Monad m => (MutableDocument -> Modify ()) -> m Document
create m = either fail (return . D.freezeDocument) . unsafeDupablePerformIO . runModify $ do
d <- mLiftIO D.createDocument
m d
return d
modify :: Monad m => Document -> (MutableDocument -> Modify ()) -> m Document
modify prt m = either fail (return . D.freezeDocument) . unsafePerformIO . runModify $ do
d <- mLiftIO $ D.copyDocument prt
m d
return d
appendElement :: (HasChildren k, MutableNodeLike n)
=> S.ByteString -> n k Mutable -> Modify (MutableNode Element)
appendElement n e = appendChild nodeTypeElement e >>= \r -> setName n r >> return r
prependElement :: (HasChildren k, MutableNodeLike n)
=> S.ByteString -> n k Mutable -> Modify (MutableNode Element)
prependElement n e = prependChild nodeTypeElement e >>= \r -> setName n r >> return r
appendDeclaration :: (HasChildren k, MutableNodeLike n)
=> S.ByteString -> n k Mutable -> Modify (MutableNode Declaration)
appendDeclaration n e = appendChild nodeTypeDeclaration e >>= \r -> setName n r >> return r
prependDeclaration :: (HasChildren k, MutableNodeLike n)
=> S.ByteString -> n k Mutable -> Modify (MutableNode Declaration)
prependDeclaration n e = prependChild nodeTypeDeclaration e >>= \r -> setName n r >> return r
appendPCData :: (HasChildren k, MutableNodeLike n)
=> S.ByteString -> n k Mutable -> Modify (MutableNode PCData)
appendPCData n e = appendChild nodeTypePCData e >>= \r -> setValue n r >> return r
prependPCData :: (HasChildren k, MutableNodeLike n)
=> S.ByteString -> n k Mutable -> Modify (MutableNode PCData)
prependPCData n e = prependChild nodeTypePCData e >>= \r -> setValue n r >> return r
appendCData :: (HasChildren k, MutableNodeLike n)
=> S.ByteString -> n k Mutable -> Modify (MutableNode CData)
appendCData n e = appendChild nodeTypeCData e >>= \r -> setValue n r >> return r
prependCData :: (HasChildren k, MutableNodeLike n)
=> S.ByteString -> n k Mutable -> Modify (MutableNode CData)
prependCData n e = prependChild nodeTypeCData e >>= \r -> setValue n r >> return r
appendComment :: (HasChildren k, MutableNodeLike n)
=> S.ByteString -> n k Mutable -> Modify (MutableNode Comment)
appendComment n e = appendChild nodeTypeComment e >>= \r -> setValue n r >> return r
prependComment :: (HasChildren k, MutableNodeLike n)
=> S.ByteString -> n k Mutable -> Modify (MutableNode Comment)
prependComment n e = prependChild nodeTypeComment e >>= \r -> setValue n r >> return r
appendDoctype :: (HasChildren k, MutableNodeLike n)
=> S.ByteString -> n k Mutable -> Modify (MutableNode Doctype)
appendDoctype n e = appendChild nodeTypeDoctype e >>= \r -> setValue n r >> return r
prependDoctype :: (HasChildren k, MutableNodeLike n)
=> S.ByteString -> n k Mutable -> Modify (MutableNode Doctype)
prependDoctype n e = prependChild nodeTypeDoctype e >>= \r -> setValue n r >> return r
appendPi :: (HasChildren k, MutableNodeLike n)
=> S.ByteString -> S.ByteString -> n k Mutable -> Modify (MutableNode Pi)
appendPi n v e = appendChild nodeTypePi e >>= \r -> setName n r >> setValue v r >> return r
prependPi :: (HasChildren k, MutableNodeLike n)
=> S.ByteString -> S.ByteString -> n k Mutable -> Modify (MutableNode Pi)
prependPi n v e = prependChild nodeTypePi e >>= \r -> setName n r >> setValue v r >> return r
class HasName (k :: NodeKind)
instance HasName Element
instance HasName Declaration
instance HasName Pi
instance HasName Unknown
class HasValue (k :: NodeKind)
instance HasValue PCData
instance HasValue CData
instance HasValue Comment
instance HasValue Doctype
instance HasValue Pi
instance HasValue Unknown
class HasAttribute (k :: NodeKind)
instance HasAttribute Element
instance HasAttribute Declaration
instance HasAttribute Unknown
class HasChildren (k :: NodeKind)
instance HasChildren Element
instance HasChildren Unknown
class MutableNodeLike (n :: NodeKind -> MutableFlag -> *) where
setName :: HasName k => S.ByteString -> n k Mutable -> Modify ()
setValue :: HasValue k => S.ByteString -> n k Mutable -> Modify ()
appendAttr :: HasAttribute k => S.ByteString -> S.ByteString -> n k Mutable -> Modify ()
prependAttr :: HasAttribute k => S.ByteString -> S.ByteString -> n k Mutable -> Modify ()
setAttr :: HasAttribute k => S.ByteString -> S.ByteString -> n k Mutable -> Modify ()
appendChild :: HasChildren k => NodeType -> n k Mutable -> Modify (MutableNode l)
prependChild :: HasChildren k => NodeType -> n k Mutable -> Modify (MutableNode l)
appendCopy :: HasChildren k => Node_ k a -> n l Mutable -> Modify (MutableNode k)
prependCopy :: HasChildren k => Node_ k a -> n l Mutable -> Modify (MutableNode k)
removeAttr :: HasAttribute k => S.ByteString -> n k Mutable -> Modify ()
removeChild :: HasChildren k => Node_ k a -> n l Mutable -> Modify ()
appendFlagment :: HasChildren k => D.ParseConfig -> S.ByteString -> n k Mutable -> Modify ()
appendAttrs :: (MutableNodeLike n, HasAttribute k) => [Attribute] -> n k Mutable -> Modify ()
appendAttrs as n = mapM_ (\(k,v) -> appendAttr k v n) as
instance MutableNodeLike Node_ where
setName = isetName
setValue = isetValue
appendAttr = iappendAttr
prependAttr = iprependAttr
setAttr = isetAttr
appendChild = iappendChild
prependChild = iprependChild
appendCopy = iappendCopy
prependCopy = iprependCopy
removeAttr = iremoveAttr
removeChild = iremoveChild
appendFlagment = iappendFlagment
instance MutableNodeLike Document_ where
setName = isetName
setValue = isetValue
appendAttr = iappendAttr
prependAttr = iprependAttr
setAttr = isetAttr
appendChild = iappendChild
prependChild = iprependChild
appendCopy = iappendCopy
prependCopy = iprependCopy
removeAttr = iremoveAttr
removeChild = iremoveChild
appendFlagment = iappendFlagment
setOrAppendAttr :: (HasAttribute k, MutableNodeLike n)
=> S.ByteString -> S.ByteString -> n k Mutable -> Modify ()
setOrAppendAttr k v n = setAttr k v n <|> appendAttr k v n
isetName :: N.NodeLike n => S.ByteString -> n k Mutable -> Modify ()
isetName n nd = mLiftIO (N.setName n nd) >>=
flip unless (fail $ "setName: " ++ show n)
isetValue :: N.NodeLike n => S.ByteString -> n k Mutable -> Modify ()
isetValue n nd = mLiftIO (N.setValue n nd) >>=
flip unless (fail $ "setValue: " ++ show n)
iappendAttr :: N.NodeLike n => S.ByteString -> S.ByteString
-> n k Mutable -> Modify ()
iappendAttr k v n = mLiftIO (N.appendAttr k v n) >>=
flip unless (fail $ "appendAttr: " ++ show k ++ " = " ++ show v)
iprependAttr :: N.NodeLike n => S.ByteString -> S.ByteString
-> n k Mutable -> Modify ()
iprependAttr k v n = mLiftIO (N.prependAttr k v n) >>=
flip unless (fail $ "appendAttr: " ++ show k ++ " = " ++ show v)
isetAttr :: N.NodeLike n => S.ByteString -> S.ByteString
-> n k Mutable -> Modify ()
isetAttr k v n = mLiftIO (N.setAttr k v n) >>=
flip unless (fail $ "setAttr: " ++ show k ++ " = " ++ show v)
iappendChild :: N.NodeLike n => NodeType -> n l Mutable -> Modify (MutableNode k)
iappendChild t n = mLiftIO (N.appendChild t n) >>=
maybe (fail $ "appendChild: " ++ show t) return
iprependChild :: N.NodeLike n => NodeType -> n l Mutable -> Modify (MutableNode k)
iprependChild t n = mLiftIO (N.prependChild t n) >>=
maybe (fail $ "prependChild: " ++ show t) return
iappendCopy :: N.NodeLike n => Node_ k a -> n l Mutable -> Modify (MutableNode k)
iappendCopy t n = mLiftIO (N.appendCopy t n) >>=
maybe (fail "appendCopy") return
iprependCopy :: N.NodeLike n => Node_ k a -> n l Mutable -> Modify (MutableNode k)
iprependCopy t n = mLiftIO (N.prependCopy t n) >>=
maybe (fail "prependCopy") return
iremoveAttr :: N.NodeLike n => S.ByteString -> n k Mutable -> Modify ()
iremoveAttr n nd = mLiftIO (N.removeAttr n nd) >>=
flip unless (fail $ "removeAttr: " ++ show n)
iremoveChild :: N.NodeLike n => Node_ l a -> n k Mutable -> Modify ()
iremoveChild n nd = mLiftIO (N.removeChild n nd) >>=
flip unless (fail "removeChild")
iappendFlagment :: N.NodeLike n => D.ParseConfig -> S.ByteString -> n k Mutable -> Modify ()
iappendFlagment cfg str n = mLiftIO (N.appendBuffer cfg str n) >>=
flip unless (fail $ "appendFlagment: " ++ show str)
nodeSetIndex :: NodeSet m -> Int -> XPathNode m
nodeSetIndex n = unsafeDupablePerformIO . X.nodeSetIndex n
nodeSetMap :: (XPathNode m -> a) -> NodeSet m -> [a]
nodeSetMap f = unsafeDupablePerformIO . X.nodeSetMapM (return . f)
nodeSetToList :: NodeSet m -> [XPathNode m]
nodeSetToList = nodeSetMap id