Commonly Used Modules

Modules have been discussed on and off throughout this book. Now that the end is here, it's time to discuss a few useful modules that we didn't cover earlier. As has been mentioned several times already, CPAN is huge—these modules are just a selection that are widely used, but that aren't included as part of the Perl distribution.

LWP

LWP, also referred to as libwww-perl, is a massive package that contains a number of individual modules that pertain to basically all things Web-related. It's most frequently used for its built-in HTTP client, but it provides plenty of other Web-related features as well. After you've installed it, you can type perldoc LWP for details.

One module in the LWP package is LWP::Simple, which enables you to easily use the HTTP client features of LWP. More flexible (and difficult to use) modules exist if you have unusual requirements, but if you're just retrieving regular old Web pages (even if you're calling CGI programs or other applications with arguments), LWP::Simple will do the trick.

Let's look at an example of how LWP::Simple is used:

#!/usr/bin/perl
use LWP::Simple;
getprint("http://www.typerl.com/");

That's the whole script. First, I import the LWP::Simple module, then I call the getprint function and pass in the URL http://www.typerl.com/. As you might have guessed, the script downloads the Web page and prints it out to STDOUT. Of course, there are plenty of other ways to simply print out the source code to a Web page.

If you want to do more to the Web page than just print it out, you can use the get function, which retrieves the contents of a page and returns a string. Here's what a script that uses get looks like:

#!/usr/bin/perl
use LWP::Simple;
my $text = get("http://www.typerl.com/");

The function returns undef if there's an error, so you can make sure that the request worked. You might want to use some other functions as well. The head function is used to retrieve information from the headers of a request. It can be called as follows:

($content_type, $document_length, $modified_time, $expires, $server)
    = head("http://www.typerl.com/");

There are also two functions used to copy remote Web pages to local files. getstore() simply takes two arguments, a URL and a filename, and copies the contents of the requested into the filename provided. The mirror function is a bit more sophisticated. It attempts to fetch and store a file, just like getstore(), but before storing the file, it checks to see if the local file already exists. If it does, it only stores the remote file if it has been modified since the file on disk was modified, and only if the content length of the remote file is different from the file stored on disk.

If LWP::Simple doesn't fulfill your requirements, the next step is to use the LWP::UserAgent module, which offers more flexibility. For information on LWP::UserAgent, check out the perldoc for it. You might also find the lwpcook Perl documentation useful, it's a cookbook for LWP users.

Sending E-mail with Net::SMTP

If you're writing Perl programs with Unix, it's easy to send mail. You just do something like this:

open (MAIL, "| mail [email protected]")
    or die "Can't send email:";

Then you can just print out your e-mail message to the MAIL filehandle and close it when you're ready to send the message. Unfortunately, if your script will run somewhere other than on a computer running Unix, your calls to the mail program won't work. If you want to make sure that your script works correctly across platforms, using Net::SMTP is the wiser choice.

Net::SMTP sends mail by connecting directly to an SMTP server and transmitting your e-mail message. Because it doesn't use any local program on the computer you're using, it will work from any platform. You just have to know the address of an SMTP server that will allow you to connect and send an e-mail.

Net::SMTP is an object-oriented module, here's some example code that demonstrates how it is used:

