3

いくつかのデータを含む XML ファイルがあります。このファイルには、列とデータ自体の説明が含まれています。列名は読み取れますが、データを返す関数にこの行名を与える方法がわからないため、データを読み取ることができません。

XML ファイル:

<?xml version="1.0" encoding="UTF-8"?>
<Document>
<Header>
<Project code="SOME PROJECT" label="PROJECT LABEL"></Project>
<Datatable name="LOG" label="Visits"></Datatable>
<Columns>
    <column name="study" label="Study" ordinal="1" type="TEXT"></column>
    <column name="site" label="Site" ordinal="2" type="INTEGER"></column>
    <column name="number" label="Subject" ordinal="3" type="INTEGER"></column>
    <column name="visit" label="Visit number" ordinal="4" type="CHARACTER VARYING(20)">     
 </column>
 <column name="vdate" label="Visit date (dd/mm/yyyy)." ordinal="5" type="CHARACTER   VARYING(10)"></column>
</Columns>
</Header>

<table xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

   <row>
   <study>Some study</study>
   <site>1</site>
   <number>1</number>
   <visit>1</visit>
   <vdate>28/12/2010</vdate>
   </row>

   <row>
   <study>Some study</study>
   <site>1</site>
   <number>1</number>
   <visit>2</visit>
   <vdate>03/03/2011</vdate>
   </row>

   <row>
   <study>Some study</study>
   <site>1</site>
   <number>1</number>
   <visit>3</visit>
   <vdate>09/06/2011</vdate>
   </row>

   </table>
   </Document>

サンプルコード:

{-# LANGUAGE Arrows #-}

import Text.XML.HXT.Core
import Data.Tree.NTree.TypeDefs

parseXML :: String -> IOStateArrow s b XmlTree
parseXML file = readDocument [ withValidate yes
                             , withRemoveWS yes
                             ] file

atTag :: ArrowXml a => String -> a (NTree XNode) XmlTree
atTag tag = deep (isElem >>> hasName tag)

text :: ArrowXml cat => cat (NTree XNode) String
text = getChildren >>> getText

getRowsData :: ArrowXml cat => cat (NTree XNode) [String]
getRowsData = atTag "table" >>>
    proc l ->  do
        row <- atTag "row" -< l

        study <- text <<< atTag "study" -< row
        site <- text <<< atTag "site" -< row
        returnA -< [study,site]

readTable :: ArrowXml t => t (NTree XNode) [[String]]
readTable =
    proc l -> do
        rows <- listA getRowsData -< l

        returnA -< rows

main :: IO ()
main = do
    res <- runX ( parseXML "log.xml" >>> readTable )
    print res

私にとっての問題はgetRowsData. サンプル コードでは列名を暗黙的に指定しましたが、リストから読み取り、アロー関数で適用して行を返すようにしたいと考えています。

4

1 に答える 1

2
import Control.Arrow

矢印のリストを結合する

あなたが探しているのは、同じ入力に複数の矢印を組み合わせて出力を一覧表示する方法だと思います。

list :: Arrow a => [a b c] -> a b [c]
list [] = returnA >>^ const []
list (a:as) = (a &&& list as) >>^ uncurry (:)

(a &&& list as)頭と尻尾のペアを返し、それらを再結合する>>^ために純粋な関数を事後適用しuncurry (:) :: (x,[x]) -> [x]ます。

テストしてみましょう。ここでは、IO 矢印で遊ぶいくつかのことを示します。モナドは矢ですが、クライスリ カテゴリにラップする必要があります。runKleisliもう一度アンラップして実行できるようにしますが、入力に時間がかかりすぎるため、中置バージョンを使用>$>して入力をフィードしました。

ask :: Kleisli IO String String
ask = Kleisli $ \xs -> putStrLn xs >> getLine

(>$>) = runKleisli

そのため、対話が簡単になりました。

*Main> ask >$> "Hello?"
Hello?
Hello!
"Hello!"

そして正常にlist動作します:

*Main> list [ask,ask] >$> "say something!"
say something!
OK
say something!
What do you want me to say?
["OK","What do you want me to say?"]

[文字列] から [文字列] を返す矢印へ

しかし、文字列のリストを、文字列のリストを生成する矢印に変えたいとします。

appList :: Arrow a => (s -> a b c) -> [s] -> a b [c]
appList f xs = list (map f xs)

ask テストのバリアントでそれをテストできます。

askRespond xs = Kleisli $ \thx -> do
                       putStrLn xs 
                       ans <- getLine
                       putStrLn thx
                       return ans

appListしたがって、各文字列から矢印を作成し、それぞれを実行して、回答を文字列に再度結合することにより、希望どおりに機能していることがわかります。

*Main> appList askRespond ["What's your name?","What's your favourite colour?","Would you like some cheese?"]  >$> "Thanks."
What's your name?
Andrew
Thanks.
What's your favourite colour?
Green
Thanks.
Would you like some cheese?
Yes - could I have gruyere?
Thanks.
["Andrew","Green","Yes - could I have gruyere?"]

複数のタグのコンテンツを取得する

これをあなたの問題に当てはめてみましょう。

まず、文字列から矢印を作成するための省略形を作成しましょう。

textAtTag xs = text <<< atTag xs 

次に、使用しましょうappList

getRowsData = atTag "table" 
          >>> atTag "row"
          >>> appList textAtTag ["study","site"]

私は最後のものをテストしていません - 確認してください!

于 2012-11-26T01:36:19.157 に答える