在Scala中修改XML而不发生变异?
我正在尝试替换
XML片段,并且需要一个累加器.假设我有一个填空的问题存储为XML,如下所示:
val q = <text>The capitals of Bolivia are <blank/> and <blank/>.</text> 在某些时候,我想要将这些空白转换为HTML输入元素,我需要能够区分第一个和第二个,所以我可以检查它们. (忽略这样一个事实,在这种情况下,两个首都可以按任意顺序出现 – 这是我以后要处理的头疼.) 感谢StackOverflow上一些可爱的答案,我制作了以下解决方案: import scala.xml._ import scala.xml.transform._ class BlankReplacer extends BasicTransformer { var i = 0 override def transform(n: Node): NodeSeq = n match { case <blank/> => { i += 1 <input name={ "blank.%d".format(i) }/> } case elem: Elem => elem.copy(child=elem.child.flatMap(transform _)) case _ => n } } 这个工作得相当好.我每次想要开始重新编号时都要创建一个新的BlankReplacer(),但它几乎可以工作: scala> new BlankReplacer()(q) res6: scala.xml.Node = <text>The capitals of Bolivia are <input name="blank.1"></input> and <input name="blank.2"></input>.</text> 这是问题所在.是否有一种简单的方法可以避免每次更换< blank />时我必须做的突变?我所拥有的并不会让我觉得太可怕,但我认为如果我每次将问题转换为HTML时都没有创建BlankReplacer类的新实例,那么这可能会更清晰.我确定有一些方法可以将它变成累加器,但我不知道该怎么做. 谢谢! 解决方法
Scales Xml提供折叠路径,允许您“修改”树并积累…
import scales.utils._ import ScalesUtils._ import scales.xml._ import ScalesXml._ // the xml example val q = <("text") /( "The capitals of Bolivia are ",<("blank")," and ",".") // which elems to fold on? val p = top(q) * "blank" val f = foldPositions(p,p.size){ // size is used as the starting point for the fold case (question,path) => (question - 1,Replace( <("input") /@ ("name" -> ("blank."+question) )) ) } // f is an either,so we assuming its working here,and ._1 is the accumalator,_.2 the Path val newTree = f.left.get._2.tree 唯一的怪癖是它以反向文档顺序累积,还有一个非累积版本.当某些变形具有破坏性时,这允许变换的组合(例如,更改子变量然后在另一个变换中删除它只是起作用). 折叠本身的输入是任何Iterable of Paths,只要它们在同一个树中,允许您根据需要组合查询. See here for more details on how to Fold Xml in Scales (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |