我有这样的NodeSeq:
< FOO>
< baz>< bar key1 =“value1”key2 =“value2”> foobar< / bar>< / baz>
等等等等等等
< bar key1 =“value3”> barfoo< / bar>
< /富>
val rule = new RewriteRule() { override def transform(node: Node): Seq[Node] = { node match { case Elem(prefix,"bar",attribs,scope,content@_*) => Elem(prefix,attribs append Attribute(None,"newKey",Text("newValue"),scala.xml.Null),content:_*) case other => other } } }
但问题是它只适用于1个节点.我希望它以递归方式处理所有节点,如果我在for循环中调用转换,我不能用新值替换它们,因为它们变得不可变.我怎么解决这个问题?
解决方法
以下是您自己的解决方案的简化版本(使用Daniel的匹配逻辑变体):
def updateBar(node: Node): Node = node match { case elem @ Elem(_,_,child @ _*) => elem.asInstanceOf[Elem] % Attribute(None,Null) copy(child = child map updateBar) case elem @ Elem(_,child @ _*) => elem.asInstanceOf[Elem].copy(child = child map updateBar) case other => other }
请注意,这与原始代码之间的主要区别在于,这个与外部处理节点,如此处所示,我在第一个答案中添加了一些打印语句:
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>
虽然您的原始代码从内到外工作(简化示例):
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>
有可能这两种技术会产生不同的结果.
另一个区别是匹配代码稍微冗长:你需要一个案例来实际转换相关元素,还有一个案例用于递归处理子节点.但是,显示的示例可能会稍微重构一下.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。