line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package XML::XMetaL::Utilities;
|
2
|
|
|
|
|
|
|
|
3
|
3
|
|
|
3
|
|
4991
|
use strict;
|
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
491
|
|
4
|
3
|
|
|
3
|
|
19
|
use warnings;
|
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
85
|
|
5
|
3
|
|
|
3
|
|
20
|
use Carp;
|
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
244
|
|
6
|
3
|
|
|
3
|
|
19
|
use Hash::Util qw(lock_keys);
|
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
37
|
|
7
|
3
|
|
|
3
|
|
8339
|
use Win32;
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
# DOM node types
|
10
|
|
|
|
|
|
|
use constant DOMELEMENT => 1;
|
11
|
|
|
|
|
|
|
use constant DOMATTR => 2;
|
12
|
|
|
|
|
|
|
use constant DOMTEXT => 3;
|
13
|
|
|
|
|
|
|
use constant DOMCDATASECTION => 4;
|
14
|
|
|
|
|
|
|
use constant DOMENTITYREFERENCE => 5;
|
15
|
|
|
|
|
|
|
use constant DOMENTITY => 6;
|
16
|
|
|
|
|
|
|
use constant DOMPROCESSINGINSTRUCTION => 7;
|
17
|
|
|
|
|
|
|
use constant DOMCOMMENT => 8;
|
18
|
|
|
|
|
|
|
use constant DOMDOCUMENT => 9;
|
19
|
|
|
|
|
|
|
use constant DOMDOCUMENTTYPE => 10;
|
20
|
|
|
|
|
|
|
use constant DOMDOCUMENTFRAGMENT => 11;
|
21
|
|
|
|
|
|
|
use constant DOMNOTATION => 12;
|
22
|
|
|
|
|
|
|
use constant DOMCHARACTERREFERENCE => 505; # Extension to DOM
|
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
# Attribute types
|
25
|
|
|
|
|
|
|
use constant UNKNOWN => -1;
|
26
|
|
|
|
|
|
|
use constant CDATA => 0;
|
27
|
|
|
|
|
|
|
use constant ID => 1;
|
28
|
|
|
|
|
|
|
use constant IDREF => 2;
|
29
|
|
|
|
|
|
|
use constant IDREFS => 3;
|
30
|
|
|
|
|
|
|
use constant ENTITY => 4;
|
31
|
|
|
|
|
|
|
use constant ENTITIES => 5;
|
32
|
|
|
|
|
|
|
use constant NMTOKEN => 6;
|
33
|
|
|
|
|
|
|
use constant NMTOKENS => 7;
|
34
|
|
|
|
|
|
|
use constant NOTATION => 8;
|
35
|
|
|
|
|
|
|
use constant NAMETOKENGROUP => 9;
|
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
require Exporter; |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
our @ISA = qw(Exporter);
|
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
our @dom_type_names = qw(
|
44
|
|
|
|
|
|
|
DOMELEMENT DOMATTR DOMTEXT
|
45
|
|
|
|
|
|
|
DOMCDATASECTION DOMENTITYREFERENCE DOMENTITY
|
46
|
|
|
|
|
|
|
DOMPROCESSINGINSTRUCTION DOMCOMMENT DOMDOCUMENT
|
47
|
|
|
|
|
|
|
DOMDOCUMENTTYPE DOMDOCUMENTFRAGMENT DOMNOTATION
|
48
|
|
|
|
|
|
|
DOMCHARACTERREFERENCE
|
49
|
|
|
|
|
|
|
);
|
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
our @attribute_type_names = qw(
|
52
|
|
|
|
|
|
|
UNKNOWN CDATA ID
|
53
|
|
|
|
|
|
|
IDREF IDREFS ENTITY
|
54
|
|
|
|
|
|
|
ENTITIES NMTOKEN NMTOKENS
|
55
|
|
|
|
|
|
|
NOTATION NAMETOKENGROUP
|
56
|
|
|
|
|
|
|
); |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
our %EXPORT_TAGS = (
|
59
|
|
|
|
|
|
|
all => [@dom_type_names, @attribute_type_names],
|
60
|
|
|
|
|
|
|
dom_node_types => [@dom_type_names],
|
61
|
|
|
|
|
|
|
attribute_types => [@attribute_type_names],
|
62
|
|
|
|
|
|
|
);
|
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
our @EXPORT_OK = (@{$EXPORT_TAGS{all}}); |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
# Variables used by the generate_id() method
|
67
|
|
|
|
|
|
|
our $count = 0;
|
68
|
|
|
|
|
|
|
our $user = Win32::LoginName();
|
69
|
|
|
|
|
|
|
our $time = time();
|
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
sub new {
|
74
|
|
|
|
|
|
|
my ($class, %args) = @_;
|
75
|
|
|
|
|
|
|
my $self;
|
76
|
|
|
|
|
|
|
eval {
|
77
|
|
|
|
|
|
|
lock_keys(%args, qw(-application));
|
78
|
|
|
|
|
|
|
$self = bless {
|
79
|
|
|
|
|
|
|
_application => $args{-application} || croak("-application parameter missing or undefined"),
|
80
|
|
|
|
|
|
|
}, ref($class) || $class;
|
81
|
|
|
|
|
|
|
lock_keys(%$self, keys %$self);
|
82
|
|
|
|
|
|
|
};
|
83
|
|
|
|
|
|
|
croak $@ if $@;
|
84
|
|
|
|
|
|
|
return $self;
|
85
|
|
|
|
|
|
|
}
|
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
sub get_application {
|
88
|
|
|
|
|
|
|
my ($self) = @_;
|
89
|
|
|
|
|
|
|
return $self->{_application};
|
90
|
|
|
|
|
|
|
}
|
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
sub get_active_document {
|
93
|
|
|
|
|
|
|
my ($self) = @_;
|
94
|
|
|
|
|
|
|
return $self->get_application()->{ActiveDocument};
|
95
|
|
|
|
|
|
|
}
|
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
sub get_selection {
|
98
|
|
|
|
|
|
|
my ($self) = @_;
|
99
|
|
|
|
|
|
|
my $application = $self->get_application();
|
100
|
|
|
|
|
|
|
return $application->{Selection};
|
101
|
|
|
|
|
|
|
}
|
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
sub insert_element_with_id {
|
104
|
|
|
|
|
|
|
my ($self, $generic_identifier) = @_;
|
105
|
|
|
|
|
|
|
my $inserted_node = undef; |
106
|
|
|
|
|
|
|
eval {
|
107
|
|
|
|
|
|
|
my $active_document = $self->get_active_document();
|
108
|
|
|
|
|
|
|
my $initial_position_range = $active_document->{Range};
|
109
|
|
|
|
|
|
|
my $final_position_range;
|
110
|
|
|
|
|
|
|
my $selection = $self->get_selection();
|
111
|
|
|
|
|
|
|
if ($selection->CanInsert($generic_identifier)) {
|
112
|
|
|
|
|
|
|
$selection->InsertElementWithRequired($generic_identifier);
|
113
|
|
|
|
|
|
|
$final_position_range = $active_document->{Range};
|
114
|
|
|
|
|
|
|
$initial_position_range->Select();
|
115
|
|
|
|
|
|
|
$selection->MoveRight(0);
|
116
|
|
|
|
|
|
|
$inserted_node = $selection->{ContainerNode};
|
117
|
|
|
|
|
|
|
$self->populate_element_with_id($inserted_node);
|
118
|
|
|
|
|
|
|
$final_position_range->Select(); |
119
|
|
|
|
|
|
|
}
|
120
|
|
|
|
|
|
|
};
|
121
|
|
|
|
|
|
|
croak $@ if $@;
|
122
|
|
|
|
|
|
|
return $inserted_node;
|
123
|
|
|
|
|
|
|
}
|
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
sub generate_id {
|
126
|
|
|
|
|
|
|
$count++;
|
127
|
|
|
|
|
|
|
my $id = sprintf "%s%u%04u",$user,$time,$count;
|
128
|
|
|
|
|
|
|
return $id;
|
129
|
|
|
|
|
|
|
}
|
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
sub get_id_attribute_name {
|
132
|
|
|
|
|
|
|
my ($self, $generic_identifier) = @_;
|
133
|
|
|
|
|
|
|
my $id_attribute_name;
|
134
|
|
|
|
|
|
|
eval {
|
135
|
|
|
|
|
|
|
my $active_document = $self->get_active_document();
|
136
|
|
|
|
|
|
|
my $doctype = $active_document->{doctype};
|
137
|
|
|
|
|
|
|
my $count = 0;
|
138
|
|
|
|
|
|
|
while ($id_attribute_name = $doctype->elementAttribute($generic_identifier, $count)) {
|
139
|
|
|
|
|
|
|
$count++;
|
140
|
|
|
|
|
|
|
last if $doctype->attributeType($generic_identifier,$id_attribute_name) == ID;
|
141
|
|
|
|
|
|
|
}
|
142
|
|
|
|
|
|
|
};
|
143
|
|
|
|
|
|
|
croak $@ if $@;
|
144
|
|
|
|
|
|
|
return $id_attribute_name || undef;
|
145
|
|
|
|
|
|
|
}
|
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
sub populate_id_attributes {
|
148
|
|
|
|
|
|
|
my ($self, $generic_identifier) = @_;
|
149
|
|
|
|
|
|
|
eval {
|
150
|
|
|
|
|
|
|
my $active_document = $self->get_active_document();
|
151
|
|
|
|
|
|
|
my $element_node_list = $active_document->getElementsByTagName($generic_identifier);
|
152
|
|
|
|
|
|
|
my $element;
|
153
|
|
|
|
|
|
|
for (my $count = 0; $count < $element_node_list->{length}; $count++) {
|
154
|
|
|
|
|
|
|
$element = $element_node_list->item($count);
|
155
|
|
|
|
|
|
|
$self->populate_element_with_id($element);
|
156
|
|
|
|
|
|
|
}
|
157
|
|
|
|
|
|
|
};
|
158
|
|
|
|
|
|
|
croak $@ if $@;
|
159
|
|
|
|
|
|
|
}
|
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
sub populate_element_with_id {
|
162
|
|
|
|
|
|
|
my ($self, $element_node) = @_;
|
163
|
|
|
|
|
|
|
eval {
|
164
|
|
|
|
|
|
|
my $generic_identifier = $element_node->{tagName};
|
165
|
|
|
|
|
|
|
my $attribute_name = $self->get_id_attribute_name($generic_identifier);
|
166
|
|
|
|
|
|
|
if ($attribute_name) {
|
167
|
|
|
|
|
|
|
unless ($element_node->hasAttribute($attribute_name)) {
|
168
|
|
|
|
|
|
|
my $id_value = $self->generate_id();
|
169
|
|
|
|
|
|
|
$element_node->setAttribute($attribute_name, $id_value);
|
170
|
|
|
|
|
|
|
}
|
171
|
|
|
|
|
|
|
}
|
172
|
|
|
|
|
|
|
};
|
173
|
|
|
|
|
|
|
croak $@ if $@;
|
174
|
|
|
|
|
|
|
}
|
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
sub word_count {
|
177
|
|
|
|
|
|
|
my ($self, $argument) = @_;
|
178
|
|
|
|
|
|
|
my $word_count;
|
179
|
|
|
|
|
|
|
eval {
|
180
|
|
|
|
|
|
|
$word_count = ref($argument) ?
|
181
|
|
|
|
|
|
|
$self->_count_words_in_element($argument):
|
182
|
|
|
|
|
|
|
$self->_count_words_in_string($argument);
|
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
};
|
185
|
|
|
|
|
|
|
croak($@) if $@;
|
186
|
|
|
|
|
|
|
return $word_count;
|
187
|
|
|
|
|
|
|
}
|
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
sub _count_words_in_string {
|
190
|
|
|
|
|
|
|
my ($self, $string) = @_;
|
191
|
|
|
|
|
|
|
my $word_count;
|
192
|
|
|
|
|
|
|
eval {
|
193
|
|
|
|
|
|
|
my @words = split /[\s\:\-\;\,]+/, $string;
|
194
|
|
|
|
|
|
|
@words = grep {$_} @words; # Filter out empty strings
|
195
|
|
|
|
|
|
|
$word_count = @words;
|
196
|
|
|
|
|
|
|
};
|
197
|
|
|
|
|
|
|
croak $@ if $@;
|
198
|
|
|
|
|
|
|
return $word_count;
|
199
|
|
|
|
|
|
|
}
|
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
sub _count_words_in_element {
|
202
|
|
|
|
|
|
|
my ($self, $element) = @_;
|
203
|
|
|
|
|
|
|
my $word_count = 0;
|
204
|
|
|
|
|
|
|
eval {
|
205
|
|
|
|
|
|
|
my $child_nodes = $element->{childNodes};
|
206
|
|
|
|
|
|
|
my ($child, $node_type);
|
207
|
|
|
|
|
|
|
for (my $count = 0; $count < $child_nodes->{length};$count++) {
|
208
|
|
|
|
|
|
|
$child = $child_nodes->item($count);
|
209
|
|
|
|
|
|
|
$node_type = $child->{nodeType};
|
210
|
|
|
|
|
|
|
foreach ($node_type) {
|
211
|
|
|
|
|
|
|
$node_type == DOMELEMENT && do {
|
212
|
|
|
|
|
|
|
$word_count += $self->_count_words_in_element($child);
|
213
|
|
|
|
|
|
|
last;
|
214
|
|
|
|
|
|
|
};
|
215
|
|
|
|
|
|
|
$node_type == DOMTEXT && do {
|
216
|
|
|
|
|
|
|
$word_count += $self->_count_words_in_string($child->{data});
|
217
|
|
|
|
|
|
|
last;
|
218
|
|
|
|
|
|
|
};
|
219
|
|
|
|
|
|
|
$node_type == DOMCDATASECTION && do {
|
220
|
|
|
|
|
|
|
$word_count += $self->_count_words_in_string($child->{data});
|
221
|
|
|
|
|
|
|
last;
|
222
|
|
|
|
|
|
|
};
|
223
|
|
|
|
|
|
|
}
|
224
|
|
|
|
|
|
|
}
|
225
|
|
|
|
|
|
|
};
|
226
|
|
|
|
|
|
|
croak $@ if $@;
|
227
|
|
|
|
|
|
|
return $word_count;
|
228
|
|
|
|
|
|
|
}
|
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
1;
|
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
__END__
|