2017-01-27 6 views
0

は、この例に親ノードが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 

を考えてみた結果は、プロパティを見ることができるように<Property key="Wed"/>も同様Propertiesが一意ではないので、Monthlyに追加されました

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> 

です。

私もtransform

val addWed = new RuleTransformer(new AddNewDayRule).transform(doc \\ "Weekly").head 

に私が渡したXML文書の一部を制限しようとした。しかし、私は何を取得することは

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

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を探し、その子を更新し、その後WeeklyProperties子を探します。

+0

ありがとう@Amir。私はこれを一般的な経路で解決しようとしました(再利用できるように)。私は更新として上記の試みを追加しましたが、失敗します。あなたがこれについて知っていれば教えてください。ありがとう – daydreamer

関連する問題