在Haskell中更新DOM
我需要从文档中深度选择一个XML节点并对其进行转换,然后将其移动到另一个位置 此示例取自以下内容并稍作更改: 选择//d/e/f,然后更改f处的内容,并将新的f节点移动到a下 我需要多次执行此类操作,因此如果更新操作是可组合的,则效果更好在Haskell中更新DOM,haskell,Haskell,我需要从文档中深度选择一个XML节点并对其进行转换,然后将其移动到另一个位置 此示例取自以下内容并稍作更改: 选择//d/e/f,然后更改f处的内容,并将新的f节点移动到a下 我需要多次执行此类操作,因此如果更新操作是可组合的,则效果更好 我正在查看xml导管包,但它似乎缺少DOM操作功能,执行此类任务的最佳方法是什么?我对HXT非常陌生,因此可能有更好的方法,但我解决了类似的问题,如: {-# OPTIONS_GHC -Wall #-} {-# LANGUAGE Arrows, NoMonom
我正在查看xml导管包,但它似乎缺少DOM操作功能,执行此类任务的最佳方法是什么?我对HXT非常陌生,因此可能有更好的方法,但我解决了类似的问题,如:
{-# OPTIONS_GHC -Wall #-}
{-# LANGUAGE Arrows, NoMonomorphismRestriction #-}
module Abc where
import Text.XML.HXT.Core
moveElts :: ArrowXml a => a XmlTree XmlTree
moveElts =
processTopDown (
-- Insert <f>'s under <a>:
slurpF `when` hasName "a"
>>>
-- and remove the old <f>'s:
removeChildrenExcept "f" `when` neg (hasName "a")
)
where
removeChildrenExcept tag =
replaceChildren (getChildren >>> neg (hasName tag))
slurpF = proc a -> do
elts <- deep (hasName "f") -< a
returnA (insertChildrenAt 0 (constA elts)) -<< a
-- Test:
test :: IO ()
test = runX (readDocument [withValidate no] "abc.xml"
>>> moveElts
>>> writeDocumentToString [withIndent yes])
>>= putStrLn . head
你所说的DOM操纵是什么意思?与Haskell中的大多数数据结构一样,xml管道使用的数据结构是不可变的。转换XML树的方法是创建一个新的树。如果你能更详细地描述你想要实现的目标,你可能会得到更多的信息。@MichaelSnoyman谢谢Michael,我已经更新了问题,并且阅读了你的问题解决方案,但是我不想将选择逻辑硬编码成递归,如果xml导管有更新或插入功能就好了。@MichaelSnoyman同样,似乎xml导管是使用Zipper实现的,选择f cur$//element d$/element e$/element f很容易,但是如果我做了一些更改并想返回到原始树中进行更改,我该怎么办?拉链孔和拉链上下文构成了整棵树,它应该有返回的方式,对吗?我曾经在反XML中使用过这个,请看这里:从“现在开始”一段中的棘手部分开始。XML管道API并不鼓励这种用法。然而,它看起来正是镜头包装所支持的那种用法。我自己没有用过,但我建议看一看。@MichaelSnoyman xml lens似乎是一个基于镜头的xml选择器,不进行转换,xml管道轴也可以进行选择工作。我觉得xml管道只有zippers导航功能,加上一些过滤器,但没有合并上下文和聚焦回原始树功能,这些功能也很有用。
{-# OPTIONS_GHC -Wall #-}
{-# LANGUAGE Arrows, NoMonomorphismRestriction #-}
module Abc where
import Text.XML.HXT.Core
moveElts :: ArrowXml a => a XmlTree XmlTree
moveElts =
processTopDown (
-- Insert <f>'s under <a>:
slurpF `when` hasName "a"
>>>
-- and remove the old <f>'s:
removeChildrenExcept "f" `when` neg (hasName "a")
)
where
removeChildrenExcept tag =
replaceChildren (getChildren >>> neg (hasName tag))
slurpF = proc a -> do
elts <- deep (hasName "f") -< a
returnA (insertChildrenAt 0 (constA elts)) -<< a
-- Test:
test :: IO ()
test = runX (readDocument [withValidate no] "abc.xml"
>>> moveElts
>>> writeDocumentToString [withIndent yes])
>>= putStrLn . head