@@ -14,7 +14,7 @@
14module Text.XML.Lens (
14module Text.XML.Lens (
15 -- * Lenses, traversals for 'Element'
15 -- * Lenses, traversals for 'Element'
16 Element(..)
16 Element(..)
18 -- ** Names
18 -- ** Names
20 , localName
20 , localName
@@ -24,8 +24,6 @@ module Text.XML.Lens (
24 -- ** Attributes
24 -- ** Attributes
25 , attributeIs
25 , attributeIs
26 , attributeSatisfies
26 , attributeSatisfies
27− , attributeSatisfies'
30 , attribute
28 , attribute
@@ -33,6 +31,7 @@ module Text.XML.Lens (
35 -- ** Children
33 -- ** Children
37 -- * Prisms for 'Node'
36 -- * Prisms for 'Node'
38 , Node(..)
37 , Node(..)
@@ -55,53 +54,49 @@ module Text.XML.Lens (
55 , Instruction(..)
54 , Instruction(..)
56 , _instructionTarget
55 , _instructionTarget
57 , _instructionData
56 , _instructionData
58+ , module Control.Lens
59import Text.XML
60import Text.XML
60import Control.Lens
61import Control.Lens
61import Data.Text (Text)
62import Data.Text (Text)
62import Data.Map (Map)
63import Data.Map (Map)
64+import Control.Applicative
63import qualified Data.CaseInsensitive as CI
65import qualified Data.CaseInsensitive as CI
64−import Data.Maybe (isNothing)
66+
66prologue :: Lens' Document Prologue
69prologue :: Lens' Document Prologue
67prologue f doc = fmap (\p -> doc { documentPrologue = p} ) $ f $ documentPrologue doc
70prologue f doc = fmap (\p -> doc { documentPrologue = p} ) $ f $ documentPrologue doc
68−{-# INLINE prologue #-}
70-- | The root element of the document.
72-- | The root element of the document.
71root :: Lens' Document Element
73root :: Lens' Document Element
72root f doc = fmap (\p -> doc { documentRoot = p} ) $ f $ documentRoot doc
74root f doc = fmap (\p -> doc { documentRoot = p} ) $ f $ documentRoot doc
75epilogue :: Lens' Document [Miscellaneous]
76epilogue :: Lens' Document [Miscellaneous]
76epilogue f doc = fmap (\p -> doc { documentEpilogue = p} ) $ f $ documentEpilogue doc
77epilogue f doc = fmap (\p -> doc { documentEpilogue = p} ) $ f $ documentEpilogue doc
77−{-# INLINE epilogue #-}
79doctype :: Lens' Prologue (Maybe Doctype)
79doctype :: Lens' Prologue (Maybe Doctype)
80doctype f doc = fmap (\p -> doc { prologueDoctype = p} ) $ f $ prologueDoctype doc
80doctype f doc = fmap (\p -> doc { prologueDoctype = p} ) $ f $ prologueDoctype doc
81−{-# INLINE doctype #-}
83class AsInstruction t where
82class AsInstruction t where
84 _Instruction :: Prism' t Instruction
83 _Instruction :: Prism' t Instruction
86_instructionTarget :: Lens' Instruction Text
85_instructionTarget :: Lens' Instruction Text
87_instructionTarget f (Instruction t d) = f t <&> \t' -> Instruction t' d
86_instructionTarget f (Instruction t d) = f t <&> \t' -> Instruction t' d
88−{-# INLINE _instructionTarget #-}
90_instructionData :: Lens' Instruction Text
88_instructionData :: Lens' Instruction Text
91_instructionData f (Instruction t d) = f d <&> \d' -> Instruction t d'
89_instructionData f (Instruction t d) = f d <&> \d' -> Instruction t d'
92−{-# INLINE _instructionData #-}
94instance AsInstruction Node where
91instance AsInstruction Node where
95 _Instruction = prism' NodeInstruction $ \s -> case s of
92 _Instruction = prism' NodeInstruction $ \s -> case s of
96 NodeInstruction e -> Just e
93 NodeInstruction e -> Just e
97 _ -> Nothing
94 _ -> Nothing
98− {-# INLINE _Instruction #-}
100instance AsInstruction Miscellaneous where
96instance AsInstruction Miscellaneous where
101 _Instruction = prism' MiscInstruction $ \s -> case s of
97 _Instruction = prism' MiscInstruction $ \s -> case s of
102 MiscInstruction e -> Just e
98 MiscInstruction e -> Just e
103 _ -> Nothing
99 _ -> Nothing
104− {-# INLINE _Instruction #-}
106class AsComment t where
101class AsComment t where
107 _Comment :: Prism' t Text
102 _Comment :: Prism' t Text
@@ -110,41 +105,33 @@ instance AsComment Node where
110 _Comment = prism' NodeComment $ \s -> case s of
105 _Comment = prism' NodeComment $ \s -> case s of
111 NodeComment e -> Just e
106 NodeComment e -> Just e
112 _ -> Nothing
107 _ -> Nothing
113− {-# INLINE _Comment #-}
115instance AsComment Miscellaneous where
109instance AsComment Miscellaneous where
116 _Comment = prism' MiscComment $ \s -> case s of
110 _Comment = prism' MiscComment $ \s -> case s of
117 MiscComment e -> Just e
111 MiscComment e -> Just e
118 _ -> Nothing
112 _ -> Nothing
119− {-# INLINE _Comment #-}
121_nameLocalName :: Lens' Name Text
114_nameLocalName :: Lens' Name Text
122_nameLocalName f n = f (nameLocalName n) <&> \x -> n { nameLocalName = x }
115_nameLocalName f n = f (nameLocalName n) <&> \x -> n { nameLocalName = x }
123−{-# INLINE _nameLocalName #-}
125_nameNamespace :: Lens' Name (Maybe Text)
117_nameNamespace :: Lens' Name (Maybe Text)
126_nameNamespace f n = f (nameNamespace n) <&> \x -> n { nameNamespace = x }
118_nameNamespace f n = f (nameNamespace n) <&> \x -> n { nameNamespace = x }
127−{-# INLINE _nameNamespace #-}
129_namePrefix :: Lens' Name (Maybe Text)
120_namePrefix :: Lens' Name (Maybe Text)
130_namePrefix f n = f (namePrefix n) <&> \x -> n { namePrefix = x }
121_namePrefix f n = f (namePrefix n) <&> \x -> n { namePrefix = x }
131−{-# INLINE _namePrefix #-}
133_Element :: Prism' Node Element
123_Element :: Prism' Node Element
134_Element = prism' NodeElement $ \s -> case s of
124_Element = prism' NodeElement $ \s -> case s of
135 NodeElement e -> Just e
125 NodeElement e -> Just e
136 _ -> Nothing
126 _ -> Nothing
137−{-# INLINE _Element #-}
139_Content :: Prism' Node Text
128_Content :: Prism' Node Text
140_Content = prism' NodeContent $ \s -> case s of
129_Content = prism' NodeContent $ \s -> case s of
141 NodeContent e -> Just e
130 NodeContent e -> Just e
142 _ -> Nothing
131 _ -> Nothing
143−{-# INLINE _Content #-}
145name :: Lens' Element Name
133name :: Lens' Element Name
146name f e = f (elementName e) <&> \x -> e { elementName = x }
134name f e = f (elementName e) <&> \x -> e { elementName = x }
149localName :: Lens' Element Text
136localName :: Lens' Element Text
150localName = name . _nameLocalName
137localName = name . _nameLocalName
@@ -152,65 +139,60 @@ localName = name . _nameLocalName
153attrs :: Lens' Element (Map Name Text)
140attrs :: Lens' Element (Map Name Text)
154attrs f e = fmap (\x -> e { elementAttributes = x }) $ f $ elementAttributes e
141attrs f e = fmap (\x -> e { elementAttributes = x }) $ f $ elementAttributes e
157nodes :: Lens' Element [Node]
143nodes :: Lens' Element [Node]
158nodes f e = fmap (\x -> e { elementNodes = x }) $ f $ elementNodes e
144nodes f e = fmap (\x -> e { elementNodes = x }) $ f $ elementNodes e
161attr :: Name -> Traversal' Element Text
146attr :: Name -> Traversal' Element Text
162attr n = attrs . ix n
147attr n = attrs . ix n
165attribute :: Name -> Lens' Element (Maybe Text)
149attribute :: Name -> Lens' Element (Maybe Text)
166attribute n = attrs . at n
150attribute n = attrs . at n
167−{-# INLINE attribute #-}
151+
152+-- | Traverse itself with its all children. Rewriting subnodes of each children will break a traversal law.
153+entire :: Traversal' Element Element
154+entire f e@(Element _ _ ns) = com <$> f e <*> traverse (_Element (entire f)) ns where
155+ com (Element n a _) = Element n a
169-- | Traverse elements which has the specified *local* name (case-insensitive).
157-- | Traverse elements which has the specified *local* name (case-insensitive).
170named :: CI.CI Text -> Traversal' Element Element
158named :: CI.CI Text -> Traversal' Element Element
171named n f s
159named n f s
172 | CI.mk (nameLocalName (elementName s)) == n = f s
160 | CI.mk (nameLocalName (elementName s)) == n = f s
173 | otherwise = pure s
161 | otherwise = pure s
176-- | Old name for 'named'
163-- | Old name for 'named'
177ell :: Text -> Traversal' Element Element
164ell :: Text -> Traversal' Element Element
178−ell n = named $ CI.mk n
165+ell = named . CI.mk
180-- | Traverse elements which has the specified name.
167-- | Traverse elements which has the specified name.
181el :: Name -> Traversal' Element Element
168el :: Name -> Traversal' Element Element
183 | elementName s == n = f s
170 | elementName s == n = f s
184 | otherwise = pure s
171 | otherwise = pure s
185−{-# DEPRECATED el "Use named instead" #-}
187attributeSatisfies :: Name -> (Text -> Bool) -> Traversal' Element Element
173attributeSatisfies :: Name -> (Text -> Bool) -> Traversal' Element Element
188−attributeSatisfies n p = attributeSatisfies' n (maybe False p)
174+attributeSatisfies n p = filtered (maybe False p . preview (attrs . ix n))
189−{-# INLINE attributeSatisfies #-}
191−attributeSatisfies' :: Name -> (Maybe Text -> Bool) -> Traversal' Element Element
192−attributeSatisfies' n p = filtered (p . preview (attrs . ix n))
193−{-# INLINE attributeSatisfies' #-}
195−withoutAttribute :: Name -> Traversal' Element Element
196−withoutAttribute n = attributeSatisfies' n isNothing
197−{-# INLINE withoutAttribute #-}
199attributeIs :: Name -> Text -> Traversal' Element Element
176attributeIs :: Name -> Text -> Traversal' Element Element
200attributeIs n v = attributeSatisfies n (==v)
177attributeIs n v = attributeSatisfies n (==v)
201−{-# INLINE attributeIs #-}
203-- | Traverse all contents of the element.
179-- | Traverse all contents of the element.
204text :: Traversal' Element Text
180text :: Traversal' Element Text
205text = nodes . traverse . _Content
181text = nodes . traverse . _Content
208-- | Traverse all comments of the element.
183-- | Traverse all comments of the element.
209comment :: Traversal' Element Text
184comment :: Traversal' Element Text
210comment = nodes . traverse . _Comment
185comment = nodes . traverse . _Comment
211−{-# INLINE comment #-}
213-- | 'plate' traverses over its sub-elements.
187-- | 'plate' traverses over its sub-elements.
214instance Plated Element where
188instance Plated Element where
215 plate = nodes . traverse . _Element
189 plate = nodes . traverse . _Element
191+-- | Combine two 'Traversal's just like XPath's slash. Identical to ('...').
194+-- l ./ m ≡ l . 'plate' . m
196+(./) :: (Applicative f, Plated c) => LensLike f s t c c -> Over p f c c a b -> Over p f s t a b
216− {-# INLINE plate #-}
198+{-# INLINE (./) #-}