Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scala - XML insert/update

do you know any Scala API to insert and (or) update Nodes according to XPath? e.g for a given Node and XPath, this API would create a copy of XML with new node

thanks

like image 595
user1746915 Avatar asked Oct 15 '12 11:10

user1746915


1 Answers

You can use the RewriteRule to do this, 2.10.3 documentation.

val cats = <Cats>
  <Cat Name="Floyd"/>
  <Cat Name="Onyx"/>
</Cats>

Then suppose the RewriteRule

class AddCat(name: String) extends RewriteRule {
   override def transform(n: Node): Seq[Node] = n match {
     case e: Elem if e.label == "Cats" =>
       val cats = (e \\ "Cat")
       val newCat = <Cat Name={name}/>
       new Elem(e.prefix, "Cats", e.attributes, e.scope, e.minimizeEmpty, (cats ++ newCat).toSeq:_*)
     case x => x
   }
 }

Then you could do,

val rule = new RuleTransformer(new AddCat("Stevie"))
rule.transform(cats)
res2: Seq[scala.xml.Node] = List(<Cats><Cat Name="Floyd"/><Cat Name="Onyx"/><Cat Name="Stevie"/></Cats>)

Similarly if you wanted to change an attribute

class AddLastName(name: String, lastName: String) extends RewriteRule {
  override def transform(n: Node): Seq[Node] = n match {
    case e: Elem if e.label == "Cat" && (e \\ "@Name" text).equals(name) =>
      val cat: String = e.attributes("Name").head.text
      e % Attribute(None, "Name", Text(s"$name $lastName"), Null)
    case x => x
  }
}

val rule = new RuleTransformer(new AddLastName("Stevie", "Nicks"))
rule.transform(cats)
res3: Seq[scala.xml.Node] = List(<Cats><Cat Name="Floyd"/><Cat Name="Onyx"/><Cat Name="Stevie Nicks"/></Cats>)

Both of these approaches would do what you're looking for. The hard part is figuring out how to get at the children, then build the parent node.

like image 184
tysonjh Avatar answered Oct 23 '22 13:10

tysonjh