杀鸡也用牛刀,Haskell 处理 XML 文档小试
来源:互联网 发布:js调用浏览器下载功能 编辑:程序博客网 时间:2024/04/29 19:56
平常经常用千千静听来听音乐,长期以来就形成了一个自己最喜欢听的音乐列表。这几天想把这些音乐全部复制到U盘,插在车上,开车的时候也可以听听。但是每个MP3、WMA分散在不同的文件夹,一个个复制的话工作量就大了。我的音乐列表一般存为千千静听的 *.ttpl 格式,其本质就是一个 XML 文件。一般格式如下:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?><ttplaylist title="[默认]" version="4" generator="TTPlayer -- 5.9.6"><format tagtitle="%A - %T" deftitle="%F"/><items count="163"><item file="E:\incomings\cd3\I Still Believe.mp3" title="I Still Believe" len="287111"/><item file="E:\incomings\cd3\When You Believe.mp3" title="When You Believe" len="273136"/></items></ttplaylist>
每个 item 节点中都有一个 file 属性,保存了 MP3 文件的具体位置。可以通过读取这个属性,找到 MP3 文件,再自动的把文件复制到 U 盘中。这个过程就是基本的读取 XML 节点属性、复制文件的操作,使用 Python 就可以轻松实现。但是最近学习了 Haskell,刚好可以用它来试试。
Haskell 中可以实现 XML操作的库有很多,比如 HaXml、HXT、xml 等。本文采用最简单的 xml 库。安装 xml 库时可以使用 Haskell 的安装工具 Cabal 来自动安装:cabal install xml。有一些音乐文件可能是中文的文件名,经过测试,Haskell 不支持 ANSI 形式的中文路径、文件名的文件操作。所以还需要调用 UTF8 的库:cabal install utf8-string。
首先,需要将 Prelude 中的 readFile 隐藏,使用 UTF8 的 readFile,这样子后面才能识别 ttpl 中的中文路径。
import Prelude hiding (readFile)import System.IO.UTF8 (readFile)
然后,载入 xml 的相关库。
import Text.XML.Light.Inputimport Text.XML.Light.Outputimport Text.XML.Light.Procimport Text.XML.Light.Typesimport Data.Maybeimport Data.List
最后,载入复制文件的相关库。
import System.Directory
接下来,写一个解析 XML 文件的函数。
parse s = let contents = parseXML s quotes = concatMap (findElements $ qqName "item") (onlyElems contents) symbols = map (findAttr $ qqName "file") quotes files = map fromJust symbols qqName name = QName name Nothing Nothing in files
上面的 s 是从文件读取进来的文本内容。将这个文本使用 parseXML 解析,得到 content 的数组。使用 onlyElems 取所有的有效元素,交给 findElements 函数来找出所有节点名字为 item 的节点。然后将这些节点的 file 属性值取出来,构成一个数组作为 parse 函数的返回值。可见,使用 Haskell 这样的函数式编程语言来处理问题时,思维方式确实与命令式编程语言有着很大的不同。
接着,再写一个函数将找出来的所有文件复制到 U 盘中。
copyMP3 [] = do return () copyMP3 (x:xs) = do let output = "U:\\" ++ findFilename x copyFile x output copyMP3 xs
copyMP3 函数将递归数组,将所有的文件复制到 U:\ 路径下。copyFile 是 System.Directory 中的一个函数,它的两个参数中如果含有中文,必须使用 UTF8 才能被正确识别,否则总是返回“找不到文件”的提示。因此,前面就需要引用 UTF8 的库。fileFilename 函数是从完整的路径(如:E:\incomings\cd3\I Still Believe.mp3)中提取出文件名(I Still Believe.mp3) 。函数定义如下:
findFilename s = drop (length s - (fromJust $ findIndex (=='\\') $ reverse s)) s
这里用到了 Data.List 中的多个方法,可能还会有更优雅的写法。最后就是在 main 函数中将所有功能组合起来。
main = do s <- readFile "r:\\test.ttpl" copyMP3 $ parse s putStrLn "ok"
最后,将所有代码保存到 CopyMP3.hs 文件中。可以使用 runhaskell CopyMP3.hs 来运行,或者使用 ghc -o CopyMP3.exe CopyMP3.hs 将它编译成 exe 之后再运行。
- 杀鸡也用牛刀,Haskell 处理 XML 文档小试
- C# 处理XML文档
- 处理XML文档
- Linq处理XML文档
- javascript xml 文档处理
- SAX --- 处理 XML 文档
- Haskell小程序
- Haskell小例子
- 用JDOM处理XML文档
- 使用SAX处理XML文档
- 用JDOM处理XML文档
- 使用JAXB处理XML文档
- 怎样用c#处理xml文档.
- java处理XML文档-JDOM
- 用JDOM处理XML文档
- 用XmlBeans处理XML文档
- 利用java处理XML文档
- 使用JAXB处理XML文档
- myeclipse中的所有快捷键列表:
- 没有迅雷会员?用QQ离线吧
- JS 传递超长参数。JS传递长字符串
- Eclipse中开辟Ruby碰到invalid multibyte char (US-ASCII)
- 不知所终
- 杀鸡也用牛刀,Haskell 处理 XML 文档小试
- 我的SEO之路2012年10月31日
- mysql存储过程详解
- 两种dlx解法比较 以及靶形数独
- 【项目1扩展(选做)】从键盘输入20个整数,输出它们的和
- 知易游戏开发教程cocos2d-x移植版004
- java-自定义异常操作
- reduce task 数量
- 弹出小键盘的安全密码输入器 密码安全 小键盘