【问题标题】:How can I transform only the top level nodes of an xml file in scala (not the descendants)如何在 scala 中仅转换 xml 文件的顶级节点(而不是后代)
【发布时间】:2014-08-06 21:30:08
【问题描述】:

我有一些 xml,其中在顶层有一个 <id/> 节点,也在后代节点内。有没有办法让我在顶层而不是低层更改值?

示例输入是

val inputXml = 
  <top>
    <id>123</id>
    <a>
      <id>innerId</id>
    </a>
    <b>other info</b>
    <c>
      <id>444</id>
    </c>
  </top>

我想看到的输出是:

val expectedOutputXml =
  <top>
    <id>999</id>
    <a>
      <id>innerId</id>
    </a>
    <b>other info</b>
    <c>
      <id>444</id>
    </c>
  </top>

我尝试过这样使用 RewriteRule:

import scala.xml.transform.{RewriteRule, RuleTransformer}
import scala.xml.{Elem, Node, NodeSeq}

def changeTopId(root:Node, newId:String) = {

  val dontChg = root \ "_" filter {e => List("a", "b").contains(e.label)}

  object t1 extends RewriteRule{
    override def transform(n: Seq[Node]): Seq[Node] = n match {
      case e:Elem if dontChg.contains(e) => e
      case e:Elem if e.label == "id" => <id>{newId}</id>
      case other => other
    }
  }
  object changeTopOne extends RuleTransformer(t1)

  changeTopOne(root)
}

但它会影响所有&lt;id/&gt;节点,导致:

scala> changeTopId(inputXml, "999")
res1: scala.xml.Node =
<top>
    <id>999</id>
    <a>
      <id>999</id>
    </a>
    <b>other info</b>
    <c>
      <id>999</id>
    </c>
  </top>

谢谢

【问题讨论】:

    标签: xml scala transform


    【解决方案1】:

    原来我不需要重写规则。 这是一个 5 行的解决方案。

    val xs = (inputXml \ "_") map {
      case e: Elem if e.label == "id" => <id>999</id>
      case other => other
    }
    
    inputXml.copy(child=xs)
    

    以及结果值(手动格式化)

    scala.xml.Elem =
    <top>
        <id>999</id>
        <a>
            <id>innerId</id>
        </a>
        <b>other info</b>
        <c>
            <id>444</id>
        </c>
    </top>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-06-05
      • 1970-01-01
      • 1970-01-01
      • 2012-07-30
      • 1970-01-01
      • 2012-10-16
      • 1970-01-01
      相关资源
      最近更新 更多