Pergunta

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&amp;text={q}&amp;sl={source}&amp;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>
Foi útil?

Solução

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 Ints which are then used as an index into the list of PU as 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 = ...
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top