git.iko.soy/typeable/xml-lens
on 114e276 help sign in
.github/workflows/haskell.ymldeleted−37
since splitsnapshots
unifiedsplit
@@ -1,37 +0,0 @@
1−name: Haskell CI
2−
3−on: [push, pull_request]
4−
5−jobs:
6− build:
7−
8− runs-on: ubuntu-latest
9− strategy:
10− matrix:
11− ghc: [ '8.8.4', '8.10.7', '9.0.1', '9.2.2' ]
12− steps:
13− - uses: actions/checkout@v3
14− - uses: haskell/actions/setup@v1
15− with:
16− ghc-version: ${{ matrix.ghc }}
17− cabal-version: '3.4'
18−
19− - name: cabal Cache
20− uses: actions/cache@v1
21− env:
22− cache-name: cache-cabal
23− with:
24− path: ~/.cabal
25− key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/*.cabal') }}-${{ hashFiles('**/cabal.project') }}
26− restore-keys: |
27− ${{ runner.os }}-build-${{ env.cache-name }}-
28− ${{ runner.os }}-build-
29− ${{ runner.os }}-
30− - name: Install dependencies
31− run: |
32− cabal update
33− cabal build --only-dependencies --enable-tests --enable-benchmarks all
34− - name: Build
35− run: cabal build --enable-tests --enable-benchmarks all
36− - name: Run tests
37− run: cabal test --enable-tests --enable-benchmarks all
.gitignore−1
@@ -1,4 +1,3 @@
1−dist-newstyle
2#################
1#################
3## Eclipse
2## Eclipse
4#################
3#################
CHANGELOG.mddeleted−10
@@ -1,10 +0,0 @@
1−## 0.3.1
2−
3−* Supported GHC 9
4−
5−## 0.3 (2021/01)
6−
7−* Deprecated `el`
8−* Removed `./` and `entire`
9−
10−
README.md+4−8
@@ -9,16 +9,16 @@ Example
9```haskell
9```haskell
10> doc <- Text.XML.readFile def "examples/books.xml"
10> doc <- Text.XML.readFile def "examples/books.xml"
11
11
12−> doc ^.. root . named "books" ... named "book" . attributeIs "category" "Textbooks" ... named "title" . text
12+> doc ^.. root . el "books" ./ el "book" . attributeIs "category" "Textbooks" ./ el "title" . text
13["Learn You a Haskell for Great Good!","Programming in Haskell","Real World Haskell"]
13["Learn You a Haskell for Great Good!","Programming in Haskell","Real World Haskell"]
14
14
15−> lengthOf ?? doc $ root . named "books" ... named "book"
15+> lengthOf ?? doc $ root . el "books" ./ el "book"
167
167
17
17
18−> doc ^? root . named "books" ... attributeIs "category" "Joke" ... named "title" . text
18+> doc ^? root . el "books" ./ attributeIs "category" "Joke" ./ el "title" . text
19Just "Functional Ikamusume"
19Just "Functional Ikamusume"
20
20
21−> doc & root . named "books" ... named "book" ... named "pages" . text <>~ " pages" & renderLBS def & BL.putStrLn
21+> doc & root . el "books" ./ el "book" ./ el "pages" . text <>~ " pages" & renderLBS def & BL.putStrLn
22```
22```
23
23
24```xml
24```xml
@@ -43,8 +43,4 @@ Just "Functional Ikamusume"
43…
43…
44```
44```
45
45
46−Tips
47−----
48
46
49−* Use [cosmos](http://hackage.haskell.org/package/lens-4.19.2/docs/Control-Lens-Plated.html) to traverse over all children
50−* You can do or-composition of traversals with [failing](http://hackage.haskell.org/package/lens-4.19.2/docs/Control-Lens-Traversal.html#v:failing)
Text/XML/Lens.hs+24−40
@@ -14,6 +14,7 @@
14module Text.XML.Lens (
14module Text.XML.Lens (
15 -- * Lenses, traversals for 'Element'
15 -- * Lenses, traversals for 'Element'
16 Element(..)
16 Element(..)
17+ , (./)
17 , (...)
18 , (...)
18 -- ** Names
19 -- ** Names
19 , name
20 , name
@@ -24,8 +25,6 @@ module Text.XML.Lens (
24 -- ** Attributes
25 -- ** Attributes
25 , attributeIs
26 , attributeIs
26 , attributeSatisfies
27 , attributeSatisfies
27− , attributeSatisfies'
28− , withoutAttribute
29 , attr
28 , attr
30 , attribute
29 , attribute
31 , attrs
30 , attrs
@@ -33,6 +32,7 @@ module Text.XML.Lens (
33 , text
32 , text
34 , comment
33 , comment
35 -- ** Children
34 -- ** Children
35+ , entire
36 , nodes
36 , nodes
37 -- * Prisms for 'Node'
37 -- * Prisms for 'Node'
38 , Node(..)
38 , Node(..)
@@ -60,48 +60,42 @@ import Text.XML
60import Control.Lens
60import Control.Lens
61import Data.Text (Text)
61import Data.Text (Text)
62import Data.Map (Map)
62import Data.Map (Map)
63+import Control.Applicative
63import qualified Data.CaseInsensitive as CI
64import qualified Data.CaseInsensitive as CI
64−import Data.Maybe (isNothing)
65+
66+infixr 9 ./
65
67
66prologue :: Lens' Document Prologue
68prologue :: Lens' Document Prologue
67prologue f doc = fmap (\p -> doc { documentPrologue = p} ) $ f $ documentPrologue doc
69prologue f doc = fmap (\p -> doc { documentPrologue = p} ) $ f $ documentPrologue doc
68−{-# INLINE prologue #-}
69
70
70-- | The root element of the document.
71-- | The root element of the document.
71root :: Lens' Document Element
72root :: Lens' Document Element
72root f doc = fmap (\p -> doc { documentRoot = p} ) $ f $ documentRoot doc
73root f doc = fmap (\p -> doc { documentRoot = p} ) $ f $ documentRoot doc
73−{-# INLINE root #-}
74
74
75epilogue :: Lens' Document [Miscellaneous]
75epilogue :: Lens' Document [Miscellaneous]
76epilogue f doc = fmap (\p -> doc { documentEpilogue = p} ) $ f $ documentEpilogue doc
76epilogue f doc = fmap (\p -> doc { documentEpilogue = p} ) $ f $ documentEpilogue doc
77−{-# INLINE epilogue #-}
78
77
79doctype :: Lens' Prologue (Maybe Doctype)
78doctype :: Lens' Prologue (Maybe Doctype)
80doctype f doc = fmap (\p -> doc { prologueDoctype = p} ) $ f $ prologueDoctype doc
79doctype f doc = fmap (\p -> doc { prologueDoctype = p} ) $ f $ prologueDoctype doc
81−{-# INLINE doctype #-}
82
80
83class AsInstruction t where
81class AsInstruction t where
84 _Instruction :: Prism' t Instruction
82 _Instruction :: Prism' t Instruction
85
83
86_instructionTarget :: Lens' Instruction Text
84_instructionTarget :: Lens' Instruction Text
87_instructionTarget f (Instruction t d) = f t <&> \t' -> Instruction t' d
85_instructionTarget f (Instruction t d) = f t <&> \t' -> Instruction t' d
88−{-# INLINE _instructionTarget #-}
89
86
90_instructionData :: Lens' Instruction Text
87_instructionData :: Lens' Instruction Text
91_instructionData f (Instruction t d) = f d <&> \d' -> Instruction t d'
88_instructionData f (Instruction t d) = f d <&> \d' -> Instruction t d'
92−{-# INLINE _instructionData #-}
93
89
94instance AsInstruction Node where
90instance AsInstruction Node where
95 _Instruction = prism' NodeInstruction $ \s -> case s of
91 _Instruction = prism' NodeInstruction $ \s -> case s of
96 NodeInstruction e -> Just e
92 NodeInstruction e -> Just e
97 _ -> Nothing
93 _ -> Nothing
98− {-# INLINE _Instruction #-}
99
94
100instance AsInstruction Miscellaneous where
95instance AsInstruction Miscellaneous where
101 _Instruction = prism' MiscInstruction $ \s -> case s of
96 _Instruction = prism' MiscInstruction $ \s -> case s of
102 MiscInstruction e -> Just e
97 MiscInstruction e -> Just e
103 _ -> Nothing
98 _ -> Nothing
104− {-# INLINE _Instruction #-}
105
99
106class AsComment t where
100class AsComment t where
107 _Comment :: Prism' t Text
101 _Comment :: Prism' t Text
@@ -110,41 +104,33 @@ instance AsComment Node where
110 _Comment = prism' NodeComment $ \s -> case s of
104 _Comment = prism' NodeComment $ \s -> case s of
111 NodeComment e -> Just e
105 NodeComment e -> Just e
112 _ -> Nothing
106 _ -> Nothing
113− {-# INLINE _Comment #-}
114
107
115instance AsComment Miscellaneous where
108instance AsComment Miscellaneous where
116 _Comment = prism' MiscComment $ \s -> case s of
109 _Comment = prism' MiscComment $ \s -> case s of
117 MiscComment e -> Just e
110 MiscComment e -> Just e
118 _ -> Nothing
111 _ -> Nothing
119− {-# INLINE _Comment #-}
120
112
121_nameLocalName :: Lens' Name Text
113_nameLocalName :: Lens' Name Text
122_nameLocalName f n = f (nameLocalName n) <&> \x -> n { nameLocalName = x }
114_nameLocalName f n = f (nameLocalName n) <&> \x -> n { nameLocalName = x }
123−{-# INLINE _nameLocalName #-}
124
115
125_nameNamespace :: Lens' Name (Maybe Text)
116_nameNamespace :: Lens' Name (Maybe Text)
126_nameNamespace f n = f (nameNamespace n) <&> \x -> n { nameNamespace = x }
117_nameNamespace f n = f (nameNamespace n) <&> \x -> n { nameNamespace = x }
127−{-# INLINE _nameNamespace #-}
128
118
129_namePrefix :: Lens' Name (Maybe Text)
119_namePrefix :: Lens' Name (Maybe Text)
130_namePrefix f n = f (namePrefix n) <&> \x -> n { namePrefix = x }
120_namePrefix f n = f (namePrefix n) <&> \x -> n { namePrefix = x }
131−{-# INLINE _namePrefix #-}
132
121
133_Element :: Prism' Node Element
122_Element :: Prism' Node Element
134_Element = prism' NodeElement $ \s -> case s of
123_Element = prism' NodeElement $ \s -> case s of
135 NodeElement e -> Just e
124 NodeElement e -> Just e
136 _ -> Nothing
125 _ -> Nothing
137−{-# INLINE _Element #-}
138
126
139_Content :: Prism' Node Text
127_Content :: Prism' Node Text
140_Content = prism' NodeContent $ \s -> case s of
128_Content = prism' NodeContent $ \s -> case s of
141 NodeContent e -> Just e
129 NodeContent e -> Just e
142 _ -> Nothing
130 _ -> Nothing
143−{-# INLINE _Content #-}
144
131
145name :: Lens' Element Name
132name :: Lens' Element Name
146name f e = f (elementName e) <&> \x -> e { elementName = x }
133name f e = f (elementName e) <&> \x -> e { elementName = x }
147−{-# INLINE name #-}
148
134
149localName :: Lens' Element Text
135localName :: Lens' Element Text
150localName = name . _nameLocalName
136localName = name . _nameLocalName
@@ -152,65 +138,63 @@ localName = name . _nameLocalName
152
138
153attrs :: Lens' Element (Map Name Text)
139attrs :: Lens' Element (Map Name Text)
154attrs f e = fmap (\x -> e { elementAttributes = x }) $ f $ elementAttributes e
140attrs f e = fmap (\x -> e { elementAttributes = x }) $ f $ elementAttributes e
155−{-# INLINE attrs #-}
156
141
157nodes :: Lens' Element [Node]
142nodes :: Lens' Element [Node]
158nodes f e = fmap (\x -> e { elementNodes = x }) $ f $ elementNodes e
143nodes f e = fmap (\x -> e { elementNodes = x }) $ f $ elementNodes e
159−{-# INLINE nodes #-}
160
144
161attr :: Name -> Traversal' Element Text
145attr :: Name -> Traversal' Element Text
162attr n = attrs . ix n
146attr n = attrs . ix n
163−{-# INLINE attr #-}
164
147
165attribute :: Name -> Lens' Element (Maybe Text)
148attribute :: Name -> Lens' Element (Maybe Text)
166attribute n = attrs . at n
149attribute n = attrs . at n
167−{-# INLINE attribute #-}
150+
151+-- | Traverse itself with its all children. Rewriting subnodes of each children will break a traversal law.
152+entire :: Traversal' Element Element
153+entire f e@(Element _ _ ns) = com <$> f e <*> traverse (_Element (entire f)) ns where
154+ com (Element n a _) = Element n a
155+{-# DEPRECATED entire "Use cosmos or deep instead" #-}
168
156
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
174−{-# INLINE named #-}
175
162
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
179
166
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
182el n f s
169el n f s
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" #-}
186
172
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 #-}
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 #-}
198
175
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 #-}
202
178
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
206−{-# INLINE text #-}
207
182
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 #-}
212
186
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
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+(./) = (...)
216− {-# INLINE plate #-}
198+{-# INLINE (./) #-}
199+
200+{-# DEPRECATED (./) "Use (...) instead" #-}
cabal.projectdeleted−1
@@ -1 +0,0 @@
1−packages: ./
stack.yamldeleted−4
@@ -1,4 +0,0 @@
1−resolver: lts-21.3
2−
3−packages:
4−- .
xml-lens.cabal+8−11
@@ -1,20 +1,17 @@
1−cabal-version: 2.4
2name: xml-lens
1name: xml-lens
3−version: 0.3.1
2+version: 0.2
4synopsis: Lenses, traversals, and prisms for xml-conduit
3synopsis: Lenses, traversals, and prisms for xml-conduit
5−description: This package provides DOM selectors based on lenses and prisms. See README.md for examples
4+description: Lens-based DOM selector
6homepage: https://github.com/fumieval/xml-lens
5homepage: https://github.com/fumieval/xml-lens
7bug-reports: https://github.com/fumieval/xml-lens/issues
6bug-reports: https://github.com/fumieval/xml-lens/issues
8−license: BSD-3-Clause
7+license: BSD3
9license-file: LICENSE
8license-file: LICENSE
10author: Fumiaki Kinoshita
9author: Fumiaki Kinoshita
11maintainer: Fumiaki Kinoshita <fumiexcel@gmail.com>
10maintainer: Fumiaki Kinoshita <fumiexcel@gmail.com>
12−copyright: Copyright (C) 2021 Fumiaki Kinoshita
11+copyright: Copyright (C) 2019 Fumiaki Kinoshita
13category: XML
12category: XML
14build-type: Simple
13build-type: Simple
15−extra-source-files:
14+cabal-version: >=1.10
16− README.md
17− CHANGELOG.md
18
15
19source-repository head
16source-repository head
20 type: git
17 type: git
@@ -25,8 +22,8 @@ library
25 ghc-options: -Wall
22 ghc-options: -Wall
26 exposed-modules: Text.XML.Lens
23 exposed-modules: Text.XML.Lens
27 build-depends: base ==4.*
24 build-depends: base ==4.*
28− , lens >= 4.0 && < 5.4
25+ , lens >= 4.0 && < 5
29 , containers >= 0.4.0 && < 0.7
26 , containers >= 0.4.0 && < 0.7
30− , text >= 0.7 && < 1.3 || >= 2 && < 2.2
27+ , text >= 0.7 && <2
31− , xml-conduit >= 1.1 && < 1.10
28+ , xml-conduit >= 1.1 && < 1.9
32 , case-insensitive
29 , case-insensitive