{-# LANGUAGE FlexibleInstances #-}

-- | Compatibility interface between `xml` and `xml-types`.
module Data.XML.Compat where

import Prelude.Compat

import Data.Text (Text)
import qualified Data.Text as T
import Data.XML.Types

import Safe

type Attr = (Name, [Content])

mkAttr :: Text -> Text -> Attr
mkAttr :: Text -> Text -> Attr
mkAttr Text
k = Name -> Text -> Attr
mkNAttr (Text -> Maybe Text -> Maybe Text -> Name
Name Text
k Maybe Text
forall a. Maybe a
Nothing Maybe Text
forall a. Maybe a
Nothing)

mkNAttr :: Name -> Text -> Attr
mkNAttr :: Name -> Text -> Attr
mkNAttr Name
k Text
v = (Name
k, [Text -> Content
ContentText Text
v])

attrKey :: Attr -> Name
attrKey :: Attr -> Name
attrKey = Attr -> Name
forall a b. (a, b) -> a
fst

strContent :: Element -> Text
strContent :: Element -> Text
strContent = [Text] -> Text
T.concat ([Text] -> Text) -> (Element -> [Text]) -> Element -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Element -> [Text]
elementText

class ToNode t where
  unode :: Name -> t -> Element

instance ToNode [Attr] where
  unode :: Name -> [Attr] -> Element
unode Name
n [Attr]
as = Name -> [Attr] -> [Node] -> Element
Element Name
n [Attr]
as []

instance ToNode [Element] where
  unode :: Name -> [Element] -> Element
unode Name
n = Name -> [Attr] -> [Node] -> Element
Element Name
n [] ([Node] -> Element)
-> ([Element] -> [Node]) -> [Element] -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Element -> Node) -> [Element] -> [Node]
forall a b. (a -> b) -> [a] -> [b]
map Element -> Node
NodeElement

instance ToNode ([Attr], Text) where
  unode :: Name -> ([Attr], Text) -> Element
unode Name
n ([Attr]
as, Text
t) = Name -> [Attr] -> [Node] -> Element
Element Name
n [Attr]
as [Content -> Node
NodeContent (Content -> Node) -> Content -> Node
forall a b. (a -> b) -> a -> b
$ Text -> Content
ContentText Text
t]

instance ToNode Text where
  unode :: Name -> Text -> Element
unode Name
n Text
t = Name -> ([Attr], Text) -> Element
forall t. ToNode t => Name -> t -> Element
unode Name
n ([] :: [Attr], Text
t)

findChildren :: Name -> Element -> [Element]
findChildren :: Name -> Element -> [Element]
findChildren Name
n Element
el = (Element -> Bool) -> [Element] -> [Element]
forall a. (a -> Bool) -> [a] -> [a]
filter ((Name
n Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
==) (Name -> Bool) -> (Element -> Name) -> Element -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Element -> Name
elementName) ([Element] -> [Element]) -> [Element] -> [Element]
forall a b. (a -> b) -> a -> b
$ Element -> [Element]
elementChildren Element
el

findChild :: Name -> Element -> Maybe Element
findChild :: Name -> Element -> Maybe Element
findChild = ([Element] -> Maybe Element
forall a. [a] -> Maybe a
headMay ([Element] -> Maybe Element)
-> (Element -> [Element]) -> Element -> Maybe Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) ((Element -> [Element]) -> Element -> Maybe Element)
-> (Name -> Element -> [Element])
-> Name
-> Element
-> Maybe Element
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Name -> Element -> [Element]
findChildren

findElements :: Name -> Element -> [Element]
findElements :: Name -> Element -> [Element]
findElements Name
n Element
e
  | Name
n Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== Element -> Name
elementName Element
e = [Element
e]
  | Bool
otherwise = (Element -> [Element]) -> [Element] -> [Element]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (Name -> Element -> [Element]
findElements Name
n) ([Element] -> [Element]) -> [Element] -> [Element]
forall a b. (a -> b) -> a -> b
$ Element -> [Element]
elementChildren Element
e

findElement :: Name -> Element -> Maybe Element
findElement :: Name -> Element -> Maybe Element
findElement = ([Element] -> Maybe Element
forall a. [a] -> Maybe a
headMay ([Element] -> Maybe Element)
-> (Element -> [Element]) -> Element -> Maybe Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) ((Element -> [Element]) -> Element -> Maybe Element)
-> (Name -> Element -> [Element])
-> Name
-> Element
-> Maybe Element
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Name -> Element -> [Element]
findElements