📄 ch10_03.htm
字号:
return; } # Fetch mtimes of this dir and the index.html in the corresponding # html dir my $index_file = "$base_path/$dir/index.html"; my $xml_mtime = (stat($xml_dir))[9]; my $html_mtime = (stat($index_file))[9]; # If the index page is older than the XML dir, or if it simply # doesn't exist, we generate a new one. if ((not($html_mtime)) or ($html_mtime <= $xml_mtime)) { generate_index($xml_dir, "$base_path/$dir", $r->uri); $r->filename($index_file); send_page($r, $index_file); return; } else { # The cached index page is fine. Let Apache serve it. $r->filename($index_file); $r->path_info(''); send_page($r, $index_file); return; } }sub generate_index { my ($xml_dir, $html_dir, $base_dir) = @_; # Snip possible trailing / from base_dir $base_dir =~ s|/$||; my $index_file = "$html_dir/index.html"; my $local_dir; if ($html_dir =~ /^$base_path\/*(.*)/) { $local_dir = $1; } # make directories, if necessary maybe_mkdir($local_dir); open (INDEX, ">$index_file") or die "Can't write to $index_file: $!"; opendir(DIR, $xml_dir) or die "Couldn't open directory $xml_dir: $!"; chdir($xml_dir) or die "Couldn't chdir to $xml_dir: $!"; # Set icon files my $doc_icon = "$icon_dir/generic.gif"; my $dir_icon = "$icon_dir/folder.gif"; # Make the displayable name of $local_dir (probably the same) my $local_dir_label = $local_dir || 'document root'; # Print start of page print INDEX <<END;<html><head><title>Index of $local_dir_label</title></head><body><h1>Index of $local_dir_label</h1><table width="100%">END # Now print one row per file in this dir while (my $file = readdir(DIR)) { # ignore dotfiles & directories & stuff if (-f $file && $file !~ /^\./) { # Create parser objects my $parser = XML::LibXML->new; # Check for well-formedness, skip if yukky: eval {$parser->parse_file($file);}; if ($@) { warn "Blecch, not a well-formed XML file."; warn "Error was: $@"; next; } my $doc = $parser->parse_file($file); my %info; # Will hold presentable info # Determine root type my $root = $doc->documentElement; my $root_type = $root->getName; # Now try to get an appropriate info node, which is named $FOOinfo my ($info) = $root->findnodes("${root_type}info"); if ($info) { # Yay, an info element for us. Fill it %info with it. if (my ($abstract) = $info->findnodes('abstract')) { $info{abstract} = $abstract->string_value; } elsif ($root_type eq 'reference') { # We can usee first refpurpose as our abstract instead. if ( ($abstract) = $root->findnodes('/reference/refentry/refnamediv/refpurpose')) { $info{abstract} = $abstract->string_value; } } if (my ($date) = $info->findnodes('date')) { $info{date} = $date->string_value; } } if (my ($title) = $root->findnodes('title')) { $info{title} = $title->string_value; } # Fill in %info stuff we don't need the XML for... unless ($info{date}) { my $mtime = (stat($file))[9]; $info{date} = localtime($mtime); } $info{title} ||= $file; # That's enough info. Let's build an HTML table row with it. print INDEX "<tr>\n"; # Figure out a filename to link to -- foo.html my $html_file = $file; $html_file =~ s/^(.*)\..*$/$1.html/; print INDEX "<td>"; print INDEX "<img src=\"$doc_icon\">" if $doc_icon; print INDEX "<a href=\"$base_dir/$html_file\">$info{title}</a></td> "; foreach (qw(abstract date)) { print INDEX "<td>$info{$_}</td> " if $info{$_}; } print INDEX "\n</tr>\n"; } elsif (-d $file) { # Just make a directory link. # ...unless it's an ignorable directory. next if grep (/^$file$/, qw(RCS CVS .)) or ($file eq '..' and not $local_dir); print INDEX "<tr>\n<td>"; print INDEX "<a href=\"$base_dir/$file\"><img src=\"$dir_icon\">" if $dir_icon; print INDEX "$file</a></td>\n</tr>\n"; } } # Close the table and end the page print INDEX <<END;</table></body></html>END close(INDEX) or die "Can't close $index_file: $!"; closedir(DIR) or die "Can't close $xml_dir: $!";}</pre></blockquote><p>These subroutines build on the transformation subroutine bygenerating the pages. Note the use of caching by comparing thetimestamps of the source DocBook file and the destination HTML fileand rewriting the latter only if it's older than theformer. (Of course, if there's no HTML at all, thenit always creates a new web page.)</p><blockquote><pre class="code">sub make_doc_page { my ($r, $html_filename) = @_; # Generate a source filename by replacing existing extension with .xml my $xml_filename = $html_filename; $xml_filename =~ s/^(.*)(?:\..*)$/$1.xml/; # If there's a problem reading the source XML file, so it goes with # the result HTML. unless (-r "$xml_path/$xml_filename") { unless (-e "$xml_path/$xml_filename") { $r->status( NOT_FOUND ); return; } else { # Exists, but no read permissions, shrug. $r->status( FORBIDDEN ); return; } } # Fetch mtimes of this file and corresponding html file my $xml_mtime = (stat("$xml_path/$xml_filename"))[9]; my $html_mtime = (stat("$base_path/$html_filename"))[9]; # If the html file is older than the xml XML file, or if it simply # doesn't exist, generate a new one if ((not($html_mtime)) or ($html_mtime <= $xml_mtime)) { transform($xml_filename, $html_filename); $r->filename("$base_path/$html_filename"); $r->status( DECLINED ); return; } else { # It's cached. Let Apache serve up the existing file. $r->status( DECLINED ); } }sub send_page { my ($r, $html_filename) = @_; # Problem here: if we're creating the file, we can't just write it # and say 'DECLINED', cuz the default server handle hits us with a # file-not-found. Until I find a better solution, I'll just spew # the file, and DECLINE only known cache-hits. $r->status( OK ); $r->send_http_header('text/html'); open(HTML, "$html_filename") or die "Couldn't read $base_path/$html_filename: $!"; while (<HTML>) { $r->print($_); } close(HTML) or die "Couldn't close $html_filename: $!"; return;}</pre></blockquote><p>Finally, we have a utility subroutine to help us with a tedious task:copying the structure of subdirectories in the cache directory thatmirrors that<a name="INDEX-779" /> of the source<a name="INDEX-780" /> XML directory:</p><blockquote><pre class="code">sub maybe_mkdir { # Given a path, make sure directories leading to it exist, mkdir-ing # any that dont. my ($filename) = @_; my @path_parts = split(/\//, $filename); # if the last one is a filename, toss it out. pop(@path_parts) if -f $filename; my $traversed_path = $base_path; foreach (@path_parts) { $traversed_path .= "/$_"; unless (-d $traversed_path) { mkdir ($traversed_path) or die "Can't mkdir $traversed_path: $!"; } } return 1;}</pre></blockquote></div><hr width="684" align="left" /><div class="navbar"><table width="684" border="0"><tr><td align="left" valign="top" width="228"><a href="ch10_02.htm"><img alt="Previous" border="0" src="../gifs/txtpreva.gif" /></a></td><td align="center" valign="top" width="228"><a href="index.htm"><img alt="Home" border="0" src="../gifs/txthome.gif" /></a></td><td align="right" valign="top" width="228"><a href="ch10_04.htm"><img alt="Next" border="0" src="../gifs/txtnexta.gif" /></a></td></tr><tr><td align="left" valign="top" width="228">10.2. Subclassing</td><td align="center" valign="top" width="228"><a href="index/index.htm"><img alt="Book Index" border="0" src="../gifs/index.gif" /></a></td><td align="right" valign="top" width="228">10.4. A Comics Index</td></tr></table></div><hr width="684" align="left" /><img alt="Library Navigation Links" border="0" src="../gifs/navbar.gif" usemap="#library-map" /><p><p><font size="-1"><a href="copyrght.htm">Copyright © 2002</a> O'Reilly & Associates. All rights reserved.</font></p><map name="library-map"><area shape="rect" coords="1,0,85,94" href="../index.htm"><area shape="rect" coords="86,1,178,103" href="../lwp/index.htm"><area shape="rect" coords="180,0,265,103" href="../lperl/index.htm"><area shape="rect" coords="267,0,353,105" href="../perlnut/index.htm"><area shape="rect" coords="354,1,446,115" href="../prog/index.htm"><area shape="rect" coords="448,0,526,132" href="../tk/index.htm"><area shape="rect" coords="528,1,615,119" href="../cookbook/index.htm"><area shape="rect" coords="617,0,690,135" href="../pxml/index.htm"></map></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -