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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (hide annotations)
Fri Dec 5 05:05:53 2003 UTC (20 years, 4 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 joko 1.1 ##############################################################################
2     #
3     # Perl module: XML::XUpdate::Rewrite
4     #
5     # By Andreas Motl, andreas.motl@ilo.de
6     #
7 joko 1.2 # $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 joko 1.1 #
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 joko 1.2 $Revision: 1.1 $
26     $Date: 2003/05/06 14:36:48 $
27 joko 1.1
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 joko 1.2 use IO::File;
179 joko 1.1 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