proc sortCommand {nodeValueCommand options node1 node2} { # get the values to compare # set value1 [{*}[string map [list %N $node1] $nodeValueCommand]]; set value2 [{*}[string map [list %N $node2] $nodeValueCommand]]; # care for the nocase option # if {"-nocase" in $options} { set value1 [string tolower $value1]; set value2 [string tolower $value2]; } # compare in dictionary style # if {"-dictionary" in $options} { if {$value1 eq $value2} { return 0; } set list [lsort -dictionary [list $value1 $value2]]; if {$value1 eq [lindex $list 0]} { return -1; } return 1; } # compare non-numerical values # if { ("-real" ni $options && "-integer" ni $options) || ![string is double -strict $value1] || ![string is double -strict $value2]} { return [string compare $value1 $value2]; } # compare numerical values # if {$value1 == $value2} { return 0; } elseif {$value1 > $value2} { return 1; } return -1; } proc sortNodesByCommand {parentNode nodeValueCommand args} { # get the child nodes and sort them # set childNodes [$parentNode childNodes]; set sortedNodes [lsort \ {*}$args \ -command [list sortCommand $nodeValueCommand $args] \ $childNodes \ ]; if {$sortedNodes eq $childNodes} { return; } # remove all child nodes from the parent node # foreach childNode $childNodes { $parentNode removeChild $childNode; } # add the child nodes in the new order # foreach childNode $sortedNodes { $parentNode appendChild $childNode; } return; } proc sortNodesByName {parentNode args} { sortNodesByCommand $parentNode {%N nodeName} {*}$args -dictionary; } proc sortNodesByValue {parentNode args} { sortNodesByCommand $parentNode {%N nodeValue} {*}$args; } proc sortNodesByText {parentNode args} { sortNodesByCommand $parentNode {%N text} {*}$args -dictionary; } proc sortNodesByAttribute {parentNode attribute args} { sortNodesByCommand $parentNode {%N getAttribute $attribute} {*}$args; } # examples # package require tdom; set dom [dom parse -html [tDOM::xmlReadFile $htmlFile]]; set doc [$dom documentElement]; set head [$doc firstChild]; sortNodesByName $head; sortNodesByCommand $body {llength [%N childNodes]};