2016-08-16 2 views
1

Ich durchquere eine XML-Struktur, die jeden Knoten mithilfe von DFS besucht. Die Ausgabe, die ich bekomme, ist nicht das, was ich erwartet habe.Scala: Das Verfolgen einer XML-Struktur mit DFS führt zu unerwarteten Ergebnissen

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) 
    }) 
    } 
} 

Ausgang:

============== 
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 

Wenn Sie einen Blick auf den Ausgang nehmen, für das erste Element (vehicles) es sagt, es 5 Kinder hat. Wenn Sie die Kinder drucken, sind zwei Kinder (das erste und das letzte) leer.
Ich möchte die Traversal besuchen vehicles dann vehicle dann gg und schließlich variable.

Jeder Rat mit diesem wird geschätzt. Vielen Dank.

Antwort

0

Diese 2 Kinder sind nicht leer. Sie sind Textknoten, die Zeilenumbrüche und Leerzeichen zwischen anderen Elementen enthalten.

Wenn Sie das XML als <vehicles><vehicle>gg</vehicle><variable></variable></vehicles> ohne Zeilenumbrüche und Leerzeichen definieren, wird Ihr Traversal das gewünschte Ergebnis liefern.

Aber wenn Sie die Traversal in Ihrem ursprünglichen XML zu arbeiten, können Sie die Kinder filtern, um nur den Textknoten mit dem tatsächlichen Inhalt enthalten:

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) 
    }) 

Und die Traversal-Funktion verwendet diese Funktion haben:

object traverse { 
    def dfs(node: Node): Unit = { 
    val nonEmptyChildren = filterEmptyNodes(node.child) 
    println("==============") 
    println(node.label + ">>>" + nonEmptyChildren + ">>>" + nonEmptyChildren.size) 
    nonEmptyChildren.foreach(dfs) 
    } 
} 

Als Randnotiz können Sie auch node \ "_" verwenden, um alle untergeordneten Elemente abzurufen, aber keine Textknoten.

Oder Sie können node.descendant oder node.descendant_or_self verwenden, um eine List aller Nachkommen in DFS-Reihenfolge zu haben, ohne die Traversierung selbst zu schreiben. Sie müssen auch die "leeren" Knoten aus den Nachkommen herausfiltern: filterEmptyNodes(node.descendant) oder filterEmptyNodes(node.descendant_or_self)

+0

Vielen Dank ........ –

+0

Ich muss die XML durchlaufen, um Pfade zu allen Blattknoten zu generieren. Ich habe eine andere Frage gestellt. Bitte schau es dir an. https://stackoverflow.com/questions/39001421/scala-what-is-the-easiest-way-to-get-all-leaf-nodes-and-their-paths-in-an-xml –

Verwandte Themen