微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

xml – Scala:修改NodeSeq

我有这样的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 举报,一经查实,本站将立刻删除。