Вы можете использовать основной синтаксический анализатор, используемый XMLEventReader
- ConstructingParser
, и обрабатывать узлы ваших сотрудников ниже верхнего уровня с помощью обратного вызова.Вам просто нужно быть осторожным, отбрасывая данные, как только они будут обработаны:
import scala.xml._
def processSource[T](input: Source)(f: NodeSeq => T) {
new scala.xml.parsing.ConstructingParser(input, false) {
nextch // initialize per documentation
document // trigger parsing by requesting document
var depth = 0 // track depth
override def elemStart(pos: Int, pre: String, label: String,
attrs: MetaData, scope: NamespaceBinding) {
super.elemStart(pos, pre, label, attrs, scope)
depth += 1
}
override def elemEnd(pos: Int, pre: String, label: String) {
depth -= 1
super.elemEnd(pos, pre, label)
}
override def elem(pos: Int, pre: String, label: String, attrs: MetaData,
pscope: NamespaceBinding, nodes: NodeSeq): NodeSeq = {
val node = super.elem(pos, pre, label, attrs, pscope, nodes)
depth match {
case 1 => <dummy/> // dummy final roll up
case 2 => f(node); NodeSeq.Empty // process and discard employee nodes
case _ => node // roll up other nodes
}
}
}
}
Затем вы используете это для обработки каждого узла на втором уровне в постоянной памяти (при условии, что узлы на втором уровне не являютсяполучение произвольного числа детей):
processSource(src){ node =>
// process here
println(node)
}
Преимущество по сравнению с XMLEventReader
заключается в том, что вы не используете два потока.Также вам не нужно анализировать узел дважды по сравнению с предложенным решением.Недостатком является то, что это зависит от внутренней работы ConstructingParser
.