File Coverage

blib/lib/TEI/Lite/Utility.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package TEI::Lite::Utility;
2             ######################################################################
3             ## ##
4             ## Package: Utility.pm ##
5             ## Author: D. Hageman ##
6             ## ##
7             ## Description: ##
8             ## ##
9             ## Perl object designed to assist the user in the creation and ##
10             ## manipulation of TEILite documents. ##
11             ## ##
12             ######################################################################
13              
14             ##==================================================================##
15             ## Libraries and Variables ##
16             ##==================================================================##
17              
18             require 5.006;
19             require Exporter;
20              
21 6     6   4066 use strict;
  6         12  
  6         254  
22 6     6   31 use warnings;
  6         12  
  6         143  
23              
24 6     6   2648 use XML::LibXML;
  0            
  0            
25             use TEI::Lite::Element;
26              
27             our @ISA = qw( Exporter );
28              
29             our @EXPORT = qw( tei_convert_html_fragment );
30              
31             our $VERSION = "0.60";
32              
33             our %HTML2TEI = (
34             'a' => [ 'link' ],
35             'abbr' => [ 'tei_abbr', {} ],
36             'acronym' => [ 'tei_abbr', {} ],
37             'address' => [ 'tei_address', {} ],
38             'applet' => [ undef ],
39             'area' => [ undef ],
40             'b' => [ 'tei_hi', { rend => 'bold' } ],
41             'base' => [ undef ],
42             'basefont' => [ undef ],
43             'bdo' => [ undef ],
44             'big' => [ 'tei_hi', { rend => 'bold' } ],
45             'blockquote' => [ 'tei_div', {} ],
46             'br' => [ 'tei_lb', {} ],
47             'center' => [ 'tei_hi', { rend => 'center' } ],
48             'cite' => [ 'tei_cit', {} ],
49             'code' => [ 'tei_code', {} ],
50             'col' => [ undef ],
51             'colgroup' => [ undef ],
52             'comment' => [ 'comment' ],
53             'dd' => [ undef ],
54             'del' => [ undef ],
55             'dfn' => [ undef ],
56             'div' => [ undef ],
57             'dl' => [ undef ],
58             'dt' => [ undef ],
59             'em' => [ 'tei_emph', {} ],
60             'fieldset' => [ undef ],
61             'font' => [ undef ],
62             'h1' => [ 'tei_head', {} ],
63             'h2' => [ 'tei_head', {} ],
64             'h3' => [ 'tei_head', {} ],
65             'h4' => [ 'tei_head', {} ],
66             'h5' => [ 'tei_head', {} ],
67             'h6' => [ 'tei_head', {} ],
68             'hr' => [ 'tei_pb', { rend => 'hr' } ],
69             'i' => [ 'tei_hi', { rend => 'italic' } ],
70             'img' => [ 'figure' ],
71             'ins' => [ undef ],
72             'isindex' => [ undef ],
73             'kbd' => [ undef ],
74             'legend' => [ undef ],
75             'li' => [ 'tei_item', {} ],
76             'link' => [ undef ],
77             'ol' => [ 'tei_list', { type => 'ordered' } ],
78             'p' => [ 'tei_p', {} ],
79             'pre' => [ undef ],
80             'q' => [ 'tei_hi', { rend => 'quoted' } ],
81             's' => [ undef ],
82             'samp' => [ 'tei_hi', { rend => 'italic' } ],
83             'small' => [ 'tei_hi', { rend => 'normal' } ],
84             'span' => [ undef ],
85             'strike' => [ 'tei_hi', { rend => 'strike-through' } ],
86             'strong' => [ 'tei_hi', { rend => 'bold' } ],
87             'style' => [ undef ],
88             'sub' => [ undef ],
89             'table' => [ 'tei_table', {} ],
90             'tbody' => [ undef ],
91             'td' => [ 'tei_cell', {} ],
92             'tfoot' => [ undef ],
93             'th' => [ undef ],
94             'thead' => [ undef ],
95             'tr' => [ 'tei_row', {} ],
96             'tt' => [ 'tei_h', { rend => 'monotype' } ],
97             'u' => [ 'tei_hi', { rend => 'underline' } ],
98             'ul' => [ 'tei_list', { type => 'bulleted' } ],
99             'var' => [ 'tei_hi', { rend => 'italic' } ]
100             );
101              
102             ##==================================================================##
103             ## Function(s) ##
104             ##==================================================================##
105              
106             ##----------------------------------------------##
107             ## tei_convert_html_fragment ##
108             ##----------------------------------------------##
109             sub tei_convert_html_fragment ($$@)
110             {
111             my( $user_conversions, $format, @html ) = @_;
112            
113             ## Define a variable to hold our HTML DOM tree.
114             my $html = join( '', @html );
115            
116             ## Create a new document to hold our data.
117             my $dom = XML::LibXML::Document->new( '1.0' );
118            
119             ## Default the format to be '0' if it isn't defined.
120             $format = 0 if !defined( $format );
121            
122             ## Create a new XML::LibXML parser to play with.
123             my $parser = XML::LibXML->new();
124              
125             eval
126             {
127             ## Attempt to parse the html data into a workable DOM tree.
128             $html = $parser->parse_html_string( $html );
129             };
130              
131             if( $@ )
132             {
133             return( undef );
134             }
135             else
136             {
137             ## Create a document fragment to insert our nodes into.
138             my $dom_fragment = $dom->createDocumentFragment;
139            
140             foreach( $html->documentElement->findnodes( "//body/*" ) )
141             {
142             my( @elements ) =
143             _convert_html_element_to_tei_element( $user_conversions, $_ );
144              
145             foreach my $element ( @elements )
146             {
147             $dom_fragment->appendChild( $element );
148             }
149             }
150              
151             return( $dom_fragment->toString( $format ) );
152             }
153             }
154              
155             ##==================================================================##
156             ## Private Function(s) ##
157             ##==================================================================##
158              
159             ##----------------------------------------------##
160             ## _convert_html_element_to_tei_element ##
161             ##----------------------------------------------##
162             ## Private helper function for the TEI to ##
163             ## HTML conversion function. ##
164             ##----------------------------------------------##
165             sub _convert_html_element_to_tei_element
166             {
167             my( $user_conversions, $node ) = @_;
168              
169             ## Define an element to hold our scratch data and other elements.
170             my @result;
171             my $function,
172             my %attributes;
173            
174             ## Simplest case is if the data is text - we can just return that to
175             ## be appended.
176             if( ref( $node ) eq ( "XML::LibXML::Text" ) )
177             {
178             return( $node );
179             }
180              
181             ## Determine which html node we are really dealing with ...
182             my $name = lc( $node->nodeName );
183              
184             ## Grab the conversion routine for this element from the converstion
185             ## hash we have already defined.
186             if( ( defined( $user_conversions ) ) &&
187             ( ref( $user_conversions ) eq "HASH" ) )
188             {
189             $function = @{ $user_conversions->{ $name } }[0];
190              
191             if( !defined( $function ) )
192             {
193             $function = @{ $HTML2TEI{ $name } }[0];
194             }
195             }
196             else
197             {
198             $function = @{ $HTML2TEI{ $name } }[0];
199             }
200              
201             ## Check to see if the conversion function is defined our not.
202             if( ( !defined( $function ) ) && ( $node->hasChildNodes() ) )
203             {
204             if( $node->hasChildNodes() )
205             {
206             my( @children ) = $node->childNodes();
207            
208             foreach( @children )
209             {
210             push( @result,
211             _convert_html_element_to_tei_element(
212             $user_conversions, $_ ) );
213             }
214             }
215             else
216             {
217             return( XML::LibXML::Text->new( " " ) );
218             }
219             }
220              
221             ## This is our true main case ... almost all the converstion elements
222             ## get done on this code branch.
223             if( ( defined( $function ) ) && ( $function =~ /tei/ ) )
224             {
225             if( defined( @{ $user_conversions->{ $name } }[1] ) )
226             {
227             %attributes = %{ @{ $user_conversions->{ $name } }[1] };
228             }
229             elsif( defined( @{ $HTML2TEI{ $name } }[1] ) )
230             {
231             ## Grab the attributes out of our converstion hash.
232             %attributes = %{ @{ $HTML2TEI{ $name } }[1] };
233             }
234              
235             no strict 'refs';
236             $result[0] = &$function( \%attributes);
237             use strict 'refs';
238              
239             ## Loop through each of the child nodes ...
240             foreach( $node->childNodes() )
241             {
242             my( @children ) =
243             _convert_html_element_to_tei_element( $user_conversions, $_ );
244            
245             ## Loop through each of those child nodes ...
246             foreach my $child ( @children )
247             {
248             $result[0]->appendChild( $child );
249             }
250             }
251             }
252              
253             ## We have a special case for comment nodes.
254             if( ( defined( $function ) ) && ( $function eq "comment" ) )
255             {
256             $result[0] = XML::LibXML::Comment->new();
257              
258             foreach( $node->childNodes() )
259             {
260             $result[0]->appendChild( $_ );
261             }
262             }
263              
264             ## We have a special case for linking nodes.
265             if( ( defined( $function ) ) && ( $function eq "link" ) )
266             {
267             my $href = $node->getAttribute( "href" );
268              
269             $result[0] = tei_xref( { url => $href } );
270              
271             foreach( $node->childNodes() )
272             {
273             my( @children ) =
274             _convert_html_element_to_tei_element( $user_conversions, $_ );
275            
276             ## Loop through each of those child nodes ...
277             foreach my $child ( @children )
278             {
279             $result[0]->appendChild( $child );
280             }
281             }
282             }
283              
284             ## We have a special case for images as well ...
285             if( ( defined( $function ) ) && ( $function eq "figure" ) )
286             {
287             my $src = $node->getAttribute( "src" ) || "";
288             my $alt = $node->getAttribute( "alt" ) || "";
289              
290             $result[0] = tei_figure( { url => $src } );
291              
292             if( $alt ne "" )
293             {
294             $result[0]->appendChild( tei_figDesc( {}, $alt ) );
295             }
296             }
297            
298             return( @result );
299             }
300              
301             ##==================================================================##
302             ## End of Code ##
303             ##==================================================================##
304             1;
305              
306             ##==================================================================##
307             ## Plain Old Documentation (POD) ##
308             ##==================================================================##
309              
310             __END__