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
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
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.
What I would do is parse the xml using \\
convert the xml to a list using .toList.last.text
append what I need to and then collect my options: jsonOption collect
here you can change some options again using orElse Some
and then finally use a for yield
to yield the xml I want.
Take advantage of scale's flexibility in data conversion. It doesn't have to be identical but I'm sure you can see the light...