2011-03-03 53 views
6

我想解析一个XML,但我想过滤和提取一个给定的节点只有确定数量的孩子。例如:计数和过滤箭头为HXT

<root> 
    <node id="a" /> 
    <node id="b" /> 
    <node id="c" /> 
    <node id="d" /> 
</root> 

然后,如果我执行箭头getChildren >>> myFilter 2,我还是会回到只有ID节点“A”和“B”。

直觉让我应该使用状态箭头来跟踪,但我不知道该怎么做。

我试图自己做,但它不完全是我想要的,不看起来非常优雅,并且不起作用。我尝试用runSLA和整数参数作为初始状态运行我的箭链,然后定义:

takeOnly :: IOSLA Int XmlTree XmlTree 
takeOnly = changeState (\s b -> s-1) 
      >>> accessState (\s b -> if s >= 0 then b else Nothing) 

但我当然不能返回Nothing,我需要返回一个XmlTree。但我根本不想回报任何东西!

这里可能有更好的方法。你可以帮我吗?

感谢您的时间和帮助!

回答

4

使用Control.Arrow.ArrowList中的组合器来处理这种事情可能更习惯使用。

该软件包专门提供了(>>.) :: a b c -> ([c] -> [d]) -> a b d,它是一个“用于将列表箭头的结果转换为另一个列表的组合程序”。这使我们可以使用我们已经在此上下文中使用的take函数。

这里是如何使用它的快速版本:

module Main where 

import Text.XML.HXT.Arrow 

takeOnly :: (ArrowXml a) => Int -> a XmlTree XmlTree 
takeOnly n = getChildren >>. take n 

main = do 
    let xml = "<root><node id='a' /><node id='b' />\ 
        \<node id='c' /><node id='d' /></root>" 

    print =<< runX (readString [] xml >>> getChildren >>> takeOnly 2) 

这我相信没有什么左右你要找的:

[email protected]% ./ArrowTake 
[NTree (XTag (LP node) [NTree (XAttr (LP id)) [NTree (XText "a") []]]) [], 
NTree (XTag (LP node) [NTree (XAttr (LP id)) [NTree (XText "b") []]]) []] 

无需IOSLA。请注意,我也稍微改变了函数类型 - 这个版本对我来说似乎更好,但是您可以很容易地将它转换为更类似于您的版本的类型。

+0

哇!这正是我正在寻找的,谢谢!因为很明显我对箭头很新颖......但我爱他们,现在更多^^ – 2011-03-04 00:08:00