File Coverage

lib/XML/Toolset.pm
Criterion Covered Total %
statement 4 6 66.6
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 6 8 75.0


line stmt bran cond sub pod time code
1              
2             package XML::Toolset;
3              
4 1     1   509 use strict;
  1         2  
  1         42  
5 1     1   635 use App;
  0            
  0            
6             use App::Service;
7             use vars qw($VERSION @ISA);
8              
9             $VERSION = sprintf"%d.%03d", q$Revision: 1.25 $ =~ /: (\d+)\.(\d+)/;
10             @ISA = ("App::Service");
11              
12             use XML::Toolset::Document;
13              
14             =head1 NAME
15              
16             XML::Toolset - perform XML construction, parsing, validation, and XPath operations using whatever underlying XML library is available (ALPHA!)
17              
18             =head1 SYNOPSIS
19              
20             use App;
21             use XML::Toolset;
22              
23             my $context = App->context();
24             my $toolset = $context->xml_toolset(class => "XML::Toolset::BestAvailable");
25              
26             ...
27              
28             =head1 DESCRIPTION
29              
30             The XML-Toolset distribution is a wrapper which provides a simplified XML
31             processing API which uses XPath to construct and dissect XML messages.
32              
33             The architecture of the XML-Toolset distribution allows for the user of
34             the API to access XML capabilities independent of the underlying XML
35             toolset technology: i.e. Xerces, LibXML, XML::XMLDOM, MSXML.
36              
37             =cut
38              
39             ###########################################################################
40             # abstract methods
41             ###########################################################################
42              
43             sub get_value {
44             &App::sub_entry if ($App::trace);
45             my ($self, $xpath) = @_;
46             my ($value);
47             die "get_value() must be implemented in a subclass";
48             &App::sub_exit($value) if ($App::trace);
49             return($value);
50             }
51              
52             sub set_value {
53             &App::sub_entry if ($App::trace);
54             my ($self, $xpath, $value) = @_;
55             die "set_value() must be implemented in a subclass";
56             &App::sub_exit() if ($App::trace);
57             }
58              
59             sub get_nodes {
60             &App::sub_entry if ($App::trace);
61             my ($self, $xpath) = @_;
62             my (@nodes);
63             die "set_nodes() must be implemented in a subclass";
64             &App::sub_exit(@nodes) if ($App::trace);
65             return(@nodes);
66             }
67              
68             sub set_nodes {
69             &App::sub_entry if ($App::trace);
70             my ($self, @nodes) = @_;
71             die "set_nodes() must be implemented in a subclass";
72             &App::sub_exit() if ($App::trace);
73             }
74              
75             sub to_string {
76             &App::sub_entry if ($App::trace);
77             my ($self) = @_;
78             my ($xml);
79             die "to_string() must be implemented in a subclass";
80             &App::sub_exit($xml) if ($App::trace);
81             return($xml);
82             }
83              
84             sub transform {
85             &App::sub_entry if ($App::trace);
86             my ($self) = @_;
87             die "transform() must be implemented in a subclass";
88             &App::sub_exit() if ($App::trace);
89             }
90              
91             sub version {
92             &App::sub_entry if ($App::trace);
93             my ($self) = @_;
94             my ($version);
95             die "version() must be implemented in a subclass";
96             &App::sub_exit($version) if ($App::trace);
97             return($version);
98             }
99              
100             sub new_parser {
101             &App::sub_entry if ($App::trace);
102             my ($self, $options) = @_;
103             my $parser = undef;
104             die "new_parser() must be implemented in a subclass";
105             &App::sub_exit($parser) if ($App::trace);
106             return($parser);
107             }
108              
109             sub new_dom {
110             &App::sub_entry if ($App::trace);
111             my ($self, $root_tag, $xmlns) = @_;
112             my ($dom);
113             die "new_dom() must be implemented in a subclass";
114             &App::sub_exit($dom) if ($App::trace);
115             return($dom);
116             }
117              
118             sub parse {
119             &App::sub_entry if ($App::trace);
120             my ($self, $xml, $options) = @_;
121            
122             my $valid = 1;
123             die "parse() must be implemented in a subclass";
124              
125             &App::sub_exit($valid) if ($App::trace);
126             return($valid);
127             }
128              
129             ###########################################################################
130             # base class methods
131             ###########################################################################
132              
133             #
134             #
135              
136             sub get_root_tag {
137             &App::sub_entry if ($App::trace);
138             my ($self, $doc) = @_;
139             my ($tag);
140             my $xml = $self->doc2xml($doc);
141             if ($xml =~ /^(<\?xml[^<>]*\?>)?\s*<\s*(\S+)/s) {
142             $tag = $2;
143             }
144             &App::sub_exit($tag) if ($App::trace);
145             return($tag);
146             }
147              
148             sub get_root_element_attribute {
149             &App::sub_entry if ($App::trace);
150             my ($self, $xml, $attrib) = @_;
151             my ($root_tag, $value);
152             if ($xml =~ /^(<\?xml[^<>]*\?>)?\s*<\s*(\S+)[^<>]*\s+$attrib\s*=\s*['"]([^<>'"]*)['"]/s) {
153             $root_tag = $2;
154             $value = $3;
155             }
156             &App::sub_exit($value) if ($App::trace);
157             return($value);
158             }
159              
160             sub set_root_element_attribute {
161             &App::sub_entry if ($App::trace);
162             my ($self, $xmlref, $attrib, $value) = @_;
163             my ($root_tag);
164             $$xmlref =~ s/^(<\?xml[^<>]*\?>)?(\s*<\s*\S+[^<>]*\s+$attrib\s*=\s*['"])([^<>'"]*)(['"])/$1$2$value$4/s;
165             &App::sub_exit() if ($App::trace);
166             }
167              
168             sub new_document {
169             &App::sub_entry if ($App::trace);
170             my ($self, @args) = @_;
171             my $doc = XML::Toolset::Document->new(@args, xml_toolset => $self);
172             &App::sub_exit($doc) if ($App::trace);
173             return($doc);
174             }
175              
176             sub type {
177             &App::sub_entry if ($App::trace);
178             my ($self) = @_;
179             my $class = ref($self);
180             $class =~ m/XML::Toolset::(.*)/;
181             my $type = $1;
182             &App::sub_exit($type) if ($App::trace);
183             return($type);
184             }
185              
186             sub validate_document {
187             &App::sub_entry if ($App::trace);
188             my ($self, $doc, $options) = @_;
189             my $xml = $self->doc2xml($doc);
190              
191             if ($self->{xmlns} && $self->{schema_location}) {
192             my $schema_location = $self->get_root_element_attribute($xml,"xsi:schemaLocation");
193             #if ($schema_location && $schema_location =~ /^$self->{xmlns} /) { }
194             if ($schema_location) {
195             my $schema_file = $schema_location;
196             $schema_file =~ s/.* //;
197             if ($schema_file =~ m/^[a-z]:/i || $schema_file =~ m/^[\\\/]/) {
198             $schema_file =~ s/.*[\\\/]//;
199             my $good_schema_location = "$self->{xmlns} $self->{schema_location}/$schema_file";
200             $self->set_root_element_attribute(\$xml,"xsi:schemaLocation",$good_schema_location);
201             }
202             }
203             }
204              
205             $options = {} if (!$options);
206             my $valid = 1;
207             delete $options->{dom};
208             delete $options->{error};
209             delete $options->{error_line};
210             delete $options->{error_column};
211              
212             die "validate called with no data to validate\n" unless defined $xml and length $xml > 0;
213              
214             my $dom = $self->parse($xml, $options);
215             if ($dom && !$options->{error}) {
216             $options->{dom} = $dom;
217             }
218             else {
219             $valid = 0;
220             }
221              
222             &App::sub_exit($valid) if ($App::trace);
223             return($valid);
224             }
225              
226             sub doc2dom {
227             &App::sub_entry if ($App::trace);
228             my ($self, $doc) = @_;
229             my $ref = ref($doc);
230             my ($dom);
231             if (!$ref) {
232             $dom = $self->parse($doc);
233             }
234             elsif ($ref eq "XML::Toolset::Document") {
235             $dom = $doc->dom();
236             }
237             else {
238             $dom = $doc;
239             }
240             &App::sub_exit($dom) if ($App::trace);
241             return($dom);
242             }
243              
244             sub doc2xml {
245             &App::sub_entry if ($App::trace);
246             my ($self, $doc) = @_;
247             my $ref = ref($doc);
248             my ($xml);
249             if (!$ref) {
250             $xml = $doc;
251             }
252             elsif ($ref eq "XML::Toolset::Document") {
253             $xml = $doc->xml();
254             }
255             else {
256             $xml = $doc->to_string();
257             }
258             &App::sub_exit($xml) if ($App::trace);
259             return($xml);
260             }
261              
262             sub set_validation {
263             &App::sub_entry if ($App::trace);
264             my ($self, $validation) = @_;
265             $self->{validation} = $validation;
266             delete $self->{parser}; # the next parser will have the new validation setting
267             &App::sub_exit() if ($App::trace);
268             }
269              
270             sub parser {
271             &App::sub_entry if ($App::trace);
272             my ($self, $options) = @_;
273             my $parser = $self->{parser};
274             if (!$parser) {
275             $parser = $self->new_parser($options);
276             $self->{parser} = $parser;
277             }
278             &App::sub_exit($parser) if ($App::trace);
279             return($parser);
280             }
281              
282             1;
283              
284             __END__