Reputation: 23
I need to have a possibility to update text in structure like this <node><data key="attr">text</data></node>
. Is there any way to do this by using HXT library in haskell?
Upvotes: 2
Views: 159
Reputation: 2909
The natural answer is a lens library; I don't think hxt
has such a thing associated with it. But there is xml-lens
which uses xml-conduit
(but not conduits in fact)
The examples in the readme https://github.com/fumieval/xml-lens are fairly straightforward, but maybe a bit operator-clogged, if you aren't familiar with lenses. But here is less dense version of one of the examples. It modifies each page number in a book list by adding " pages" to it, changing
<pages>360</pages>
to
<pages>360 pages</pages>
starting with an XML like this:
<?xml version="1.0" encoding="ISO-8859-1"?>
<books>
<book category="Textbooks">
<title>Learn You a Haskell for Great Good!</title>
<author year="2011">Miran Lipovaca</author>
<pages>360</pages>
</book>
<book category="Textbooks">
<title>Programming in Haskell</title>
<author year="2007">Graham Hutton</author>
<pages>200</pages>
</book>
</books>
We need imports like these
>>> import Text.XML.Lens -- from the lens-xml package
>>> import Control.Lens -- from the lens package
>>> import Text.XML -- from the xml-conduit package
>>> import Data.Monoid ((<>))
>>> import qualified Data.Text as T
>>> import qualified Data.ByteString.Lazy.Char8 as BL
>>> :set -XOverloadedStrings -- for Text literals
First I define the traversal that targets what I want to change:
>>> let my_focus = root . el "books" ./ el "book" ./ el "pages" . text
then I define an ordinary Haskell function in terms of it, using over some_traversal some_function
>>> let my_transformation = over my_focus (<> " pages") -- i.e. apply (<> " pages") to
>>> :t my_transformation -- all the focused positions
my_transformation :: Document -> Document
read the document:
>>> doc <- Text.XML.readFile def "book.xml"
>>> :t doc
doc :: Document
and then transform and render it:
>>> BL.putStrLn $ renderLBS def (my_transformation doc)
<?xml version="1.0" encoding="UTF-8"?><books>
<book category="Textbooks">
<title>Learn You a Haskell for Great Good!</title>
<author year="2011">Miran Lipovaca</author>
<pages>360 pages</pages>
</book>
<book category="Textbooks">
<title>Programming in Haskell</title>
<author year="2007">Graham Hutton</author>
<pages>200 pages</pages>
</book>
</books>
This might be a little slow given the fancy apparatus it is using below the surface, but is plainly crazy powerful.
Upvotes: 2