Рассмотрим примерКак добавить узел в XML, когда родительский узел не уникален в документе XML?
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
не является уникальным.
Я также попытался ограничить часть документа XML, который я прохожу к 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>
, а не весь документ.
Каков наилучший способ решить эту проблему?
Update
Я попытался решить эту проблему для родового пути, и моя попытка ниже
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)
Я не уверен, что сделать, чтобы следующий
Thanks @Amir. Я попытался решить это по общему пути (чтобы его можно было повторно использовать). Я добавил эту попытку выше, но это не удается. Дайте мне знать, если вы знаете об этом. благодаря – daydreamer