/[cvs]/nfo/perl/libs/XML/XUpdate/Rewrite.pm
ViewVC logotype

Contents of /nfo/perl/libs/XML/XUpdate/Rewrite.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (show annotations)
Fri Dec 5 05:05:53 2003 UTC (20 years, 11 months ago) by joko
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +8 -5 lines
+ minor fix - use IO::File instead if plain IO

1 ##############################################################################
2 #
3 # Perl module: XML::XUpdate::Rewrite
4 #
5 # By Andreas Motl, andreas.motl@ilo.de
6 #
7 # $Id: Rewrite.pm,v 1.1 2003/05/06 14:36:48 joko Exp $
8 #
9 # $Log: Rewrite.pm,v $
10 # Revision 1.1 2003/05/06 14:36:48 joko
11 # initial commit - preliminary (didn't work out as expected)
12 #
13 #
14 ###############################################################################
15
16
17 =pod
18
19 =head1 NAME
20
21 XML::XUpdate::Rewrite - A perl module for rewriting xml documents.
22
23 =head1 VERSION
24
25 $Revision: 1.1 $
26 $Date: 2003/05/06 14:36:48 $
27
28 =head1 DESCRIPTION
29
30 =head2 ABOUT
31
32 Pass through data of xml document untouched,
33 just modify its layout and/or descriptive information.
34
35 Layout manipulation:
36 - Node indentation level control and similar to optimize for human or machine readable payloads.
37
38 Descriptive information:
39 - Control if and how to produce the starting (e.g.) <?xml version="1.0" encoding="UTF-8"?> line.
40 - Toggle root node encapsulation on/off, specify root node.
41
42 Note for CPAN maintainers:
43 This would in fact make a general purpose module(???), it´s just in this namespace because
44 it was developed together with XML::XUpdate::XSLT.
45 Better name: XML::Rewrite? Or completely different - XML::Passthru. Or - associated to
46 its main usage - XML::ParseWriter. The "descriptive information encapsulation" could make
47 up a XML::Encap.
48 Both things in mind, let´s find a more abstract name combining its intention but
49 "one level away" from its core functionality!? e.g. XML::Smooth? XML::Polish?
50
51 =head2 IMPLEMENTATION
52
53 It was started using XML::Parser::PerlSAX and its companions XML::Handler::XMLWriter
54 and XML::Handler::CanonXMLWriter. This did *not* exactly solve the problem on the
55 first attempt, but was more simple to achieve through information provided by their
56 core pods.
57 The XML::Parser vs. XML::Writer way seems to be more straightforward and better
58 to customize by a richer set of parameters closer reflecting the intention of this module.
59 (convenient highlevel wrapper just doing a subset of what´s possible at all)
60
61
62
63 =head1 TODO
64
65 o Handle / convert between other important representations of XML documents (e.g. from/to XML::DOM)
66 This [c|w]ould make a XML::Convert or Convert::XML??? Does already exist one on CPAN?
67 o Provide some hooks to (e.g.) enable possibility to convert values from Latin to UTF-8 or such stuff.
68
69
70 =cut
71
72
73 ######################################################################
74 package XML::XUpdate::Rewrite;
75 ######################################################################
76
77 use strict;
78 use warnings;
79
80 use vars qw ( $VERSION );
81
82 use Data::Dumper;
83 # To load perl modules on demand at runtime.
84 # Perl will not croak at compile time for missing modules.
85 use Class::Loader;
86 #use base qw( Class::Loader );
87
88 $VERSION = '0.01';
89
90
91 ######################################################################
92 # PUBLIC DEFINITIONS
93
94 sub new {
95 my $class = shift;
96 my $self = bless {}, $class;
97 $self->{options} = $self->__arglist2hash(@_);
98
99 $self->{DEBUG} = $self->{options}->{debug};
100 $self->{WARNINGS} = $self->{options}->{warnings};
101
102 return $self;
103 }
104
105 sub set_document {
106 my $self = shift;
107 my $xml = shift;
108 $self->{XML}->{document} = $xml;
109 }
110
111 sub get_document {
112 my $self = shift;
113 return $self->{XML}->{document};
114 }
115
116 sub process {
117 my $self = shift;
118
119 # are we here?
120 #print "YAI!", "\n";
121
122 # set default options (in case just "rewrite" is turned on)
123 # a) canonical mode using XML::Parser::PerlSAX
124 $self->{options}->{engine} ||= "PerlSAX";
125 $self->{options}->{style} ||= "canonical";
126 # b) human readable xml using XML::Parser vs. XML::Writer
127 $self->{options}->{engine} ||= "XMLParser";
128 $self->{options}->{style} ||= "readable";
129
130 my $raw = $self->get_document();
131
132 # Rewrite xml payload to change output style of raw document (human readable or canonical).
133 # TODO: use XML::Writer as third option!
134 # from its pod: [...] and elements can optionally be indented based as their nesting level.
135 # FIXME: Do on-demand loading of helper modules here.
136
137 # V1 - The PerlSAX way.
138 if ($self->{options}->{engine} eq "PerlSAX") {
139
140 # First, create writer instance ...
141 my $writer;
142 if ($self->{options}->{style} eq "readable") {
143 # V1 - static
144 #use XML::Handler::XMLWriter;
145 #$writer = XML::Handler::XMLWriter->new( AsString => 1, Newlines => 0 );
146 # V2 - dynamic
147 #$writer = Class::Loader::_load( undef,
148 # Module => 'XML::Handler::XMLWriter',
149 # Args => [ AsString => 1, Newlines => 0 ],
150 #);
151 # V3 - auxiliary method
152 $writer = $self->__load( "XML::Handler::XMLWriter", [ AsString => 1, Newlines => 0 ] );
153 } elsif ($self->{options}->{style} eq "canonical") {
154 # FIXME: Make this work again!
155 #use XML::Handler::CanonXMLWriter;
156 #$writer = XML::Handler::CanonXMLWriter->new( PrintComments => 1 );
157 }
158
159 # pre-flight checks (do we actually have a writer instance?)
160 die( __PACKAGE__ . ": No writer instance!" ) if (not $writer or not ref $writer);
161
162 # ... and then create the parser instance.
163 my $parser = $self->__load( "XML::Parser::PerlSAX" );
164
165 # more pre-flight checks
166 die( __PACKAGE__ . ": No parser instance!") if (not $parser or not ref $parser);
167
168 # Finally, run them together, overwrite our payload ...
169 $self->set_document( $parser->parse( Source => { String => $raw }, Handler => $writer ) );
170
171 # ... and signal good.
172 return 1;
173 }
174
175 # V2 - using the classic XML::Parser together with its companion, XML::Writer
176 if ($self->{options}->{engine} eq "XMLParser") {
177
178 use IO::File;
179 my $output = IO::File->new(">output.xml");
180
181 # These return instances which are not required. => overhead!
182 $self->__load("XML::Writer");
183 $self->__load("XML::Parser::StreamWriter");
184
185 # First, create the writer instance ...
186 #my $writer = XML::Writer->new( OUTPUT => $output, NEWLINES => 0, DATA_MODE => 1, DATA_INDENT => 2 );
187 my $writer = XML::Writer->new( OUTPUT => *STDERR, NEWLINES => 0, DATA_MODE => 0, DATA_INDENT => 2 );
188 # ... and pass it through expat to the stream handler.
189 my $parser = XML::Parser->new( Style => "Stream", Pkg => "XML::Parser::StreamWriter", Writer => $writer );
190
191 # Run that stuff...
192 $parser->parse( $raw );
193
194 # Like above ...
195 #$self->set_document( $parser->parse( $raw ) );
196 #return 1;
197
198 }
199
200 return 0;
201
202 }
203
204 ######################################################################
205 # AUXILIARY METHODS
206
207 # Argument list parsing.
208 # ... from XML::XUpdate::LibXML (w/o backwards compatibility hook).
209 # Could this make up a Class::AutoFill::__read_arglist which transparently
210 # makes object attributes from constructor arguments in a configurable way?
211 # also similar inside XML::XUpdate::XSLT!!!
212 # solution: do some mixin here!!! --> Class::Container!?
213 sub __arglist2hash {
214 my $self = shift;
215 my %args;
216
217 if ( @_ % 2 ) {
218 $args{dummy} = shift;
219 %args = (%args, @_);
220 } else {
221 %args = @_;
222 }
223
224 return \%args;
225 }
226
227 sub __load {
228 my $self = shift;
229 my $name = shift;
230 my $args = shift;
231 return Class::Loader::_load( undef, Module => $name, Args => $args );
232 }
233
234 1;
235 __END__

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed