git.iko.soy/typeable/xml-lens
on master help sign in
add 'entire'
38ca91afumieval
README.md+1−1
@@ -6,7 +6,7 @@ Lenses and traversals for [xml-conduit](http://hackage.haskell.org/package/xml-c
6Example
6Example
7========
7========
8
8
9− > doc <- Text.XML.readFile def "examples\\books.xml"
9+ > doc <- Text.XML.readFile def "examples/books.xml"
10
10
11 > doc ^.. root . el "books" ./ el "book" . attributeIs "category" "Textbooks" ./ el "title" . text
11 > doc ^.. root . el "books" ./ el "book" . attributeIs "category" "Textbooks" ./ el "title" . text
12 ["Learn You a Haskell for Great Good!","Programming in Haskell","Real World Haskell"]
12 ["Learn You a Haskell for Great Good!","Programming in Haskell","Real World Haskell"]
Text/XML/Lens.hs+38−11
@@ -1,4 +1,4 @@
1−{-# LANGUAGE Rank2Types #-}
1+{-# LANGUAGE Rank2Types, FlexibleContexts #-}
2-----------------------------------------------------------------------------
2-----------------------------------------------------------------------------
3-- |
3-- |
4-- Module : Text.XML.Lens
4-- Module : Text.XML.Lens
@@ -8,22 +8,26 @@
8-- Maintainer : Fumiaki Kinoshita <fumiexcel@gmail.com>
8-- Maintainer : Fumiaki Kinoshita <fumiexcel@gmail.com>
9-- Stability : experimental
9-- Stability : experimental
10-- Portability : non-portable
10-- Portability : non-portable
11−--
11+-- Useful traversals inspired by XPath
12----------------------------------------------------------------------------
12----------------------------------------------------------------------------
13module Text.XML.Lens (
13module Text.XML.Lens (
14− -- * Useful traversals inspired by XPath
14+ -- * Lenses, traversals for 'Element'
15 (./)
15 (./)
16+ -- ** Names
17+ , name
16 , el
18 , el
19+ -- ** Attributes
17 , attributeIs
20 , attributeIs
18 , attributeSatisfies
21 , attributeSatisfies
22+ , attr
23+ , attribute
24+ , attrs
25+ -- ** Contents
19 , text
26 , text
20 , comment
27 , comment
21− -- * Lenses, traversals for 'Element'
28+ -- ** Children
22− , name
29+ , entire
23− , attrs
24 , nodes
30 , nodes
25− , attr
26− , attribute
27 -- * Prisms for 'Node'
31 -- * Prisms for 'Node'
28 , _Element
32 , _Element
29 , _Content
33 , _Content
@@ -38,6 +42,9 @@ module Text.XML.Lens (
38 , _nameLocalName
42 , _nameLocalName
39 , _nameNamespace
43 , _nameNamespace
40 , _namePrefix
44 , _namePrefix
45+ -- * Lenses for 'Instruction'
46+ , _instructionTarget
47+ , _instructionData
41 ) where
48 ) where
42import Text.XML
49import Text.XML
43import Control.Lens
50import Control.Lens
@@ -50,6 +57,7 @@ infixr 9 ./
50prologue :: Lens' Document Prologue
57prologue :: Lens' Document Prologue
51prologue f doc = fmap (\p -> doc { documentPrologue = p} ) $ f $ documentPrologue doc
58prologue f doc = fmap (\p -> doc { documentPrologue = p} ) $ f $ documentPrologue doc
52
59
60+-- | The root element of the document.
53root :: Lens' Document Element
61root :: Lens' Document Element
54root f doc = fmap (\p -> doc { documentRoot = p} ) $ f $ documentRoot doc
62root f doc = fmap (\p -> doc { documentRoot = p} ) $ f $ documentRoot doc
55
63
@@ -62,6 +70,12 @@ doctype f doc = fmap (\p -> doc { prologueDoctype = p} ) $ f $ prologueDoctype d
62class AsInstruction t where
70class AsInstruction t where
63 _Instruction :: Prism' t Instruction
71 _Instruction :: Prism' t Instruction
64
72
73+_instructionTarget :: Lens' Instruction Text
74+_instructionTarget f (Instruction t d) = f t <&> \t' -> Instruction t' d
75+
76+_instructionData :: Lens' Instruction Text
77+_instructionData f (Instruction t d) = f d <&> \d' -> Instruction t d'
78+
65instance AsInstruction Node where
79instance AsInstruction Node where
66 _Instruction = prism' NodeInstruction $ \s -> case s of
80 _Instruction = prism' NodeInstruction $ \s -> case s of
67 NodeInstruction e -> Just e
81 NodeInstruction e -> Just e
@@ -113,12 +127,18 @@ attrs f e = fmap (\x -> e { elementAttributes = x }) $ f $ elementAttributes e
113nodes :: Lens' Element [Node]
127nodes :: Lens' Element [Node]
114nodes f e = fmap (\x -> e { elementNodes = x }) $ f $ elementNodes e
128nodes f e = fmap (\x -> e { elementNodes = x }) $ f $ elementNodes e
115
129
116−attr :: Name -> Traversal' Element Text
130+attr :: Name -> IndexedTraversal' Name Element Text
117attr n = attrs . ix n
131attr n = attrs . ix n
118
132
119−attribute :: Name -> Lens' Element (Maybe Text)
133+attribute :: Name -> IndexedLens' Name Element (Maybe Text)
120attribute n = attrs . at n
134attribute n = attrs . at n
121
135
136+-- | Traverse itself with its all children.
137+entire :: Traversal' Element Element
138+entire f e@(Element _ _ ns) = com <$> f e <*> traverse (_Element (entire f)) ns where
139+ com (Element n a _) ns = Element n a ns
140+
141+-- | Traverse elements which has the specified name.
122el :: Name -> Traversal' Element Element
142el :: Name -> Traversal' Element Element
123el n f s
143el n f s
124 | elementName s == n = f s
144 | elementName s == n = f s
@@ -130,14 +150,21 @@ attributeSatisfies n p = filtered (maybe False p . preview (attrs . ix n))
130attributeIs :: Name -> Text -> Traversal' Element Element
150attributeIs :: Name -> Text -> Traversal' Element Element
131attributeIs n v = attributeSatisfies n (==v)
151attributeIs n v = attributeSatisfies n (==v)
132
152
153+-- | Traverse all contents of the element.
133text :: Traversal' Element Text
154text :: Traversal' Element Text
134text = nodes . traverse . _Content
155text = nodes . traverse . _Content
135
156
157+-- | Traverse all comments of the element.
136comment :: Traversal' Element Text
158comment :: Traversal' Element Text
137comment = nodes . traverse . _Comment
159comment = nodes . traverse . _Comment
138
160
139instance Plated Element where
161instance Plated Element where
140 plate = nodes . traverse . _Element
162 plate = nodes . traverse . _Element
141
163
164+-- | Combine two 'Traversal's just like XPath's slash.
165+--
166+-- @
167+-- l ./ m ≡ l . 'plate' . m
168+-- @
142(./) :: Plated a => Traversal s t a a -> Traversal a a u v -> Traversal s t u v
169(./) :: Plated a => Traversal s t a a -> Traversal a a u v -> Traversal s t u v
143−l ./ m = l . plate . m
170+l ./ m = l . plate . m