Reputation: 1403
Given this XML:
<root>
<item>
<discriminator>d1</discriminator>
<target>t1</target>
<subitem>
<incomplete></incomplete>
</subitem>
<subitem>
<incomplete></incomplete>
</subitem>
</item>
<item>
<discriminator>d2</discriminator>
<target>t2</target>
<subitem>
<incomplete></incomplete>
</subitem>
</item>
</root>
I need to transform it such that:
1) for each <item>
, text of <target>
is modified based on the text in <discriminator>
.
2) for each <incomplete>
, add some text content.
Based on other SO posts, so far I've come up with a solution for 2), using RewriteRule
and RuleTransformer
. It goes like this:
object completeIncomplete extends RewriteRule {
override def transform(n: Node): Seq[Node] = n match {
case Elem(_, "incomplete", _, _, _*) =>
<incomplete>content</incomplete>
case other => other
}
}
object transform extends RuleTransformer(completeIncomplete)
transform(xml)
This seems to work fine, but I don't know:
For 1), I have tried to pattern match the list of children, like this:
case Elem("", "item", _, _, disc@Elem("", "discriminator", _, _, _*))
if discriminate(disc) => //...?
or this:
case item@Elem("", "item", _, _, _*)
if discriminate(item \ "disc") => //..?
But that didn't work out so well, because I don't know how to recreate the whole item with only replacing <target>
I don't even know if in this case matching against <item>
is the way to go. But if it is, can I somehow achieve the transformation of its <incomplete>
children?
What is the correct approach here?
Upvotes: 0
Views: 293
Reputation: 35463
See if this works for you:
override def transform(n: Node): Seq[Node] = n match {
case el @ Elem(_, "item", _, _, _*) =>
val children = el.child
val disc = children.find(_.label == "discriminator")
val content = children.collect{
case el @ Elem(_, "target", _, _, _*) =>
<target>{el.text + disc.map(_.text).getOrElse("")}</target>
case e:Elem => e
}
<item>{content}</item>
case el @ Elem(_, "incomplete", _, _, _*) =>
<incomplete>some content</incomplete>
case other => other
}
The xml structure is immutable, so when you are on a particular element, you can not access it's parent. Because of that, I chose to approach your problem #1 by stopping on item
instead and replacing its child content. I hope this is what you were looking for.
Upvotes: 1