Обратите внимание, что родительский узел узла Text в вашем примере на самом деле является узлом .
Поскольку узлы не имеют ссылок на своих родителей, один из способов получить к ним доступ - просто передать их с собой при ходьбе по дереву, например:
def processNode(node: Node, parent: Option[Node]) {
if (node.isInstanceOf[Text]) {
if (node.text.contains("Welcome"))
{
println("Node: " + node)
println("Parent: " + parent.getOrElse("[toplevel]"))
}
}
node.child foreach { n: Node => processNode(n, Some(node)) }
}
processNode(xml, None)
Конечно, это становится громоздким, когда вы хотите взобраться на дерево на произвольный уровень. Один из подходов к этому - заключить ваши узлы в SuperNode
, который имеет необязательную родительскую ссылку.
case class SuperNode(current: Node, parent: Option[SuperNode] = None)
Для удобства создайте неявную функцию для преобразования узлов в SuperNodes в случае отсутствия по умолчанию родительского элемента.
implicit def nodeMakeSuper(n: Node) = SuperNode(n)
Теперь вы можете перемещаться вверх по дереву произвольное количество раз, например:
def processNode(node: SuperNode) {
node.current match {
case n @ Text(t) if t.contains("Welcome") => {
println("Node: " + n)
node.parent match {
case Some(p) => {
println("Parent: " + p.current)
p.parent match {
case Some(gp) => println("GrandParent: " + gp.current)
case None => println("No grandparent!")
}
}
case None => println("No parent!")
}
}
case _ => // these aren't the droids you're looking for
}
node.current.child foreach { child: Node => processNode(SuperNode(child, Some(node))) }
}