0

鉴于此 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) 的解决方案,使用RewriteRuleand 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)(根据兄弟元素修改元素)
  • 如何结合这两个处理步骤。也就是说:在这种情况下,有两个不同的 RewriteRule-s 有意义吗?这两个是不是很浪费?在一次迭代中实现这两种转换是否可能/可取?

对于 1),我尝试对子列表进行模式匹配,如下所示:

case Elem("", "item", _, _, disc@Elem("", "discriminator", _, _, _*)) 
    if discriminate(disc) => //...?

或这个:

case item@Elem("", "item", _, _, _*) 
    if discriminate(item \ "disc") => //..?

但这并没有那么好,因为我不知道如何只用替换来重新创建整个项目<target>

我什至不知道在这种情况下匹配反对<item>是要走的路。但如果是的话,我能不能以某种方式实现它的<incomplete>孩子的转变?

这里的正确方法是什么?

4

1 回答 1

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。我希望这就是你要找的。

于 2013-05-14T16:01:52.183 回答