4

简而言之,这就是我想要完成的事情:

"foo.xml"

<?xml version="1.0"?>
<foo>
  <bar>
    <baz>
      <a>foo</a>
      <a>bar</a>
      <a>baz</a>
    </baz>
  </bar>
</foo>

预期结果(内容"bar.xml"):

<?xml version="1.0"?>
<foo>
  <bar>
    <baz>
      <a>foo!</a>
      <a>bar!</a>
      <a>baz!</a>
    </baz>
  </bar>
</foo>

...我试图解决这个问题:

module Main (main) where

import Control.Monad

import Control.Arrow.ArrowTree
import Text.XML.HXT.Core

main :: IO ()
main = void . runX $ readDocument [] "foo.xml" >>>
       applic >>> writeDocument [withIndent yes] "bar.xml"

applic :: IOSArrow XmlTree XmlTree
applic = getChildren >>> hasName "foo"
--       ^^ because of extra root node (?)
         /> hasName "bar" /> hasName "baz" /> hasName "a" >>> changeText excl

excl :: String -> String
excl = (++ "!")

问题:如何直接编辑选定的元素而不更改/删除它们的根元素?另请注意,该程序不会创建"bar.xml"文件,因此肯定有问题。跟踪显示,应用applic箭头后,文档由三个a元素("foo""bar""baz"; 不带感叹号)组成。

4

1 回答 1

2

我不假装擅长HXT,我用的不多,但我已经通过一些实验得到了你想做的工作。如果有人对 HXT 有更多经验,请随时提供更好的解决方案。

我通过浏览HXT wiki发现了process*函数,比如processTopDownprocessChildren,以及其他几个函数。这些似乎是真正允许改变发生的原因。现在,我假设您的实际用例更复杂,您可能只想选择某个级别的元素。我偶然发现的模式是processChildren与 HXT 版本一起使用的when,而不是那个,Control.Monad因为它们不一样。基本上,我的第一个实现是

applic
    = processChildren
    $ flip when (isElem >>> hasName "foo")
        $ processChildren
        $ flip when (isElem >>> hasName "bar")
            $ processChildren
            $ flip when (isElem >>> hasName "baz")
                $ processChildren
                $ flip when (isElem >>> hasName "a")
                    $ processChildren
                $ flip when isText
                    $ changeText excl

这对我来说真的很丑陋,重复太多了。因此,我将其抽象为更具可读性的内容:

-- Fixity is important here, must be right-associative.
infixr 5 />/
(/>/) :: ArrowXml a => String -> a XmlTree XmlTree -> a XmlTree XmlTree
name />/ action
    = processChildren
    $ action `when` (isElem >>> hasName name)

applic = "foo" />/ "bar" />/ "baz" />/ "a" />/
    processChildren (
        changeText excl `when` isText
    )

所有这些调用都processChildren可能是多余的,特别是如果您只是深入研究结构,但它确实有效,并且不会修改a文件不同部分的其他元素。

于 2015-04-21T20:03:19.287 回答