Для сравнения я реализовал пример Дэвида , используя комбинаторы средств выбора из GData Scala Client библиотека:
def segment: Pickler[Segment] =
wrap(elem("segment",
attr("uri", text)
~ rep(segment))) { // rep = zero or more repetitions
// convert (uri ~ children) to Segment(uri, children), for unpickling
Segment.apply
} {
// convert Segment to (uri ~ children), for pickling
(s: Segment) => new ~(s.uri, s.children toList)
}
def body = elem("body", rep(segment))
case class Segment(uri: String, children: List[Segment])
Этот код - все, что необходимо для указания обоих направлений перевода между Segment
s и XML, тогда как аналогичный объем кода указывает только одно направление перевода при использовании библиотеки Scala XML. На мой взгляд, эту версию также легче понять (если вы знаете, DSL выбора). Конечно, как отметил Дэвид в комментарии, этот подход требует дополнительной зависимости и другого DSL, с которым разработчики должны быть знакомы.
Перевод XML в сегменты так же прост, как
body.unpickle(LinearStore.fromFile(filename)) // returns a PicklerResult[List[Segment]]
и перевод в другую сторону выглядит как
xml.XML.save(filename, body.pickle(segments, PlainOutputStore.empty).rootNode)
Что касается библиотеки комбинаторов, она, кажется, находится в приличной форме и компилируется в Scala 2.8.1. Мое первоначальное впечатление состоит в том, что в библиотеке отсутствуют некоторые тонкости (например, oneOrMore
комбинатор), которые можно довольно легко исправить. У меня не было времени, чтобы увидеть, насколько хорошо он обрабатывает неверные данные, но пока он выглядит достаточно для моих нужд.