blob: 9d9ec87b0c84fa3278073bced94df1504cfa0158 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
# dommap.tcl --
#
# Apply a mapping function to a DOM structure
#
# Copyright (c) 1998-2003 Zveno Pty Ltd
# http://www.zveno.com/
#
# See the file "LICENSE" in this distribution for information on usage and
# redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# $Id: dommap.tcl,v 1.1.1.1 2009/01/16 22:11:49 joye Exp $
package provide dommap 1.0
# We need the DOM
package require dom 2.6
namespace eval dommap {
namespace export map
}
# dommap::apply --
#
# Apply a function to a DOM document.
#
# The callback command is invoked with the node ID of the
# matching DOM node as its argument. The command may return
# an error, continue or break code to alter the processing
# of further nodes.
#
# Filter functions may be applied to match particular
# nodes. Valid functions include:
#
# -nodeType regexp
# -nodeName regexp
# -nodeValue regexp
# -attribute {regexp regexp}
#
# If a filter is specified then the node must match for the
# callback command to be invoked. If a filter is not specified
# then all nodes match that filter.
#
# Arguments:
# node DOM document node
# cmd callback command
# args configuration options
#
# Results:
# Depends on callback command
proc dommap::apply {node cmd args} {
array set opts $args
# Does this node match?
set match 1
catch {set match [expr $match && [regexp $opts(-nodeType) [::dom::node cget $node -nodeType]]]}
catch {set match [expr $match && [regexp $opts(-nodeName) [::dom::node cget $node -nodeName]]]}
catch {set match [expr $match && [regexp $opts(-nodeValue) [::dom::node cget $node -nodeValue]]]}
if {$match && ![string compare [::dom::node cget $node -nodeType] element]} {
set match 0
foreach {attrName attrValue} [array get [::dom::node cget $node -attributes]] {
set match 1
catch {set match [expr $match && [regexp [lindex $opts(-attribute) 0] $attrName]]}
catch {set match [expr $match && [regexp [lindex $opts(-attribute) 1] $attrValue]]}
if {$match} break
}
}
if {$match && [set code [catch {eval $cmd [list $node]} msg]]} {
switch $code {
0 {}
3 {
return -code break
}
4 {
return -code continue
}
default {
return -code error $msg
}
}
}
# Process children
foreach child [::dom::node children $node] {
switch [catch {eval apply [list $child] [list $cmd] $args} msg] {
0 {
# No action required
}
3 {
# break
return -code break
}
4 {
# continue - skip processing of siblings
return
}
1 -
2 -
default {
# propagate the error message
return -code error $msg
}
}
}
return {}
}
|