在AntiXML中链接转换

时间:2012-08-19 11:21:06

标签: xml scala

我有反xml Elem,类似这样(自动生成的数据):

<library>
  <bookshelf number="0">
    <book year="1997" title="Puzzled Coordinators" author="Lily Williams"></book>
    <book year="2005" title="Jittery Fare" author="Lucy Taylor"></book>
    <book year="2001" title="Dizzy Jurisdiction" author="Lucy Robinson"></book>
  </bookshelf>
  <bookshelf number="1">
    <book year="1997" title="Bashful Trusts" author="Lucas Wilson"></book>
    <book year="2003" title="Outrageous Consequences" author="Byron White"></book>
    <book year="1992" title="Irritated Accusations" author="Anne Roberts"></book>
  </bookshelf>
</library>

我想对它应用几种转换,例如:

val transforms: Seq[...] = ...
val result = transforms.foldLeft(library)(l,t) => t(l))

但我只得到这个解决方案:

val transforms: Seq[Elem => Zipper[Node]] = Seq(
  x => x \\ "book" filter (_.attrs("year").toInt > 2000) unselect,
  x => x \\ "book" filter (_.attrs("title").contains("J")) unselect
)
val result = transforms.foldLeft(lib)((l,t) => t(l).head.asInstanceOf[Elem])

有没有办法获得更好的转换类型(Elem =&gt; Elem)并避免那些丑陋的演员?

1 个答案:

答案 0 :(得分:1)

鉴于unselect目前只返回一个Zipper[Node],我没有找到一种方法来获得你想要的东西,而不需要一点点类型系统,这就像一个类似于演员的东西

在这种情况下,鉴于Anti-XML库的当前状态,你真的知道类型系统无法知道的东西:你知道你的转换产生的拉链的父级是一个Zipper[Elem],因此unselect为您提供 的内容<{1}},即使它被输入为Zipper[Elem]

所以我认为你能做的最好的事情就是把这种不愉快包装得更干净:

Zipper[Node]

或者,为了让你的意图更明显:

def toEndo(t: Elem => Zipper[Elem]): Elem => Elem =
  t andThen (_.unselect.head.asInstanceOf[Elem])

然后你可以写下以下内容:

def toEndo(t: Elem => Zipper[Elem]) = t andThen (_.unselect.head match {
  case e: Elem => e
  case _ => throw new RuntimeException("Aaaaah! This was never meant to happen!")
})

请注意,我已将val transforms: Seq[Elem => Zipper[Elem]] = Seq( _ \\ "book" filter (_.attrs("year").toInt > 2000), _ \\ "book" filter (_.attrs("title").contains("J")) ) val result = Function.chain(transforms map toEndo)(lib) 移动到帮助程序中,以便为我们提供更多类型安全性。