xml-lens API惊喜:功能组合和旅行

时间:2014-11-28 16:22:10

标签: haskell xml-parsing lens

以下表达方式的意图有何不同?我很惊讶他们实际上在下面的例子中输入检查并产生不同的结果。

(./) ::
  Plated a =>
  Traversal s t a a -> Traversal a a u v -> Traversal s t u v
        -- Defined in âText.XML.Lensâ
infixr 9 ./

(.) :: (b -> c) -> (a -> b) -> a -> c   -- Defined in âGHC.Baseâ
infixr 9 .

它们如何与典型的pom.xml文件一起使用:

*Main> x ^.. root ./ ell "version" . text
["1.0-SNAPSHOT"]
*Main> x ^.. root ./ ell "version" ./ text
[]

,其中

text ::
  Control.Applicative.Applicative f =>
  (Data.Text.Internal.Text -> f Data.Text.Internal.Text)
  -> Element -> f Element
        -- Defined in âText.XML.Lensâ

data Element
  = Element {elementName :: Name,
             elementAttributes :: containers-0.5.5.1:Data.Map.Base.Map
                                    Name Data.Text.Internal.Text,
             elementNodes :: [Node]}
        -- Defined in âText.XMLâ
instance Plated Element -- Defined in âText.XML.Lensâ

1 个答案:

答案 0 :(得分:2)

(./)基于Plated实例,该实例是具有相同类型“子”的类型。 HTML元素,数学表达式的AST等等。

这里(.)只是遍历链。所以

*Main> x ^.. root ./ ell "version" . text
["1.0-SNAPSHOT"]

使用本地名称==“version”转到根节点的所有子节点,并收集其中的文本内容。 (这里只有一个这样的节点)

然而,

(./)增加了一个额外的步骤。

*Main> x ^.. root ./ ell "version" ./ text
[]

这适用于具有本地名称==“version”的根节点的任何子节点,然后关注这些节点的所有子节点并选择其中的文本内容。如果没有找到子项,则生成的遍历很可能不会指向任何结果,这可能是您获得空列表的原因。

基本上,l ./ l'遍历l所描述的内容,产生了许多目标,然后将焦点从这些目标中的每一个切换到“相同类型的孩子”(如Plated实例),然后使用l'遍历这些。

请注意,您必须在root之后使用./,因为您希望下载到根节点的所有直接子节点,只选择具有您感兴趣的名称的子节点。但是在查看"version"元素的内容时,您只需要内部的直接内容,无需进一步遍历子元素,因此必须使用(.)而不是{{1 }}