HXT:在Haskell中使用HXT按位置选择节点?

2024-01-31

我正在尝试使用 Haskell 解析一些 XML 文件。对于这项工作我正在使用HXT http://www.haskell.org/haskellwiki/HXT获得有关现实世界应用中箭头的一些知识。所以我对箭头主题很陌生。

在 XPath 中(和HaXml http://hackage.haskell.org/packages/archive/HaXml/1.24/doc/html/Text-XML-HaXml-Combinators.html#v%3aposition)可以按位置选择节点,比方说:/root/a[2]/b

即使一遍又一遍地阅读文档后,我也不知道如何使用 HXT 做类似的事情。

这是我正在使用的一些示例代码:

module Main where

import Text.XML.HXT.Core

testXml :: String
testXml = unlines
    [ "<?xml version=\"1.0\"?>"
    , "<root>"
    , "    <a>"
    , "        <b>first element</b>"
    , "        <b>second element</b>"
    , "    </a>"
    , "    <a>"
    , "        <b>third element</b>"
    , "    </a>"
    , "    <a>"
    , "        <b>fourth element</b>"
    , "        <b>enough...</b>"
    , "    </a>"
    , "</root>"
    ]

selector :: ArrowXml a => a XmlTree String
selector = getChildren /> isElem >>> hasName "a" -- how to select second <a>?
                       /> isElem >>> hasName "b"
                       /> getText

main :: IO ()
main = do
    let doc = readString [] testXml
    nodes <- runX $ doc >>> selector
    mapM_ putStrLn nodes

期望的输出是:

third element

提前致谢!


我相信的解决方案选择“/root/a[2]/b”(第二个“a”标签内的所有“b”标签):

selector :: ArrowXml a => Int -> a XmlTree String
selector nth =
    (getChildren /> isElem >>> hasName "a")   -- the parentheses required!
    >. (!! nth) 
    /> isElem >>> hasName "b" /> getText

(结果是["third element"]).

说明:据我所知,class (..., ArrowList a, ...) => ArrowXml a, so ArrowXml a是一个子类ArrowList。翻翻ArrowList界面:

(>>.) :: a b c -> ([c] -> [d]) -> a b d
(>.) :: a b c -> ([c] -> d) -> a b d

so >>.可以使用一些提升来选择列表的子集[c] -> [d] and >.可以使用 type 的提升函数从列表中选择单个项目[c] -> d。因此,在选择子项并过滤标签“a”之后,让我们使用(!! nth) :: [a] -> a.

有一个重要的事情需要注意:

infix 1 >>>
infix 5 />
infix 8 >.

(所以我很难弄清楚为什么>.没有括号则无法按预期工作)。因此,getChildren /> isElem >>> hasName "a"必须用括号括起来。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

HXT:在Haskell中使用HXT按位置选择节点? 的相关文章

随机推荐