@@ -14,7 +14,7 @@
1414module Text.XML.Lens (
1515 -- * Lenses, traversals for 'Element'
1616 Element(..)
17− , (./)
17+ , (...)
1818 -- ** Names
1919 , name
2020 , localName
@@ -24,6 +24,8 @@ module Text.XML.Lens (
2424 -- ** Attributes
2525 , attributeIs
2626 , attributeSatisfies
27+ , attributeSatisfies'
28+ , withoutAttribute
2729 , attr
2830 , attribute
2931 , attrs
@@ -31,7 +33,6 @@ module Text.XML.Lens (
3133 , text
3234 , comment
3335 -- ** Children
34− , entire
3536 , nodes
3637 -- * Prisms for 'Node'
3738 , Node(..)
@@ -54,49 +55,53 @@ module Text.XML.Lens (
5455 , Instruction(..)
5556 , _instructionTarget
5657 , _instructionData
57− -- * Reexport
58− , module Control.Lens
5958 ) where
6059import Text.XML
6160import Control.Lens
6261import Data.Text (Text)
6362import Data.Map (Map)
64−import Control.Applicative
6563import qualified Data.CaseInsensitive as CI
66−
67−infixr 9 ./
64+import Data.Maybe (isNothing)
6865
6966prologue :: Lens' Document Prologue
7067prologue f doc = fmap (\p -> doc { documentPrologue = p} ) $ f $ documentPrologue doc
68+{-# INLINE prologue #-}
7169
7270-- | The root element of the document.
7371root :: Lens' Document Element
7472root f doc = fmap (\p -> doc { documentRoot = p} ) $ f $ documentRoot doc
73+{-# INLINE root #-}
7574
7675epilogue :: Lens' Document [Miscellaneous]
7776epilogue f doc = fmap (\p -> doc { documentEpilogue = p} ) $ f $ documentEpilogue doc
77+{-# INLINE epilogue #-}
7878
7979doctype :: Lens' Prologue (Maybe Doctype)
8080doctype f doc = fmap (\p -> doc { prologueDoctype = p} ) $ f $ prologueDoctype doc
81+{-# INLINE doctype #-}
8182
8283class AsInstruction t where
8384 _Instruction :: Prism' t Instruction
8485
8586_instructionTarget :: Lens' Instruction Text
8687_instructionTarget f (Instruction t d) = f t <&> \t' -> Instruction t' d
88+{-# INLINE _instructionTarget #-}
8789
8890_instructionData :: Lens' Instruction Text
8991_instructionData f (Instruction t d) = f d <&> \d' -> Instruction t d'
92+{-# INLINE _instructionData #-}
9093
9194instance AsInstruction Node where
9295 _Instruction = prism' NodeInstruction $ \s -> case s of
9396 NodeInstruction e -> Just e
9497 _ -> Nothing
98+ {-# INLINE _Instruction #-}
9599
96100instance AsInstruction Miscellaneous where
97101 _Instruction = prism' MiscInstruction $ \s -> case s of
98102 MiscInstruction e -> Just e
99103 _ -> Nothing
104+ {-# INLINE _Instruction #-}
100105
101106class AsComment t where
102107 _Comment :: Prism' t Text
@@ -105,33 +110,41 @@ instance AsComment Node where
105110 _Comment = prism' NodeComment $ \s -> case s of
106111 NodeComment e -> Just e
107112 _ -> Nothing
113+ {-# INLINE _Comment #-}
108114
109115instance AsComment Miscellaneous where
110116 _Comment = prism' MiscComment $ \s -> case s of
111117 MiscComment e -> Just e
112118 _ -> Nothing
119+ {-# INLINE _Comment #-}
113120
114121_nameLocalName :: Lens' Name Text
115122_nameLocalName f n = f (nameLocalName n) <&> \x -> n { nameLocalName = x }
123+{-# INLINE _nameLocalName #-}
116124
117125_nameNamespace :: Lens' Name (Maybe Text)
118126_nameNamespace f n = f (nameNamespace n) <&> \x -> n { nameNamespace = x }
127+{-# INLINE _nameNamespace #-}
119128
120129_namePrefix :: Lens' Name (Maybe Text)
121130_namePrefix f n = f (namePrefix n) <&> \x -> n { namePrefix = x }
131+{-# INLINE _namePrefix #-}
122132
123133_Element :: Prism' Node Element
124134_Element = prism' NodeElement $ \s -> case s of
125135 NodeElement e -> Just e
126136 _ -> Nothing
137+{-# INLINE _Element #-}
127138
128139_Content :: Prism' Node Text
129140_Content = prism' NodeContent $ \s -> case s of
130141 NodeContent e -> Just e
131142 _ -> Nothing
143+{-# INLINE _Content #-}
132144
133145name :: Lens' Element Name
134146name f e = f (elementName e) <&> \x -> e { elementName = x }
147+{-# INLINE name #-}
135148
136149localName :: Lens' Element Text
137150localName = name . _nameLocalName
@@ -139,60 +152,65 @@ localName = name . _nameLocalName
139152
140153attrs :: Lens' Element (Map Name Text)
141154attrs f e = fmap (\x -> e { elementAttributes = x }) $ f $ elementAttributes e
155+{-# INLINE attrs #-}
142156
143157nodes :: Lens' Element [Node]
144158nodes f e = fmap (\x -> e { elementNodes = x }) $ f $ elementNodes e
159+{-# INLINE nodes #-}
145160
146161attr :: Name -> Traversal' Element Text
147162attr n = attrs . ix n
163+{-# INLINE attr #-}
148164
149165attribute :: Name -> Lens' Element (Maybe Text)
150166attribute n = attrs . at n
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
167+{-# INLINE attribute #-}
156168
157169-- | Traverse elements which has the specified *local* name (case-insensitive).
158170named :: CI.CI Text -> Traversal' Element Element
159171named n f s
160172 | CI.mk (nameLocalName (elementName s)) == n = f s
161173 | otherwise = pure s
174+{-# INLINE named #-}
162175
163176-- | Old name for 'named'
164177ell :: Text -> Traversal' Element Element
165−ell = named . CI.mk
178+ell n = named $ CI.mk n
166179
167180-- | Traverse elements which has the specified name.
168181el :: Name -> Traversal' Element Element
169182el n f s
170183 | elementName s == n = f s
171184 | otherwise = pure s
185+{-# DEPRECATED el "Use named instead" #-}
172186
173187attributeSatisfies :: Name -> (Text -> Bool) -> Traversal' Element Element
174−attributeSatisfies n p = filtered (maybe False p . preview (attrs . ix n))
188+attributeSatisfies n p = attributeSatisfies' n (maybe False p)
189+{-# INLINE attributeSatisfies #-}
190+
191+attributeSatisfies' :: Name -> (Maybe Text -> Bool) -> Traversal' Element Element
192+attributeSatisfies' n p = filtered (p . preview (attrs . ix n))
193+{-# INLINE attributeSatisfies' #-}
194+
195+withoutAttribute :: Name -> Traversal' Element Element
196+withoutAttribute n = attributeSatisfies' n isNothing
197+{-# INLINE withoutAttribute #-}
175198
176199attributeIs :: Name -> Text -> Traversal' Element Element
177200attributeIs n v = attributeSatisfies n (==v)
201+{-# INLINE attributeIs #-}
178202
179203-- | Traverse all contents of the element.
180204text :: Traversal' Element Text
181205text = nodes . traverse . _Content
206+{-# INLINE text #-}
182207
183208-- | Traverse all comments of the element.
184209comment :: Traversal' Element Text
185210comment = nodes . traverse . _Comment
211+{-# INLINE comment #-}
186212
187213-- | 'plate' traverses over its sub-elements.
188214instance Plated Element where
189215 plate = nodes . traverse . _Element
190−
191−-- | Combine two 'Traversal's just like XPath's slash. Identical to ('...').
192−--
193−-- @
194−-- l ./ m ≡ l . 'plate' . m
195−-- @
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
197−(./) = (...)
198−{-# INLINE (./) #-}
216+ {-# INLINE plate #-}