我有这样的NodeSeq:
<foo>
<baz><bar key1="value1" key2="value2">foobar</bar></baz>
Blah blah blah
<bar key1="value3">barfoo</bar>
</foo>
我想为所有bars'属性添加一个新属性.我现在正在做:
val rule = new RewriteRule() {
override def transform(node: Node): Seq[Node] = {
node match {
case Elem(prefix, "bar", attribs, scope, content@_*) => Elem(prefix, "bar", attribs append Attribute(None, "newKey", Text("newValue"), scala.xml.Null) , scope, content:_*)
case other => other
}
}
}
Run Code Online (Sandbox Code Playgroud)
但问题是它只适用于1个节点.我希望它以递归方式处理所有节点,如果我在for循环中调用转换,我不能用新值替换它们,因为它们变得不可变.我怎么解决这个问题?
这是您自己的解决方案的简化版本(使用 Daniel 的匹配逻辑变体):
def updateBar(node: Node): Node = node match {
case elem @ Elem(_, "bar", _, _, child @ _*) => elem.asInstanceOf[Elem] % Attribute(None, "newKey", Text("newValue"), Null) copy(child = child map updateBar)
case elem @ Elem(_, _, _, _, child @ _*) => elem.asInstanceOf[Elem].copy(child = child map updateBar)
case other => other
}
Run Code Online (Sandbox Code Playgroud)
请注意,此代码与原始代码之间的主要区别在于,此代码从外部处理节点,如下所示,我在第一个答案中添加了一些打印语句:
scala> updateBar(<foo><bar>blabla</bar></foo>)
processing '<foo><bar>blabla</bar></foo>'
processing '<bar>blabla</bar>'
processing 'blabla'
result: 'blabla'
result: '<bar newKey="newValue">blabla</bar>'
result: '<foo><bar newKey="newValue">blabla</bar></foo>'
res1: scala.xml.Node = <foo><bar newKey="newValue">blabla</bar></foo>
Run Code Online (Sandbox Code Playgroud)
虽然您的原始代码是从内到外工作的(简化示例):
scala> xf { <a><b><c/></b></a> }
transforming '<c></c>'
result: '<c></c>'
transforming '<b><c></c></b>'
result: '<b><c></c></b>'
transforming '<a><b><c></c></b></a>'
result: '<a><b><c></c></b></a>'
res4: scala.xml.Node = <a><b><c></c></b></a>
Run Code Online (Sandbox Code Playgroud)
在某些情况下,这两种技术可能会产生不同的结果。
另一个区别是匹配代码稍微冗长:您需要一种情况来实际转换相关元素,并需要一种情况来递归处理子节点。不过,所示的示例可能需要稍微重构一下。
| 归档时间: |
|
| 查看次数: |
5543 次 |
| 最近记录: |