packages feed

xml-html-conduit-lens-0.3.2.2: example/books.hs

{-# LANGUAGE OverloadedStrings #-}
module Books where

import Control.Applicative -- base
import Control.Lens        -- lens
import Data.Text (Text)    -- text
import Text.Xml.Lens       -- xml-html-conduit-lens

-- $setup
-- >>> :set -XOverloadedStrings
-- >>> import Text.Xml.Lens
-- >>> import qualified Data.Text.Lazy.IO as Text
-- >>> doc <- Text.readFile "example/books.xml"

-- | Titles of the books in the "Textbooks" category
--
-- >>> toListOf titles doc
-- ["Learn You a Haskell for Great Good!","Programming in Haskell","Real World Haskell"]
titles :: AsXmlDocument t => Traversal' t Text
titles =
  xml...attributed (ix "category".only "Textbooks").node "title".text

-- | Authors of the books longer then 500 pages
--
-- >>> toListOf authors doc
-- ["Bryan O'Sullivan, Don Stewart, and John Goerzen","Benjamin C. Pierce"]
authors :: AsXmlDocument t => Traversal' t Text
authors =
  xml...filtered (has (node "pages".text.filtered (> "500"))).node "author".text

-- | Titles and authors of the books in the "Textbooks" category
--
-- >>> toListOf titlesAndAuthors doc
-- [("Learn You a Haskell for Great Good!","Miran Lipovaca"),("Programming in Haskell","Graham Hutton"),("Real World Haskell","Bryan O'Sullivan, Don Stewart, and John Goerzen")]
titlesAndAuthors :: AsXmlDocument t => Fold t (Text, Text)
titlesAndAuthors =
  xml...attributed (ix "category".only "Textbooks").runFold (liftA2 (,) (Fold title) (Fold author))
 where
  title, author :: Fold Element Text
  title = node "title".text
  author = node "author".text

-- | Title of the third book in the list
--
-- >>> preview thirdTitle doc
-- Just "Programming in Haskell"
thirdTitle :: AsXmlDocument t => Fold t Text
thirdTitle =
  xml.parts.ix 2.node "title".text

-- | All tags in the document.
--
-- >>> toListOf allTags doc
-- ["books","book","title","author","pages","price","book","title","author","pages","book","title","author","pages","book","title","author","pages","book","title","author","pages","book","title","author","pages","book","title","author"]
allTags :: AsXmlDocument t => Fold t Text
allTags =
  xml.folding universe.name

-- | Compute the length of the books list:
--
-- >>> lengthOf allBooks doc
-- 7
allBooks :: AsXmlDocument t => Traversal' t Element
allBooks =
  xml.plate

-- | Find the title of the first book in the "Joke" category:
--
-- >>> preview titleOfFirstJokeBook doc
-- Just "Functional Ikamusume"
titleOfFirstJokeBook :: AsXmlDocument t => Traversal' t Text
titleOfFirstJokeBook =
  xml...attributed (ix "category".only "Joke").node "title".text

-- | Append the string " pages" to `<pages>` tags' content:
--
-- >>>  Text.putStr (appendPages doc)
-- <?xml version="1.0" encoding="UTF-8"?><books>
-- <book category="Language and library definition">
--     <title>Haskell 98 language and libraries: the Revised Report</title>
--     <author year="2003">Simon Peyton Jones</author>
--     <pages>272 pages</pages>
--     <price>£45.00</price>
-- </book>
-- <book category="Textbooks">
--     <title>Learn You a Haskell for Great Good!</title>
--     <author year="2011">Miran Lipovaca</author>
--     <pages>360 pages</pages>
-- </book>
-- <book category="Textbooks">
--     <title>Programming in Haskell</title>
--     <author year="2007">Graham Hutton</author>
--     <pages>200 pages</pages>
-- </book>
-- <book category="Textbooks">
--     <title>Real World Haskell</title>
--     <author year="2008">Bryan O'Sullivan, Don Stewart, and John Goerzen</author>
--     <pages>700 pages</pages>
-- </book>
-- <book category="TextBooks">
--     <title>The Fun of Programming</title>
--     <author year="2002">Jeremy Gibbons and Oege de Moor</author>
--     <pages>288 pages</pages>
-- </book>
-- <book category="Foundations">
--     <title>Types and Programming Languages</title>
--     <author year="2002">Benjamin C. Pierce</author>
--     <pages>645 pages</pages>
-- </book>
-- <book category="Joke">
--     <title>Functional Ikamusume</title>
--     <author>Team "Referential Transparent Sea Keepers"</author>
-- </book>
-- </books>
appendPages :: AsXmlDocument t => t -> t
appendPages =
  xml...node "pages".text <>~ " pages"