加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

如何更改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>

此页面有一个添加属性的建议,但没有详细介绍一个将当前属性映射到一个函数的方法(这样做会非常困难):
http://www.scalaclass.com/book/export/html/1

我想到的是手动创建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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读