use Net::SMTP;
$smtp = Net::SMTP->new('mailhost'),
$smtp->mail('user'),
$smtp->to('[email protected]'),
$smtp->data();
$smtp->datasend("To: postmaster
");
$smtp->datasend("
");
$smtp->datasend("A simple test message
");
$smtp->dataend();
$smtp->quit();

Let's look at the example line by line. First, the Net::SMTP method is imported so that it can be used. On the next line, the constructor is called to create a new SMTP session. The constructor accepts the hostname (or IP address) of the SMTP server as its argument. Needless to say, the host specified must be running an SMTP server, and you must be authorized to use it for this to work.

Next, the mail method is used to initiate the sending of the new message. The argument passed in is the address that will appear in the From: field of the e-mail. If you just pass in a username, the hostname of the machine that the script is running on will be appended to the address.

The to method is used to specify the recipient (or list of recipients) to which the message will be sent. If you are sending the e-mail to multiple recipients, the argument list should take the following format:


The data method can be used in two ways. In this example, I use the data method to indicate that I'm going to start sending the body of the e-mail. Then, the datasend method is used to send the actual data and dataend to indicate that I'm finished. The alternate approach is to supply a list (or list reference) as an argument to data. The data in the list is used as the body of the e-mail message.

When you've sent your e-mail message, you can use the quit method to end your SMTP session.

Handling XML with Perl

At this point, XML is more than just a trend. It's being used as a storage format for documents, an interchange format for sharing data between applications, and a standardized, structured format for things like configuration files. Perl is a perfect match for handling XML data just because of its built-in functionality for dealing with text files. However, because valid XML follows a specific structure, you don't just have to rip apart your XML files using regular expressions and functions such as split. Instead, you can use a module designed to handle XML files.

There are a number of XML modules for Perl, including XML::Parser and XML::Simple, which can be used to parse XML and to create it. There are also a lot of modules that are designed to produce XML output, like a module that turns POD documentation into XML files. For a list of all the XML-related modules, check out CPAN.

Here's a specific example that uses the XML::Simple module. First, let's look at our data file, a very simple XML document. Here's the data:

<computers>
    <computer name="foo">
        <os>Mac OS X</os>
        <memory>256</memory>
        <address>foo.example.com</address>
        <applications>
            <application>Emacs</application>
            <application>Microsoft Word</application>
            <application>FileMaker</application>
        </applications>
    </computer>
    <computer name="bar">
        <os>Linux</os>
        <memory>256</memory>
        <address>bar.example.com</address>
        <applications>
            <application>vi</application>
            <application>mutt</application>
            <application>Apache</application>
        </applications>
    </computer>
</computers>

As you can see, the data in the XML document is stored in a tree-like data structure. XML::Simple will parse the file and create a nested data structure using hashes and arrays that mirror the data in the XML file. Using the Data::Dumper module, we can see the data structure that's created.

Here's the program:

#!/usr/bin/perl

use XML::Simple;
use Data::Dumper;

my $computers = XMLin("computers.xml", searchpath=>("."));

print Dumper($computers);

First, the XML::Simple and Data::Dumper modules are imported. Then, the XMLin() function is used to parse the XML file. The first argument to XMLin() is the name of the file to parse and the second is a hash of options. For a list of all the options, see the perldoc for XML::Simple. In this case, I just put the current directory in the search path for XML documents.

The last line of the script runs the data structure generated by XML::Simple through data dumper, producing the following:

'computer' => {
               'foo' => {
                          'os' => 'Mac OS X',
                          'memory' => '256',
                          'address' => 'foo.example.com',
                          'apps' => {
                                      'app' => [
                                                 'Emacs',
                                                 'Microsoft Word',
                                                 'FileMaker'
                                               ]
                                    }
                        } ,
               'bar' => {
                          'os' => 'Linux',
                          'memory' => '256',
                          'address' => 'bar.example.com',
                          'apps' => {
                                      'app' => [
                                                 'vi',
                                                 'mutt',
                                                 'Apache'
                                               ]
                                    }
                        }
             }
						

(I cheated a bit and trimmed the output, but for all intents and purposes, it's the same.) Compare the output of Data::Dumper to the example XML document. The root level of the document is mapped to the variable $computers, which is a reference to a hash. The hash has one element—its key is computer. Its value is a reference to another hash, with keys denoted by the name attributes of the computer elements in the XML file. Each of those hashes has members with keys mapped to children of the computer elements. Let's look at one special item. The apps element contains a number of app elements. Those are stored in an anonymous array, which is referenced by the value of the app element.

Let's look at a program that fetches specific data from the data structure:

#!/usr/bin/perl

use XML::Simple;

my $computers = XMLin();

print $computers->{computer} ->{foo} ->{os} , "
";
print $computers->{computer} ->{foo} ->{applications} ->{application} ->[0], "
";

On line 3, the module is imported. On line 5, the XMLIn() subroutine is called, which reads in the XML document and assigns the data structure to the variable $computers. Because a filename is not specified anywhere in this program, it assumes I want to load an XML file with the same base name as the name of the program. So if the program is called testxml.pl, it looks for testxml.xml.

The output of this program is

Mac OS X
Emacs

It's easy to save a data structure to an XML file as well. To convert a data structure into XML, you just use the XMLout() function. It returns a string that you can save to a file, or a database field, or anywhere else you choose. Here's the syntax:

my $xml = XMLout($computers);

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset