我正在遍历使用DFS访问每个节点的XML树。我得到的输出不是我的预期。
object Main extends App {
lazy val testXml =
<vehicles>
<vehicle>
gg
</vehicle>
<variable>
</variable>
</vehicles>
traverse.dfs(testXml.head)
}
object traverse {
def dfs(node: Node): Unit = {
println("==============")
println(node.label + ">>>" + node.child + ">>>" + node.child.size)
node.child.map(child => {
dfs(child)
})
}
}
输出:
==============
vehicles>>>ArrayBuffer(
, <vehicle>
gg
</vehicle>,
, <variable>
</variable>,
)>>>5
==============
#PCDATA>>>List()>>>0
==============
vehicle>>>ArrayBuffer(
gg
)>>>1
==============
#PCDATA>>>List()>>>0
==============
#PCDATA>>>List()>>>0
==============
variable>>>ArrayBuffer(
)>>>1
==============
#PCDATA>>>List()>>>0
==============
#PCDATA>>>List()>>>0
Process finished with exit code 0
如果您查看输出,对于第一个元素(vehicles
),它表示它有5个子元素。如果您打印孩子,两个孩子(第一个和最后一个)是空的。
我希望遍历访问vehicles
然后vehicle
然后gg
,最后variable
。
对此有任何建议表示赞赏。感谢。
答案 0 :(得分:0)
这两个孩子不是空的。它们是包含换行符和其他元素之间空格的文本节点。
如果您将XML定义为<vehicles><vehicle>gg</vehicle><variable></variable></vehicles>
而没有换行符和空格,则您的遍历将提供所需的结果。
但是如果您希望遍历处理原始XML,则可以过滤子项以仅包含具有实际内容的文本节点:
import scala.xml._
def filterEmptyNodes(nodes: Seq[Node]): Seq[Node] =
nodes.collect(Function.unlift {
case Text(text) =>
if (text.trim.isEmpty) None
else Some(Text(text.trim))
case node => Some(node)
})
让遍历函数使用此函数:
object traverse {
def dfs(node: Node): Unit = {
val nonEmptyChildren = filterEmptyNodes(node.child)
println("==============")
println(node.label + ">>>" + nonEmptyChildren + ">>>" + nonEmptyChildren.size)
nonEmptyChildren.foreach(dfs)
}
}
另外,您也可以使用node \ "_"
获取所有子元素,但不包含文本节点。
或者您可以使用node.descendant
或node.descendant_or_self
以DFS顺序拥有List
所有后代,而无需自己编写遍历。您还必须从后代中过滤掉“空”节点:filterEmptyNodes(node.descendant)
或filterEmptyNodes(node.descendant_or_self)