考虑这个例子
import scala.xml.{Node, Elem}
import scala.xml.transform.{RewriteRule, RuleTransformer}
val doc: Elem =
<root>
<level1>
<Weekly>
<Properties>
<Property key="Sun"/>
<Property key="Mon"/>
<Property key="Tue"/>
</Properties>
</Weekly>
</level1>
<level2>
<Monthly>
<Properties>
<Property key="Jan"/>
<Property key="Feb"/>
<Property key="Mar"/>
</Properties>
</Monthly>
</level2>
</root>
val wednesday = <Property key="Wed"/>
final class AddNewDayRule extends RewriteRule {
override def transform(n: Node): Seq[Node] = n match {
case e: Elem if e.label == "Properties" => e.copy(child = e.child ++ wednesday)
case e => e
}
}
val addWed = new RuleTransformer(new AddNewDayRule).transform(doc).head
结果是
addWed: scala.xml.Node = <root>
<level1>
<Weekly>
<Properties>
<Property key="Sun"/>
<Property key="Mon"/>
<Property key="Tue"/>
<Property key="Wed"/></Properties>
</Weekly>
</level1>
<level2>
<Monthly>
<Properties>
<Property key="Jan"/>
<Property key="Feb"/>
<Property key="Mar"/>
<Property key="Wed"/></Properties>
</Monthly>
</level2>
</root>
正如您所看到的,<Property key="Wed"/>
中添加了Monthly
属性,因为Properties
不是唯一的。
我还尝试限制传递给transform
val addWed = new RuleTransformer(new AddNewDayRule).transform(doc \\ "Weekly").head
但是,我得到的是
addWed: scala.xml.Node = <Weekly>
<Properties>
<Property key="Sun"/>
<Property key="Mon"/>
<Property key="Tue"/>
<Property key="Wed"/></Properties>
</Weekly>
而不是整个文件。
解决这个问题的最佳方法是什么?
更新
我尝试用通用路径解决这个问题,我的尝试在
final class AddNewNodeRule(expectedPath: Array[String], newNode: Node) extends RewriteRule {
private var index = 0
private val currentPath = Array[String]()
// only one transformation. If multiple, take expectedCount as input
var transformed = false
override def transform(ns: Seq[Node]): Seq[Node] = ns match {
case e: Node if index < expectedPath.length && e.label == expectedPath(index) =>
currentPath(index) = e.label
index += 1
println(s"i.inc = $index")
e
case e: Node if index == expectedPath.length - 1
&& (expectedPath sameElements currentPath) && !transformed =>
transformed = true
println(s"i.done = $index")
//e.copy(child = e.child ++ newNode)
e
case other: Node =>
println(s"i.other = $index, label=${other.label}")
other
}
}
val wednesday = <Property key="Wed"/>
val expectedPath = Array("level1", "Weekly", "Properties")
new RuleTransformer(new AddNewNodeRule(expectedPath, wednesday)).transform(doc).head
但现在它失败了
wednesday: scala.xml.Elem = <Property key="Wed"/>
expectedPath: Array[String] = Array(level1, Weekly, Properties)
i.other = 0, label=#PCDATA
i.other = 0, label=#PCDATA
i.other = 0, label=#PCDATA
i.other = 0, label=#PCDATA
i.other = 0, label=Property
i.other = 0, label=#PCDATA
i.other = 0, label=Property
i.other = 0, label=#PCDATA
i.other = 0, label=Property
i.other = 0, label=#PCDATA
i.other = 0, label=Properties
i.other = 0, label=#PCDATA
i.other = 0, label=Weekly
i.other = 0, label=#PCDATA
java.lang.ArrayIndexOutOfBoundsException: 0
at #worksheet#.AddNewNodeRule.transform(scratch_13.scala:36)
at scala.xml.transform.RuleTransformer.$anonfun$transform$1(scratch_13.scala:11)
at scala.collection.IndexedSeqOptimized.foldLeft(scratch_13.scala:52)
at scala.collection.IndexedSeqOptimized.foldLeft$(scratch_13.scala:60)
at scala.collection.mutable.WrappedArray.foldLeft(scratch_13.scala:30)
at scala.xml.transform.RuleTransformer.transform(scratch_13.scala:11)
at scala.xml.transform.BasicTransformer.$anonfun$transform$2(scratch_13.scala:31)
at scala.collection.TraversableLike.$anonfun$flatMap$1(scratch_13.scala:237)
at scala.collection.mutable.ResizableArray.foreach(scratch_13.scala:55)
at scala.collection.mutable.ResizableArray.foreach$(scratch_13.scala:48)
at scala.collection.mutable.ArrayBuffer.foreach(scratch_13.scala:44)
at scala.collection.TraversableLike.flatMap(scratch_13.scala:237)
at scala.collection.TraversableLike.flatMap$(scratch_13.scala:234)
at scala.collection.AbstractTraversable.flatMap(scratch_13.scala:100)
at scala.xml.transform.BasicTransformer.transform(scratch_13.scala:31)
at scala.xml.transform.BasicTransformer.transform(scratch_13.scala:41)
at scala.xml.transform.RuleTransformer.transform(scratch_13.scala:11)
at #worksheet#.#worksheet#(scratch_13.scala:54)
我不确定下一步会怎么做
答案 0 :(得分:0)
像这样更新RewriteRule
:
final class AddNewDayRule extends RewriteRule {
override def transform(n: Node): Seq[Node] = n match {
case e: Elem if e.label == "Weekly" => e.copy(
child = e.child map {
case child: Elem =>
if (child.label == "Properties") {
child.copy(child = child.child ++ wednesday)
} else {
child
}
case other => other
}
)
case e => e
}
}
首先查找父节点Weekly
,然后查找Properties
的{{1}}子节点,然后更新其子节点。