[Keith Vetter] 2005-03-21 : Recently I had to optimize some code that was using pure-tcl to extract out each element of an XML file in the order it appears in the file. My first step in optimization was simply to use [tdom] to build a dom tree. Then, the following code does a restartable pre-order traversal of that tree The first call to ''':::WalkXML::NextNode''' with XML data initializes the dom tree. Each subsequent call to '''::WalkXML::NextNode''' returns the next dom node. Just this optimization alone, without redoing the code to utilize the dom tree, greatly speeded up the processing. ---- ##+########################################################################## # # WalkXML -- walks an tdom XML tree with each call to NextNode returning # the next node in a pre-order traversal of the dom tree. # by Keith Vetter, March 2005 # package require tdom namespace eval ::WalkXML { variable stack} proc ::WalkXML::NextNode {{XML ""}} { variable stack ;# List of VISITED ancestors if {$XML ne ""} { ;# Parse given xml set doc [dom parse $XML] set root [$doc documentElement] set stack [list $root] return $root } while {1} { set last [lindex $stack end] ;# Last already visited node set next [$last firstChild] ;# Try going down the tree if {$next ne ""} break set stack [lrange $stack 0 end-1] set next [$last nextSibling] ;# Try going across the tree if {$next ne ""} break while {1} { ;# Must go up the tree set next [lindex $stack end] ;# Parent set stack [lrange $stack 0 end-1] if {$next eq ""} break set next [$next nextSibling] ;# Try parent's sibling if {$next ne ""} break } break } if {$next ne ""} { lappend stack $next } return $next } ################################################################ # # Demo code # set XML { Geocache http://www.geocaching.com/seek/cache_details.aspx?wp=GCGPXK Geocache http://www.geocaching.com/seek/cache_details.aspx?wp=GC19DF } set node [::WalkXML::NextNode $XML] while {$node ne ""} { if {[$node nodeType] eq "TEXT_NODE"} { puts "\"[$node nodeValue]\"" } else { puts "[$node nodeName]" } set node [::WalkXML::NextNode] } ----