鉴于此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>
我需要改变它:
1)对于每个<item>
,<target>
的文字会根据<discriminator>
中的文字进行修改。
2)为每个<incomplete>
添加一些文本内容。
基于其他SO帖子,到目前为止,我已经提出了2)的解决方案,使用RewriteRule
和RuleTransformer
。它是这样的:
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)
这似乎工作正常,但我不知道:
对于1),我试图模仿匹配孩子的列表,如下所示:
case Elem("", "item", _, _, disc@Elem("", "discriminator", _, _, _*))
if discriminate(disc) => //...?
或者这个:
case item@Elem("", "item", _, _, _*)
if discriminate(item \ "disc") => //..?
但是这样做并没有那么好,因为我不知道如何仅用替换<target>
来重新创建整个项目
我甚至不知道在这种情况下是否可以与<item>
匹配。但如果是的话,我能以某种方式实现其<incomplete>
孩子的转变吗?
这里的正确方法是什么?
答案 0 :(得分:1)
看看这是否适合你:
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
}
xml结构是不可变的,因此当您使用特定元素时,您无法访问它的父级。因此,我选择通过停在item
上并替换其子内容来解决问题#1。我希望这就是你要找的东西。