{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE CPP #-}
-- | parse xml
--
-- @
-- \> docA <- parse def \"\\"
-- \> docA
-- Right Document \
--
-- \> parseFile def \"test.xml\"
-- Document \
-- @
--
-- render xml
--
-- @
-- \> Data.ByteString.Lazy.Char.putStrLn $ either undefined (pretty def) docA
-- \
-- \
--
-- \> prettyFile def docA
-- @
--
-- create xml
--
-- @
-- testHtml :: IO 'Document'
-- testHtml = 'create' $ \doc -\> do
-- decl <- 'appendDeclaration' \"xml\" doc
-- 'appendAttrs' [(\"version\", \"1.0\"), (\"lang\", \"ja\")] decl
--
-- 'appendDoctype' \"html\" doc
--
-- html <- 'appendElement' \"html\" doc
-- body <- appendElement \"body\" html
-- div_ <- appendElement \"div\" body
-- a <- appendElement \"a\" div_
-- 'appendAttr' \"href\" \"http:\/\/example.com\" a
-- txt <- 'appendPCData' \"example.com\" a
-- return ()
-- @
--
-- @
-- -- testHtml for copy&paste to ghci.
-- \> doc \<- create $ \\doc -\> appendDeclaration \"xml\" doc >>= \\decl -\> appendAttrs [(\"version\", \"1.0\"), (\"lang\", \"ja\")] decl >> appendDoctype \"html\" doc >> appendElement \"html\" doc >>= \\html -\> appendElement \"body\" html >>= \\body -\> appendElement \"div\" body >>= \\div_ -\> appendElement \"a\" div_ >>= \\a -\> appendAttr \"href\" \"http:\/\/example.com\" a >> appendPCData \"example.com\" a >> return ()
--
-- \> doc
-- Document \\\\\\
example.com\<\/a\>\<\/div\>\<\/body\>\<\/html\>
-- @
--
-- access xml tree
--
-- @
-- \> let Just x = 'child' \"xml\" doc
-- \> x
-- Node \
--
-- \> 'nextSibling' x
-- Just Node \
--
-- \> Just html = 'nextSiblingByName' "html" x
--
-- \> html
-- Node \\\\
example.com\<\/a\>\<\/div\>\<\/body\>\<\/html\>
--
-- \> 'evaluate' [xpath|string(\/\/a\/@href)|] html
-- \"http:\/\/example.com\"
--
-- \> let ns = evaluate [xpath|\/\/a\/@href|] html
--
-- \> 'nodeSetSize' ns
-- 1
-- \> 'nodeSetIndex' ns 0
-- Right (\"href\",\"http:\/\/example.com\")
-- @
--
-- modify xml
--
-- @
-- modify doc $ \\d -\> 'selectSingleNode' [xpath|\/\/a|] d >>= \\(Left a) -\> setOrAppendAttr \"href\" \"#\" a
-- Document \\\\\\
example.com\<\/a\>\<\/div\>\<\/body\>\<\/html\>
-- @
--
module Text.XML.Pugi
( -- * Document
Document_, Document, MutableDocument
-- ** parse
, D.ParseConfig(..), D.ParseException(..)
, parse, D.parseFile
-- ** render
, D.PrettyConfig(..)
, D.prettyFile, pretty
-- * Node
, Node_, Node, MutableNode
, NodeKind(..)
, HasName, HasValue, HasAttribute, HasChildren
-- ** getter
, M, NodeLike(..)
-- ** setter
, Modify
, create, modify
, MutableNodeLike(..)
, appendAttrs
, setOrAppendAttr
-- *** specified append/prepend child
, appendElement, prependElement
, appendDeclaration, prependDeclaration
, appendPCData, prependPCData
, appendCData, prependCData
, appendComment, prependComment
, appendDoctype, prependDoctype
, appendPi, prependPi
-- * XPath
, XPath
, X.EvalXPath
, X.xpath
-- ** NodeSet
, NodeSet, XPathNode, Attribute
, X.nodeSetSize
, nodeSetIndex
, X.nodeSetMapM, X.nodeSetMapM_, nodeSetMap, nodeSetToList
-- * reexport
, 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 = unsafeDupablePerformIO $ D.parse cfg str
pretty :: D.PrettyConfig -> Document -> L.ByteString
pretty cfg doc = unsafeDupablePerformIO $ D.pretty cfg doc
instance Show Node where
show = ("Node " ++) . L8.unpack . prettyNode def {D.prettyFlags = formatRaw} 0
instance Show Document where
show = ("Document " ++) . L8.unpack . prettyNode def {D.prettyFlags = formatRaw} 0
-- |
-- @
-- M Immutable a = a
-- M Mutable a = 'Modify' a
-- @
--
type family M (m :: MutableFlag) a
type instance M Immutable a = a
type instance M Mutable a = Modify a
-- |
-- @
-- instance NodeLike 'Document_' Immutable
-- instance NodeLike 'Node_' Immutable
-- instance NodeLike 'Document_' Mutable
-- instance NodeLike 'Node_' Mutable
-- @
--
class NodeLike n m where
asNode :: n k m -> M m (Node_ k m)
forgetNodeKind :: n k m -> n Unknown m
forgetNodeKind = unsafeCoerce
{-# INLINE forgetNodeKind #-}
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 -- ^ node name
-> S.ByteString -- ^ attribute name
-> S.ByteString -- ^ attribute value
-> n k m -> M m (Maybe (Node_ Unknown m))
findChildByAttr :: HasChildren k
=> S.ByteString -- ^ attribute name
-> S.ByteString -- ^ attribute value
-> 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
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
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
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
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
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
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
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
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
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 document from scratch.
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 document.
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 ()
-- | generic appendChild method. Recommend to use 'appendElement' etc...
appendChild :: HasChildren k => NodeType -> n k Mutable -> Modify (MutableNode l)
-- | generic prependChild method. Recommend to use 'prependElement' etc...
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