如何更改Scala XML元素的属性
发布时间:2020-12-16 09:39:21 所属栏目:安全 来源:网络整理
导读:我有一个XML文件,我想使用脚本映射一些属性。例如: a b attr1 = "100" attr2 = "50"//a 可能有属性按比例缩放: a b attr1 = "200" attr2 = "100"//a 此页面有一个添加属性的建议,但没有详细介绍一个将当前属性映射到一个函数的方法(这样做会非常困难):
我有一个XML文件,我想使用脚本映射一些属性。例如:
<a> <b attr1 = "100" attr2 = "50"/> </a> 可能有属性按比例缩放: <a> <b attr1 = "200" attr2 = "100"/> </a> 此页面有一个添加属性的建议,但没有详细介绍一个将当前属性映射到一个函数的方法(这样做会非常困难): 我想到的是手动创建XML(非scala)链接列表…如下所示: // a typical match case for running thru XML elements: case Elem(prefix,e,attributes,scope,children @ _*) => { var newAttribs = attributes for(attr <- newAttribs) attr.key match { case "attr1" => newAttribs = attribs.append(new UnprefixedAttribute("attr1",(attr.value.head.text.toFloat * 2.0f).toString,attr.next)) case "attr2" => newAttribs = attribs.append(new UnprefixedAttribute("attr2",attr.next)) case _ => } Elem(prefix,newAttribs,updateSubNode(children) : _*) // set new attribs and process the child elements } 它的可怕,冗长和不必要地重新命令输出中的属性,这对我目前的项目是坏的,由于一些坏的客户端代码。有这样做的scala方式吗? 解决方法
好的,尽力而为,Scala 2.8。我们需要重构属性,这意味着我们必须正确地分解它们。让我们创建一个功能:
import scala.xml._ case class GenAttr(pre: Option[String],key: String,value: Seq[Node],next: MetaData) { def toMetaData = Attribute(pre,key,value,next) } def decomposeMetaData(m: MetaData): Option[GenAttr] = m match { case Null => None case PrefixedAttribute(pre,next) => Some(GenAttr(Some(pre),next)) case UnprefixedAttribute(key,next) => Some(GenAttr(None,next)) } 接下来,我们将链接属性分解成一个序列: def unchainMetaData(m: MetaData): Iterable[GenAttr] = m flatMap (decomposeMetaData) 在这一点上,我们可以轻松地操纵这个列表: def doubleValues(l: Iterable[GenAttr]) = l map { case g @ GenAttr(_,_,Text(v),_) if v matches "d+" => g.copy(value = Text(v.toInt * 2 toString)) case other => other } 现在,再次链接: def chainMetaData(l: Iterable[GenAttr]): MetaData = l match { case Nil => Null case head :: tail => head.copy(next = chainMetaData(tail)).toMetaData } 现在,我们只需要创建一个函数来处理这些事情: def mapMetaData(m: MetaData)(f: GenAttr => GenAttr): MetaData = chainMetaData(unchainMetaData(m).map(f)) 所以我们可以这样使用: import scala.xml.transform._ val attribs = Set("attr1","attr2") val rr = new RewriteRule { override def transform(n: Node): Seq[Node] = (n match { case e: Elem => e.copy(attributes = mapMetaData(e.attributes) { case g @ GenAttr(_,_) if attribs contains key => g.copy(value = Text(v.toInt * 2 toString)) case other => other }) case other => other }).toSeq } val rt = new RuleTransformer(rr) 最后让你做你想要的翻译: rt.transform(<a><b attr1="100" attr2="50"></b></a>) 所有这一切可以简化为: >属性实际定义的前缀,键和值,带有可选的前缀属性是序列,而不是链属性有一个map,mapKeys,mapValues> Elem有一个mapAttribute (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
相关内容