    -- |A set of useful helper functions for dealing with XML data.
    module Text.XML.Light.Helpers
     where

    import Control.Monad
    import Data.Maybe
    import Text.XML.Light

    -- |Map the given function over the children of the given element with the
    -- given name.
    mapChildren :: String -> Element -> (Element -> Maybe a) -> Maybe [a]
    mapChildren :: forall a. String -> Element -> (Element -> Maybe a) -> Maybe [a]
    mapChildren String
    s Element
    e Element -> Maybe a
    f = [Maybe a] -> Maybe [a]
    forall (t :: * -> *) (m :: * -> *) a.
    (Traversable t, Monad m) =>
    t (m a) -> m (t a)
    forall (m :: * -> *) a. Monad m => [m a] -> m [a]
    sequence ([Maybe a] -> Maybe [a]) -> [Maybe a] -> Maybe [a]
    forall a b. (a -> b) -> a -> b
    $ (Element -> Maybe a) -> [Element] -> [Maybe a]
    forall a b. (a -> b) -> [a] -> [b]
    map Element -> Maybe a
    f ([Element] -> [Maybe a]) -> [Element] -> [Maybe a]
    forall a b. (a -> b) -> a -> b
    $ QName -> Element -> [Element]
    findChildren (String -> QName
    unqual String
    s) Element
    e

    -- |Fold the function over the children of the given element with the given
    -- name.
    foldChildren :: String -> Element -> a -> (a -> Element -> Maybe a) -> Maybe a
    foldChildren :: forall a.
    String -> Element -> a -> (a -> Element -> Maybe a) -> Maybe a
    foldChildren String
    s Element
    e a
    b a -> Element -> Maybe a
    f = (a -> Element -> Maybe a) -> a -> [Element] -> Maybe a
    forall (t :: * -> *) (m :: * -> *) b a.
    (Foldable t, Monad m) =>
    (b -> a -> m b) -> b -> t a -> m b
    foldM a -> Element -> Maybe a
    f a
    b ([Element] -> Maybe a) -> [Element] -> Maybe a
    forall a b. (a -> b) -> a -> b
    $ QName -> Element -> [Element]
    findChildren (String -> QName
    unqual String
    s) Element
    e

    -- |Map the given function over all subelements of the given element with
    -- the given name.
    mapElements :: String -> Element -> (Element -> Maybe a) -> Maybe [a]
    mapElements :: forall a. String -> Element -> (Element -> Maybe a) -> Maybe [a]
    mapElements String
    s Element
    e Element -> Maybe a
    f = [Maybe a] -> Maybe [a]
    forall (t :: * -> *) (m :: * -> *) a.
    (Traversable t, Monad m) =>
    t (m a) -> m (t a)
    forall (m :: * -> *) a. Monad m => [m a] -> m [a]
    sequence ([Maybe a] -> Maybe [a]) -> [Maybe a] -> Maybe [a]
    forall a b. (a -> b) -> a -> b
    $ (Element -> Maybe a) -> [Element] -> [Maybe a]
    forall a b. (a -> b) -> [a] -> [b]
    map Element -> Maybe a
    f ([Element] -> [Maybe a]) -> [Element] -> [Maybe a]
    forall a b. (a -> b) -> a -> b
    $ QName -> Element -> [Element]
    findElements (String -> QName
    unqual String
    s) Element
    e

    -- |Fold the given function over the children of the given element with
    -- the given name.
    foldElements :: String -> Element -> a -> (a -> Element -> Maybe a) -> Maybe a
    foldElements :: forall a.
    String -> Element -> a -> (a -> Element -> Maybe a) -> Maybe a
    foldElements String
    s Element
    e a
    b a -> Element -> Maybe a
    f = (a -> Element -> Maybe a) -> a -> [Element] -> Maybe a
    forall (t :: * -> *) (m :: * -> *) b a.
    (Foldable t, Monad m) =>
    (b -> a -> m b) -> b -> t a -> m b
    foldM a -> Element -> Maybe a
    f a
    b ([Element] -> Maybe a) -> [Element] -> Maybe a
    forall a b. (a -> b) -> a -> b
    $ QName -> Element -> [Element]
    findElements (String -> QName
    unqual String
    s) Element
    e

    --

    -- |Map the given function over the children of the given element that
    -- have an attribute "name" matching the given string.
    mapChildrenWithAttName :: String -> Element -> (Element -> Maybe a) -> Maybe [a]
    mapChildrenWithAttName :: forall a. String -> Element -> (Element -> Maybe a) -> Maybe [a]
    mapChildrenWithAttName String
    s Element
    e Element -> Maybe a
    f = (Element -> Maybe a) -> [Element] -> Maybe [a]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM Element -> Maybe a
    f ([Element] -> Maybe [a]) -> [Element] -> Maybe [a]
    forall a b. (a -> b) -> a -> b
    $ String -> Element -> [Element]
    findChildrenWithAttName String
    s Element
    e

    -- |Map the given function over the subelements of the given element that
    -- have an attribute "name" matching the given string.
    mapElementsWithAttName :: String -> Element -> (Element -> Maybe a) -> Maybe [a]
    mapElementsWithAttName :: forall a. String -> Element -> (Element -> Maybe a) -> Maybe [a]
    mapElementsWithAttName String
    s Element
    e Element -> Maybe a
    f = (Element -> Maybe a) -> [Element] -> Maybe [a]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM Element -> Maybe a
    f ([Element] -> Maybe [a]) -> [Element] -> Maybe [a]
    forall a b. (a -> b) -> a -> b
    $ String -> Element -> [Element]
    findElementsWithAttName String
    s Element
    e

    -- |Fold the given function over the children of the given element that
    -- have an attribute "name" matching the given string.
    foldChildrenWithAttName :: String -> Element -> a ->
                               (a -> Element -> Maybe a) ->
                               Maybe a
    foldChildrenWithAttName :: forall a.
    String -> Element -> a -> (a -> Element -> Maybe a) -> Maybe a
    foldChildrenWithAttName String
    s Element
    e a
    b a -> Element -> Maybe a
    f = (a -> Element -> Maybe a) -> a -> [Element] -> Maybe a
    forall (t :: * -> *) (m :: * -> *) b a.
    (Foldable t, Monad m) =>
    (b -> a -> m b) -> b -> t a -> m b
    foldM a -> Element -> Maybe a
    f a
    b ([Element] -> Maybe a) -> [Element] -> Maybe a
    forall a b. (a -> b) -> a -> b
    $ String -> Element -> [Element]
    findChildrenWithAttName String
    s Element
    e

    -- |Fold the given function over the subelements of the given element that
    -- have an attribute "name" matching the given string.
    foldElementsWithAttName :: String -> Element -> a ->
                               (a -> Element -> Maybe a) ->
                               Maybe a
    foldElementsWithAttName :: forall a.
    String -> Element -> a -> (a -> Element -> Maybe a) -> Maybe a
    foldElementsWithAttName String
    s Element
    e a
    b a -> Element -> Maybe a
    f = (a -> Element -> Maybe a) -> a -> [Element] -> Maybe a
    forall (t :: * -> *) (m :: * -> *) b a.
    (Foldable t, Monad m) =>
    (b -> a -> m b) -> b -> t a -> m b
    foldM a -> Element -> Maybe a
    f a
    b ([Element] -> Maybe a) -> [Element] -> Maybe a
    forall a b. (a -> b) -> a -> b
    $ String -> Element -> [Element]
    findElementsWithAttName String
    s Element
    e

    --

    -- |Get the string contents of the child of the given element with the given
    -- name.
    getChildData :: String -> Element -> Maybe String
    getChildData :: String -> Element -> Maybe String
    getChildData String
    s Element
    x = Element -> String
    strContent (Element -> String) -> Maybe Element -> Maybe String
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    `fmap` QName -> Element -> Maybe Element
    findChild (String -> QName
    unqual String
    s) Element
    x

    -- |Get the string contents of the subelement of the given element with the
    -- given name.
    getElementData :: String -> Element -> Maybe String
    getElementData :: String -> Element -> Maybe String
    getElementData String
    s Element
    x = Element -> String
    strContent (Element -> String) -> Maybe Element -> Maybe String
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    `fmap` QName -> Element -> Maybe Element
    findElement (String -> QName
    unqual String
    s) Element
    x

    --

    -- |Find a child of the given element with that has an attribute "name"
    -- equal to the given string.
    findChildWithAttName :: String -> Element -> Maybe Element
    findChildWithAttName :: String -> Element -> Maybe Element
    findChildWithAttName String
    s = [Element] -> Maybe Element
    forall a. [a] -> Maybe a
    listToMaybe ([Element] -> Maybe Element)
    -> (Element -> [Element]) -> Element -> Maybe Element
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> Element -> [Element]
    findChildrenWithAttName String
    s

    -- |Find all the children of the given element that have an attribute "name"
    -- equal to the given string.
    findChildrenWithAttName :: String -> Element -> [Element]
    findChildrenWithAttName :: String -> Element -> [Element]
    findChildrenWithAttName String
    s = (Element -> Bool) -> Element -> [Element]
    filterChildren (String -> Element -> Bool
    elementHasNameAttr String
    s)

    -- |Find a subelement of the given element that has an attribute "name"
    -- equal to the given string.
    findElementWithAttName :: String -> Element -> Maybe Element
    findElementWithAttName :: String -> Element -> Maybe Element
    findElementWithAttName  String
    s = [Element] -> Maybe Element
    forall a. [a] -> Maybe a
    listToMaybe ([Element] -> Maybe Element)
    -> (Element -> [Element]) -> Element -> Maybe Element
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> Element -> [Element]
    findElementsWithAttName String
    s

    -- |Find all the subelements of the given element that have an attribute
    -- "name" equal to the given string.
    findElementsWithAttName :: String -> Element -> [Element]
    findElementsWithAttName :: String -> Element -> [Element]
    findElementsWithAttName String
    s = (Element -> Bool) -> Element -> [Element]
    filterElements (String -> Element -> Bool
    elementHasNameAttr String
    s)

    -- |Returns True iff the given alement has an attribute "name" equal to
    -- the given string.
    elementHasNameAttr :: String -> Element -> Bool
    elementHasNameAttr :: String -> Element -> Bool
    elementHasNameAttr String
    s Element
    e =
      case QName -> Element -> Maybe String
    findAttr (String -> QName
    unqual String
    "name") Element
    e of
        Maybe String
    Nothing -> Bool
    False
        Just String
    v  -> String
    s String -> String -> Bool
    forall a. Eq a => a -> a -> Bool
    == String
    v

    -- |Convert a list of rows (subelement with the name "row") into a Haskell
    -- datatype using the given function.s
    parseRows :: (Element -> Maybe a) -> Element -> Maybe [a]
    parseRows :: forall a. (Element -> Maybe a) -> Element -> Maybe [a]
    parseRows Element -> Maybe a
    f Element
    xml = [Maybe a] -> Maybe [a]
    forall (t :: * -> *) (m :: * -> *) a.
    (Traversable t, Monad m) =>
    t (m a) -> m (t a)
    forall (m :: * -> *) a. Monad m => [m a] -> m [a]
    sequence ([Maybe a] -> Maybe [a]) -> [Maybe a] -> Maybe [a]
    forall a b. (a -> b) -> a -> b
    $ (Element -> Maybe a) -> [Element] -> [Maybe a]
    forall a b. (a -> b) -> [a] -> [b]
    map Element -> Maybe a
    f ([Element] -> [Maybe a]) -> [Element] -> [Maybe a]
    forall a b. (a -> b) -> a -> b
    $ QName -> Element -> [Element]
    findElements (String -> QName
    unqual String
    "row") Element
    xml