Im writing a pickler for OpenTable xml files. It's the first time I use HXT, and I have some problems.
My first problem is that bindings is a list of multiple kinds of elements. How would I write the bindings pickler?
Im including the full source
Haskell data type:
module OpenTable
where
data OpenTable = OpenTable { meta :: Meta
, bindings :: [Binding]
} deriving (Read, Show)
data Meta = Meta { metaApiKeyURL :: Maybe String
, metaAuthor :: Maybe String
, metaDocumentationURL :: Maybe String
, metaDescription :: Maybe String
, metaSampleQuery :: Maybe String
} deriving (Read, Show)
data Binding = SelectBinding Select
| InsertBinding Insert
| UpdateBinding Update
| DeleteBinding Delete
deriving (Read, Show)
data Select = Select { selectItemPath :: Maybe String
, selectPollingFrequencySeconds :: Maybe Integer
, selectProduces :: Maybe String
, selectUrls :: [String]
, selectInputs :: [Input]
} deriving (Read, Show)
....
Parser:
module Main
where
import System.Environment
import Text.XML.HXT.Core
import OpenTable
main :: IO ()
main
= do
[file] <- getArgs
parseYQL file
return ()
instance XmlPickler OpenTable where
xpickle = xpOpenTable
xpOpenTable :: PU OpenTable
xpOpenTable
= xpElem "table" $
xpWrap ( uncurry OpenTable
, \ot -> (meta ot, bindings ot)) $
xpPair xpMeta xpBindings
instance XmlPickler Meta where
xpickle = xpMeta
xpMeta :: PU Meta
xpMeta
= xpElem "meta" $
xpWrap ( \ ((api, aut, doc, des, sam)) -> Meta api aut doc des sam
, \ m -> (metaApiKeyURL m, metaAuthor m, metaDocumentationURL m,
metaDescription m, metaSampleQuery m)) $
xp5Tuple
(xpOption $ xpElem "apiKeyUrl" xpText)
(xpOption $ xpElem "author" xpText)
(xpOption $ xpElem "documentationURL" xpText)
(xpOption $ xpElem "description" xpText)
(xpOption $ xpElem "sampleQuery" xpText)
xpBindings :: PU [Binding]
xpBindings = xpElem "bindings" $
xpList xpBinding
instance XmlPickler Binding where
xpickle = xpBinding
xpBinding :: PU Binding
xpBinding = undefined
parseYQL file
= runX ( xunpickleDocument xpOpenTable [] file
>>>
xpickleDocument xpOpenTable [] "dst.xml" )
OpenTable XML:
<?xml version="1.0" encoding="UTF-8"?>
<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd">
<meta>
<sampleQuery>select * from {table} where q="this is a test" and target="de";</sampleQuery>
</meta>
<bindings>
<select itemPath="json" produces="JSON">
<urls>
<url>http://translate.google.com/translate_a/t?client=x&text={q}&sl={source}&tl={target}</url>
</urls>
<inputs>
<key id='q' type='xs:string' paramType='query' required="true" />
<key id='source' type='xs:string' paramType='path' default="auto" />
<key id='target' type='xs:string' paramType='path' required="true" />
</inputs>
</select>
</bindings>
</table>
HXT provides the xpAlt :: (a -> Int) -> [PU a] -> PU a
function for sum data types. The first argument maps values of the sum type a
to Int
s which are then used as an index into the list of PU a
s in the second argument, i.e. an appropriate PU a
will be selected based on the the a
value passed to the function in the first argument.
For your code, you might try something like:
xpBinding :: PU Binding
xpBinding = xpAlt tag ps
where
tag (SelectBinding s) = 0
tag (InsertBinding i) = 1
-- ...
ps = [ xpSelectBinding
, xpInsertBinding
-- ...
]
xpSelectBinding :: PU Binding
xpSelectBinding = ...
xpInsertBinding :: PU Binding
xpInsertBinding = ...