git.iko.soy/typeable/xml-lens
on 90ded18 help sign in
8 files changed+44−157
since splitsnapshots
unifiedsplit
.github/workflows/haskell.yml−37 .gitignore−1 CHANGELOG.md−10 README.md+8−14 Text/XML/Lens.hs+27−73 cabal.project−1 stack.yaml−4 xml-lens.cabal+9−17
.github/workflows/haskell.ymldeleted−37
@@ -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
21#################
32## Eclipse
43#################
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+8−14
@@ -6,20 +6,18 @@ Lenses and traversals for [xml-conduit](http://hackage.haskell.org/package/xml-c
66Example
77========
88
9−```haskell
10−> doc <- Text.XML.readFile def "examples/books.xml"
9+ > doc <- Text.XML.readFile def "examples/books.xml"
1110
12−> doc ^.. root . named "books" ... named "book" . attributeIs "category" "Textbooks" ... named "title" . text
13−["Learn You a Haskell for Great Good!","Programming in Haskell","Real World Haskell"]
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"]
1413
15−> lengthOf ?? doc $ root . named "books" ... named "book"
16−7
14+ > lengthOf ?? doc $ root . el "books" ./ el "book"
15+ 7
1716
18−> doc ^? root . named "books" ... attributeIs "category" "Joke" ... named "title" . text
19−Just "Functional Ikamusume"
17+ > doc ^? root . el "books" ./ attributeIs "category" "Joke" ./ el "title" . text
18+ Just "Functional Ikamusume"
2019
21−> doc & root . named "books" ... named "book" ... named "pages" . text <>~ " pages" & renderLBS def & BL.putStrLn
22−```
20+ > doc & root . el "books" ./ el "book" ./ el "pages" . text <>~ " pages" & renderLBS def & BL.putStrLn
2321
2422```xml
2523<?xml version="1.0" encoding="ISO-8859-1"?>
@@ -43,8 +41,4 @@ Just "Functional Ikamusume"
4341…
4442```
4543
46−Tips
47−----
4844
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+27−73
@@ -1,31 +1,24 @@
11{-# LANGUAGE Rank2Types, FlexibleContexts #-}
2−{-# OPTIONS_GHC -fno-warn-orphans #-}
32-----------------------------------------------------------------------------
43-- |
54-- Module : Text.XML.Lens
6−-- Copyright : (C) 2015 Fumiaki Kinoshita
5+-- Copyright : (C) 2013 Fumiaki Kinoshita
76-- License : BSD-style (see the file LICENSE)
87--
98-- Maintainer : Fumiaki Kinoshita <fumiexcel@gmail.com>
10−-- Stability : provisional
9+-- Stability : experimental
1110-- Portability : non-portable
12−--
11+-- Useful traversals inspired by XPath
1312----------------------------------------------------------------------------
1413module Text.XML.Lens (
1514 -- * Lenses, traversals for 'Element'
16− Element(..)
17− , (...)
15+ (./)
1816 -- ** Names
1917 , name
20− , localName
2118 , el
22− , ell
23− , named
2419 -- ** Attributes
2520 , attributeIs
2621 , attributeSatisfies
27− , attributeSatisfies'
28− , withoutAttribute
2922 , attr
3023 , attribute
3124 , attrs
@@ -33,26 +26,23 @@ module Text.XML.Lens (
3326 , text
3427 , comment
3528 -- ** Children
29+ , entire
3630 , nodes
3731 -- * Prisms for 'Node'
38− , Node(..)
3932 , _Element
4033 , _Content
4134 , AsInstruction(..)
4235 , AsComment(..)
4336 -- * Lenses for 'Document'
44− , Document(..)
4537 , root
4638 , prologue
4739 , epilogue
4840 , doctype
4941 -- * Lenses for 'Name'
50− , Name(..)
5142 , _nameLocalName
5243 , _nameNamespace
5344 , _namePrefix
5445 -- * Lenses for 'Instruction'
55− , Instruction(..)
5646 , _instructionTarget
5747 , _instructionData
5848 ) where
@@ -60,48 +50,41 @@ import Text.XML
6050import Control.Lens
6151import Data.Text (Text)
6252import Data.Map (Map)
63−import qualified Data.CaseInsensitive as CI
64−import Data.Maybe (isNothing)
53+import Control.Applicative
54+
55+infixr 9 ./
6556
6657prologue :: Lens' Document Prologue
6758prologue f doc = fmap (\p -> doc { documentPrologue = p} ) $ f $ documentPrologue doc
68−{-# INLINE prologue #-}
6959
7060-- | The root element of the document.
7161root :: Lens' Document Element
7262root f doc = fmap (\p -> doc { documentRoot = p} ) $ f $ documentRoot doc
73−{-# INLINE root #-}
7463
7564epilogue :: Lens' Document [Miscellaneous]
7665epilogue f doc = fmap (\p -> doc { documentEpilogue = p} ) $ f $ documentEpilogue doc
77−{-# INLINE epilogue #-}
7866
7967doctype :: Lens' Prologue (Maybe Doctype)
8068doctype f doc = fmap (\p -> doc { prologueDoctype = p} ) $ f $ prologueDoctype doc
81−{-# INLINE doctype #-}
8269
8370class AsInstruction t where
8471 _Instruction :: Prism' t Instruction
8572
8673_instructionTarget :: Lens' Instruction Text
8774_instructionTarget f (Instruction t d) = f t <&> \t' -> Instruction t' d
88−{-# INLINE _instructionTarget #-}
8975
9076_instructionData :: Lens' Instruction Text
9177_instructionData f (Instruction t d) = f d <&> \d' -> Instruction t d'
92−{-# INLINE _instructionData #-}
9378
9479instance AsInstruction Node where
9580 _Instruction = prism' NodeInstruction $ \s -> case s of
9681 NodeInstruction e -> Just e
9782 _ -> Nothing
98− {-# INLINE _Instruction #-}
9983
10084instance AsInstruction Miscellaneous where
10185 _Instruction = prism' MiscInstruction $ \s -> case s of
10286 MiscInstruction e -> Just e
10387 _ -> Nothing
104− {-# INLINE _Instruction #-}
10588
10689class AsComment t where
10790 _Comment :: Prism' t Text
@@ -110,107 +93,78 @@ instance AsComment Node where
11093 _Comment = prism' NodeComment $ \s -> case s of
11194 NodeComment e -> Just e
11295 _ -> Nothing
113− {-# INLINE _Comment #-}
11496
11597instance AsComment Miscellaneous where
11698 _Comment = prism' MiscComment $ \s -> case s of
11799 MiscComment e -> Just e
118100 _ -> Nothing
119− {-# INLINE _Comment #-}
120101
121102_nameLocalName :: Lens' Name Text
122−_nameLocalName f n = f (nameLocalName n) <&> \x -> n { nameLocalName = x }
123−{-# INLINE _nameLocalName #-}
103+_nameLocalName f n = fmap (\x -> n { nameLocalName = x }) $ f $ nameLocalName n
124104
125105_nameNamespace :: Lens' Name (Maybe Text)
126−_nameNamespace f n = f (nameNamespace n) <&> \x -> n { nameNamespace = x }
127−{-# INLINE _nameNamespace #-}
106+_nameNamespace f n = fmap (\x -> n { nameNamespace = x }) $ f $ nameNamespace n
128107
129108_namePrefix :: Lens' Name (Maybe Text)
130−_namePrefix f n = f (namePrefix n) <&> \x -> n { namePrefix = x }
131−{-# INLINE _namePrefix #-}
109+_namePrefix f n = fmap (\x -> n { namePrefix = x }) $ f $ namePrefix n
132110
133111_Element :: Prism' Node Element
134112_Element = prism' NodeElement $ \s -> case s of
135113 NodeElement e -> Just e
136114 _ -> Nothing
137−{-# INLINE _Element #-}
138115
139116_Content :: Prism' Node Text
140117_Content = prism' NodeContent $ \s -> case s of
141118 NodeContent e -> Just e
142119 _ -> Nothing
143−{-# INLINE _Content #-}
144120
145121name :: Lens' Element Name
146−name f e = f (elementName e) <&> \x -> e { elementName = x }
147−{-# INLINE name #-}
148−
149−localName :: Lens' Element Text
150−localName = name . _nameLocalName
151−{-# INLINE localName #-}
122+name f e = fmap (\x -> e { elementName = x }) $ f $ elementName e
152123
153124attrs :: Lens' Element (Map Name Text)
154125attrs f e = fmap (\x -> e { elementAttributes = x }) $ f $ elementAttributes e
155−{-# INLINE attrs #-}
156126
157127nodes :: Lens' Element [Node]
158128nodes f e = fmap (\x -> e { elementNodes = x }) $ f $ elementNodes e
159−{-# INLINE nodes #-}
160129
161−attr :: Name -> Traversal' Element Text
130+attr :: Name -> IndexedTraversal' Name Element Text
162131attr n = attrs . ix n
163−{-# INLINE attr #-}
164132
165−attribute :: Name -> Lens' Element (Maybe Text)
133+attribute :: Name -> IndexedLens' Name Element (Maybe Text)
166134attribute n = attrs . at n
167−{-# INLINE attribute #-}
168−
169−-- | Traverse elements which has the specified *local* name (case-insensitive).
170−named :: CI.CI Text -> Traversal' Element Element
171−named n f s
172− | CI.mk (nameLocalName (elementName s)) == n = f s
173− | otherwise = pure s
174−{-# INLINE named #-}
175135
176−-- | Old name for 'named'
177−ell :: Text -> Traversal' Element Element
178−ell n = named $ CI.mk n
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
179140
180141-- | Traverse elements which has the specified name.
181142el :: Name -> Traversal' Element Element
182143el n f s
183144 | elementName s == n = f s
184145 | otherwise = pure s
185−{-# DEPRECATED el "Use named instead" #-}
186146
187147attributeSatisfies :: Name -> (Text -> Bool) -> Traversal' Element Element
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 #-}
148+attributeSatisfies n p = filtered (maybe False p . preview (attrs . ix n))
198149
199150attributeIs :: Name -> Text -> Traversal' Element Element
200151attributeIs n v = attributeSatisfies n (==v)
201−{-# INLINE attributeIs #-}
202152
203153-- | Traverse all contents of the element.
204154text :: Traversal' Element Text
205155text = nodes . traverse . _Content
206−{-# INLINE text #-}
207156
208157-- | Traverse all comments of the element.
209158comment :: Traversal' Element Text
210159comment = nodes . traverse . _Comment
211−{-# INLINE comment #-}
212160
213−-- | 'plate' traverses over its sub-elements.
214161instance Plated Element where
215162 plate = nodes . traverse . _Element
216− {-# INLINE plate #-}
163+
164+-- | Combine two 'Traversal's just like XPath's slash.
165+--
166+-- @
167+-- l ./ m ≡ l . 'plate' . m
168+-- @
169+(./) :: Plated a => Traversal s t a a -> Traversal a a u v -> Traversal s t u v
170+l ./ m = l . plate . m
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+9−17
@@ -1,20 +1,16 @@
1−cabal-version: 2.4
21name: xml-lens
3−version: 0.3.1
4−synopsis: Lenses, traversals, and prisms for xml-conduit
5−description: This package provides DOM selectors based on lenses and prisms. See README.md for examples
2+version: 0.1.2
3+synopsis: Lenses, traversals, prisms for xml-conduit
4+description:
65homepage: https://github.com/fumieval/xml-lens
7−bug-reports: https://github.com/fumieval/xml-lens/issues
8−license: BSD-3-Clause
6+license: BSD3
97license-file: LICENSE
108author: Fumiaki Kinoshita
119maintainer: Fumiaki Kinoshita <fumiexcel@gmail.com>
12−copyright: Copyright (C) 2021 Fumiaki Kinoshita
13−category: XML
10+copyright: Copyright (C) 2013 Fumiaki Kinoshita
11+category: Control
1412build-type: Simple
15−extra-source-files:
16− README.md
17− CHANGELOG.md
13+cabal-version: >=1.10
1814
1915source-repository head
2016 type: git
@@ -24,9 +20,5 @@ library
2420 default-language: Haskell2010
2521 ghc-options: -Wall
2622 exposed-modules: Text.XML.Lens
27− build-depends: base ==4.*
28− , lens >= 4.0 && < 5.4
29− , containers >= 0.4.0 && < 0.7
30− , text >= 0.7 && < 1.3 || >= 2 && < 2.2
31− , xml-conduit >= 1.1 && < 1.10
32− , case-insensitive
23+ -- other-modules:
24+ build-depends: base ==4.*, lens >= 3.8 && < 4.2, containers >= 0.4.0 && < 0.6, text == 0.11.*, xml-conduit >= 1.1