0 | module Language.XML.Element
4 | import public Data.List.Alternating
6 | import Data.String.Extra
7 | import Data.String.Parser
9 | import public Language.XML.Attribute
10 | import public Language.XML.CharData
11 | import public Language.XML.Misc
12 | import public Language.XML.Name
15 | data Element = EmptyElem QName (List Attribute)
16 | | Elem QName (List Attribute) (Odd CharData $
Either Misc Element)
21 | (.name) : Element -> QName
22 | (EmptyElem name _).name = name
23 | (Elem name _ _).name = name
26 | (.attrs) : Element -> List Attribute
27 | (EmptyElem _ attrs).attrs = attrs
28 | (Elem _ attrs _).attrs = attrs
31 | (.content) : Element -> Odd CharData (Either Misc Element)
32 | (EmptyElem _ _).content = [""]
33 | (Elem _ _ content).content = content
36 | maybeNl : Bool -> String
41 | showNl : CharData -> String
42 | showNl (MkCharData preSpace c postSpace) = maybeNl preSpace ++ c ++ maybeNl postSpace
45 | textContent : Element -> String
46 | textContent (EmptyElem name attrs) = ""
47 | textContent (Elem name attrs content) = concat $
Odd.forget $
48 | bimap showNl textContent $
content >>= either (const neutral) pure
51 | find : (Element -> Bool) -> Element -> Maybe Element
52 | find f elem = find f (rights $
evens elem.content)
55 | mapContent : (Odd CharData (Either Misc Element) -> Odd CharData (Either Misc Element)) -> Element -> Element
56 | mapContent f (EmptyElem name attrs) = EmptyElem name attrs
57 | mapContent f (Elem name attrs content) = Elem name attrs (f content)
60 | mapContentM : Monad m => (Odd CharData (Either Misc Element) -> m (Odd CharData (Either Misc Element))) -> Element -> m Element
61 | mapContentM f (EmptyElem name attrs) = pure $
EmptyElem name attrs
62 | mapContentM f (Elem name attrs content) = pure $
Elem name attrs !(f content)
64 | indentTail : String -> String
66 | let (x ::: xs) = split (== '\n') str in
67 | join "\n" (x :: map indent xs)
69 | indent : String -> String
75 | show (EmptyElem name attrs) =
76 | "<\{show name}\{concat $ map (\attr => " " ++ show attr) attrs}/>"
77 | show (Elem name attrs content) =
79 | <\{show name}\{concat $ map (\attr => " " ++ show attr) attrs}>\
80 | \{indentTail $ concat $ forget $ assert_total $ bimap showNl (either show show) content}\
85 | element : Parser Element
89 | attrs <- many (spaces *> attribute)
91 | Nothing <- optional $
string "/>"
92 | | Just _ => pure $
EmptyElem name attrs
95 | content <- alternating charData $
map Left misc <|> map Right element
97 | string "</\{show name}" *> spaces <* string ">"
99 | pure $
Elem name attrs content
100 | ) <?> "XML element"