我有一个包含一些数据的 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 中。在示例代码中,我隐式给出了列名,但我希望它从列表中读取,在箭头函数中应用并返回行。
最佳答案
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 箭头的东西。一个 monad 是一个箭头,但你必须将它包装到它的 Kleisli 类别中。 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"]
我还没有测试最后一个 - 请检查!
关于xml - 在 Haskell 中为箭头函数提供参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13554051/
我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)
两者都可以defsetup(options={})options.reverse_merge:size=>25,:velocity=>10end和defsetup(options={}){:size=>25,:velocity=>10}.merge(options)end在方法的参数中分配默认值。问题是:哪个更好?您更愿意使用哪一个?在性能、代码可读性或其他方面有什么不同吗?编辑:我无意中添加了bang(!)...并不是要询问nobang方法与bang方法之间的区别 最佳答案 我倾向于使用reverse_merge方法:option
我正在尝试用ruby中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了
我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin
我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano