2017-01-27 9 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 

результат

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) 

Я не уверен, что сделать, чтобы следующий

ответ

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 ребенка Weekly затем обновляет его ребенок.

+0

Thanks @Amir. Я попытался решить это по общему пути (чтобы его можно было повторно использовать). Я добавил эту попытку выше, но это не удается. Дайте мне знать, если вы знаете об этом. благодаря – daydreamer

Смежные вопросы