Examples of XML Document Generation


In this section, I'm going to present a few examples that demonstrate the different approaches to generating XML data. While going through the examples, try to keep the advantages and disadvantages of each approach in mind. First, let's take a look at generating an XML document by using the Perl print function.

Using the Perl print Function

No, don't worry; if you are reading this section, you are not necessarily crazy, but rather enjoy exploring things. Using Perl's print function to generate XML data can be time saving, and at other times, time consuming. It all depends on the task. Just follow the famous advice, "Use the right tool for the right job," and make the right choice.

If your requirement is to simply generate a relatively small XML file, then it won't be time consuming. If you don't mind explicitly typing every XML construct in your Perl code, then a simple Perl program based on the print function might just be your answer. Any other task will most likely greatly benefit from the use of a specialized XML writer module. For example, a small application configuration file might be a good candidate for manual generation.

Remember, first and foremost, an XML document is really just a text file that follows a strict set of rules for defining structure and content.You can take advantage of this fact, and you can use the standard Perl print function to generate an output XML document. Let's say that you are responsible for generating the simple XML document for configuring a Perl DBI-based application.You parsed this XML document back in Chapter 4, "Tree-Based Parser Modules," using the XML::Simple Perl module; however, let's take a look at how to generate it using the Perl print function. The XML document is shown in Listing 5.1.

Listing 5.1 XML document containing DBI configuration information. (Filename: ch5_dbi_config.xml)
 <?xml version="1.0" encoding="UTF-8"?>  <!DOCTYPE db_config_information SYSTEM "ch5_dbi_config.dtd">  <db_config_information>     <db_user>        <username>mark</username>        <password>mark's password</password>     </db_user>     <db_server hostname="rocket" os="Linux">        <server_ip>192.168.1.10</server_ip>        <db_driver>MySQL</db_driver>        <port>3306</port>     </db_server>    <db_server hostname="scooter" os="Microsoft Windows">        <server_ip>192.168.1.50</server_ip>        <db_driver>ODBC</db_driver>        <port>3379</port>     </db_server>  </db_config_information> 

As you can see, this is a very simple XML document, and you can easily generate it using the standard Perl print function. The Perl program that was used to generate the XML document is shown in Listing 5.2.

Listing 5.2 Perl program used to generate a Perl DBI configuration file in XML. (Filename: ch5_dbi_config_app.pl)
 1.   use strict;  2.  3.   # Open the output file.  4.   open (OUTPUT, "> ch5_dbi_config.xml")  5.     or die "Can't open ch5_dbi_config.xml file for writing: $!\n";  6.  7.   # Start the Perl "Here" document.  Everything until the  8.   # EOF is printed by the single print statement.  9.   print OUTPUT <<EOF;  10.  11.   <?xml version="1.0" encoding="UTF-8"?>  12.   <!DOCTYPE db_config_information SYSTEM "xml-simple.dtd">  13.   <db_config_information>  14.      <db_user>  15.         <username>mark</username>  16.         <password>mark's secret password</password>  17.      </db_user>  18.      <db_server hostname="rocket" os="Linux">  19.         <server_ip>192.168.1.10</server_ip>  20.         <db_driver>MySQL</db_driver>  21.         <port>3306</port>  22.      </db_server> 23.      <db_server hostname="scooter" os="Microsoft Windows">  24.         <server_ip>192.168.1.50</server_ip>  25.         <db_driver>ODBC</db_driver>  26.         <port>3379</port>  27.      </db_server>  28.   </db_config_information>  29.   EOF  30.  31.   close (OUTPUT); 
Example Discussion

1 “5 As you can already see, the program shown in Listing 5.2 is very simple. The top of the Perl program contains the standard pragma ( use strict ). Note that we don't need an additional use module pragmas because we're only using the standard Perl print function. Then, we open the output file named ch5_dbi_config.xml that will contain the generated XML data.

 1.   use strict;  2.  3.   # Open the output file.  4.   open (OUTPUT, "> ch5_dbi_config.xml")  5.     or die "Can't open ch5_dbi_config.xml file for writing: $!\n"; 

7 “31 In this section of the program, we take advantage of a little-known Perl construct called a "Here" document. It can save a lot of time and greatly simplify the structure of your program. Basically, everything between the two occurrences of the terminating string (in our case, " EOF ") is printed, so all you need to do is insert your XML document between the EOF as you would like it printed. Note that you basically have to type the entire XML document inside the "Here" blocks.

One advantage of the "Here" document is that you don't need to have a print statement on each line. One disadvantage is that you can't have comments inside of a "Here" block ”the comments will show up inside the output file. Here are the four steps to using this construct:

First, following the " << " symbol, we specify a string to terminate all the quoted characters . In our case, the string that signifies the end of the block is " EOF ". Note that we're sending the output to the OUTPUT filehandle.

Second, all lines following the current line down to (but not including) the terminating line are considered part of the output string. So, we basically just insert the entire contents of our XML document. There isn't a limit to the size of the output string, so this output string could span several pages (if required).

Third, we'll need to identify the end of the output block. So, we insert EOF on a line all by itself. Note that the ending tag for a "Here" document (in our case, EOF ) must appear flush against the left margin, and it can't have any trailing spaces or tabs. When you run this program, it prints everything that is contained between the two EOF statements.

Keep this syntax in mind; it comes in handy in a number of situations. If we didn't use the "Here" document syntax, we would have needed a print function on each line of the program. In addition to causing your hands to ache after typing all those print statements, all those print statements would cause your program to be very cluttered and prone to error.

Note

You can find additional information on the Perl "Here" documents by looking at perldoc perldata.


Using the Perl XML::Writer Module

XML::Writer is an XML writer Perl module that was developed by David Megginson (http://www.megginson.com/) to address some of the problems associated with using the standard Perl print function to generate XML data. Most of the problems usually appear when trying to generate complex XML documents using only the standard Perl print function. I will show you how the XML::Writer module simplifies the task of generating an XML document and provides support for generating more complex documents by handling potentially error-prone aspects of XML document generation. Basically, this module addresses just about all the disadvantages related to using the Perl print function.

For example, the module generates escape characters for both attribute values and character data. XML::Writer builds all the required markup text (for example, tags, comments, and processing instructions). In addition, the XML::Writer module executes several checks to verify that the generated XML document is well- formed (for example, that all start tags have corresponding end tags) and simplifies your code. As you can see, the XML::Writer module does a lot of behind-the-scenes work for you. This enables you to concentrate on other parts of the application.

XML::Writer Perl Module Example

Probably the best way to illustrate the capabilities of the XML::Writer module is to start with an example. Let's first look at an example that generates the short, XML configuration file that was shown in Listing 5.1.Yes, this is the same task performed in the previous example (Listing 5.2) using the Perl print function. Now, I'll show you how easy it is to use the XML::Writer module.

Listing 5.3 Program that demonstrates basic XML::Writer functionality. (Filename: ch5_xml_writer_app.pl)
 1.   use strict;  2.   use XML::Writer;  3.   use IO::File;  4.  5.   # Open the output XML document.  6.   my $output = new IO::File(">ch5_dbi_config_writer.xml");  7.  8.   # Instantiate a new XML::Writer object.  9.   my $writer = new XML::Writer(OUTPUT => $output, DATA_MODE=>1,  10.                                  DATA_INDENT=>4);  11.  12.   # Start generating the XML document.  13.   $writer->xmlDecl("UTF-8");  14.   $writer->doctype("db_config_information", "", "xml-simple.dtd");  15.   $writer->startTag("db_config_information");  16.  17.   $writer->startTag("db_user");  18.   $writer->dataElement("username", "mark");  19.   $writer->dataElement("password", "mark's password");  20.   $writer->endTag("db_user");  21.  22.   $writer->startTag("db_server", hostname=>"rocket", os=>"Linux");  23.   $writer->dataElement("server_ip", "192.168.1.10");  24.   $writer->dataElement("db_driver", "MySQL");  25.   $writer->dataElement("port", "3306");  26.   $writer->endTag("db_server"); 27.  28.   $writer->startTag("db_server", hostname=>"scooter", os=>"Microsoft  Windows");  29.   $writer->dataElement("server_ip", "192.168.1.50");  30.   $writer->dataElement("db_driver", "ODBC");  31.   $writer->dataElement("port", "3379");  32.   $writer->endTag("db_server");  33.  34.   $writer->endTag("db_config_information");  35.  36.   # Destroy the XML::Writer object and close generated XML document.  37.   $writer->end();  38.   $output->close(); 

This example program is about the same size in terms of line count as the original example that generated the XML document by using only the Perl print function. However, as you can see, this program is much simpler and easier to maintain and modify. Let's examine this example a little more closely, and I'll explain exactly what happens in each section of the program.

Example Discussion

1 “10 The first portion of the program contains the standard pragma ( use strict ) and two others that you haven't seen yet. First, note that to access the XML::Writer module, you'll need to include the use XML::Writer pragma to load the module. Second, you have the use IO::File pragma. The use IO::File statement loads the IO::File module that is part of the IO module family (Handle, Seekable, File, Pipe, Socket, Dir). In this example, you're using the IO::File module because it provides helper functions used for reading and writing files. So, you use the IO::File module to create a file handle and pass this file handle into the XML::Writer constructor. When you're finished, this file will contain the output XML data.

After creating the filehandle, you need create an XML::Writer object by using the new function call. As you can see, you're passing several arguments into the XML::Writer constructor. Note that all arguments are passed into the XML::Writer constructor as key=>value pairs. The first constructor argument ( $output ) is the handle to the output XML file that will be generated by the XML::Module. The DATA_MODE=>1 argument tells the XML::Writer module to insert new lines around elements, while the DATA_INDENT=>4 argument tells the XML::Writer module the indent step size for elements in the output document. Note that both of these options are for human readability and aren't required. A large number of options are available for the XML::Writer module; however, the arguments that you employed here are some of the most commonly used. Now that you have a new XML::Writer object, you can start the process of actually generating the XML document.

 1.   use strict;  2.   use XML::Writer;  3.   use IO::File;  4.  5.   # Open the output XML document.  6.   my $output = new IO::File(">ch5_dbi_config_writer.xml");  7.  8.   # Instantiate a new XML::Writer object.  9.   my $writer = new XML::Writer(OUTPUT => $output, DATA_MODE=>1,  10.                                   DATA_INDENT=>4); 

Note

For additional information on the IO family of modules, please see perldoc IO. If you're interested specifically in the IO::File module, please see perldoc IO::File.


12 “38 Next , we finally make our first XML::Writer calls with the xmlDecl and startTag methods . The xmlDecl method generates the XML declaration:

 <?xml version="1.0" encoding="UTF-8"?> 

Remember, this must be the first line of your generated XML document. Because the XML::Writer module generates XML data in the order called by the methods, you need to make sure that this is the first method called.

In this section of the program, you're basically using three XML::Writer methods, over and over again. The three primary calls are as follows:

  • startTag ($name, [attribute name =>attribute value]) ” This method generates the start tag for a particular element. Two arguments for this method exist, one required and one optional. The required argument is the element name, and the optional argument is a hash of key-value pairs that correspond to attribute names and attribute values.You will usually need to use this method at the beginning of a block containing nested elements.

  • endTag ” This method generates the end tag for a particular element. It has one argument, the element name. If you don't provide an argument, the XML::Writer module will supply the name of the currently open element. Based on my experience, it is a good idea to provide the element name as an argument. It helps with the readability of your source code, especially for more complex documents. As with the startTag , you will usually need to use this element at the end of a block containing nested elements.

  • dataElement ” This method combines some of the functionality of the startTag and endTag elements. It takes the same arguments as the startTag element ”the element name and an optional hash containing attribute name and value pairs. However, this method generates both the start and end tags for a particular element. If you have a standalone element (that is, an element that doesn't contain any child elements), you will probably use this method.You'll see that you can't use this method at the beginning of a nested block because it generates both the start and end tags.

Now that you have an introduction to the methods that you'll be using, let's take a look at the code in the program that actually uses them.

The first thing you need to do (after printing the XML declaration statement) is create the opening tag for the root element. In the example, the root element is named <db_config_information> . As you can see in the code, we use the <startTag> method to create the opening tag.

Following the opening tag for the <db_config_information> element, we have a child element, <db_user> . The opening and closing tags for the db_user element surround its child elements ( <username> and <password> ). Note that because the <username> and <password> elements don't have any children, you can use the dataElement method rather than a combination of the startTag and endTag methods.

The same approach is followed to generate the contents of the <db_server> elements. One of the only differences between generating <db_server> elements and <db_user> elements is that each of the <db_server> elements has two attributes. Remember, the attributes are passed into the methods as hashes of key value pairs.

After generating all the required tags, you need to call the end method. This XML::Writer method verifies that all the start tags have corresponding end tags. If all the start tags don't have matching end tags, the XML::Writer module will generate a warning.

 12.   # Start generating the XML document.  13.   $writer->xmlDecl("UTF-8");  14.   $writer->doctype("db_config_information", "", "xml-simple.dtd");  15.   $writer->startTag("db_config_information");  16.  17.   $writer->startTag("db_user");  18.   $writer->dataElement("username", "mark");  19.   $writer->dataElement("password", "mark's password");  20.   $writer->endTag("db_user");  21.  22.   $writer->startTag("db_server", hostname=>"rocket", os=>"Linux");  23.   $writer->dataElement("server_ip", "192.168.1.10");  24.   $writer->dataElement("db_driver", "MySQL");  25.   $writer->dataElement("port", "3306");  26.   $writer->endTag("db_server");  27.  28.   $writer->startTag("db_server", hostname=>"scooter", os=>"Microsoft Windows");  29.   $writer->dataElement("server_ip", "192.168.1.50");  30.   $writer->dataElement("db_driver", "ODBC");  31.   $writer->dataElement("port", "3379");  32.   $writer->endTag("db_server");  33.  34.   $writer->endTag("db_config_information");  35.  36.   # Destroy the XML::Writer object and close generated XML document.  37.   $writer->end();  38.   $output->close(); 

So, I've shown you your first example using the XML::Writer Perl module. Granted, it was a simple example, but the purpose was to show you that using the XML::Writer Perl module can reduce both the size and the complexity of your program, while still performing the same task (and not having to worry about all of the low-level details). In the next example, I'll show a more complex application.

A More Advanced XML::Writer Perl Module Example

Let's take a look at another example that generates an XML file from the information contained in a simple Comma Separated Value (CSV) file. Several specialized Perl modules exist for working with CSV files (for example, XML::SAXDriver::CSV, Text::CSV_XS). However, you won't need any of those advanced capabilities because I'm using a simple example and want to focus on the XML generation aspect of the example. For this example, let's assume that you're employed by a bookstore, and they're upgrading their bar code reading system. The problem is that the store inventory in the old system can only be exported to a CSV file, while the new system requires the store inventory to be in a specifically structured XML document. So, basically your task is to convert a CSV file into an XML document that contains the same information.

How do you solve this problem? You need to make sure that you understand the formats of the input and output data. In this case, the CSV file is the input, and the XML file is the output. Let's first look at the structure of the input CSV file that contains the data related to each book. For the sake of simplicity, you will assume that the CSV file has six fields in the following format:

 Title,Author,ISBN,Publisher,Price,Quantity 

As you can see, the fields are ordered and separated by commas. This input information from the CSV file must then be mapped to the output XML document.

The first step in this mapping is to define a DTD or a schema (depending on what you're more comfortable working with). A DTD that defines the format of our XML document is shown in Listing 5.4.

Listing 5.4 DTD that describes the book inventory XML document. (Filename: ch5_book_inventory.dtd)
 <?xml version="1.0" encoding="UTF-8"?>  <!ELEMENT book_inventory (book*)>  <!ELEMENT book (author,isbn,publisher,price,quantity)>  <!ATTLIST book title CDATA #REQUIRED>  <!ELEMENT author (#PCDATA)>  <!ELEMENT isbn (#PCDATA)>  <!ELEMENT publisher (#PCDATA)>  <!ELEMENT price (#PCDATA)>  <!ELEMENT quantity (#PCDATA)> 

As you can see, the DTD is very straightforward and maps directly to the CSV input file. The book_inventory element is the root element, and it can have multiple book child elements. The book element also contains a Title attribute, which contains the title of the book. The other fields contained within the book node represent particular data about that book. Listing 5.5 shows an XML schema that corresponds to the required XML file format.

Listing 5.5 XML schema that describes the book inventory XML document. (Filename: ch5_book_inventory.xsd)
 <?xml version="1.0" encoding="UTF-8"?>  <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"  elementFormDefault="qualified">     <xs:element name="author" type="xs:string"/>     <xs:element name="book">        <xs:complexType>           <xs:sequence>              <xs:element ref="author"/>              <xs:element ref="isbn"/>              <xs:element ref="publisher"/>              <xs:element ref="price"/>              <xs:element ref="quantity"/>           </xs:sequence>           <xs:attribute name="title" type="xs:string" use="required"/>        </xs:complexType>     </xs:element>     <xs:element name="book_inventory">        <xs:complexType>           <xs:sequence>              <xs:element ref="book" minOccurs="0" maxOccurs="unbounded"/>           </xs:sequence>        </xs:complexType>     </xs:element>     <xs:element name="isbn" type="xs:positiveInteger"/>     <xs:element name="price" type="xs:string"/>     <xs:element name="publisher" type="xs:string"/>     <xs:element name="quantity" type="xs:positiveInteger"/>+  </xs:schema> 

Now that you are familiar with both the source and destination data formats, you can develop a Perl program to convert between the input (CSV) and output (XML) formats. The program shown in Listing 5.6 performs the conversion between the two formats.

Listing 5.6 XML::Writer-based program used to convert from CSV to XML. (Filename: ch5_book_inventory_app.pl)
 1.   use strict;  2.   use XML::Writer;  3.   use IO;  4.  5.   # Open the file provided in the command line argument.  6.   my $input = new IO::File(shift);  7.  8.   # Open the output file.  9.   my $output = new IO::File(">ch5_book_inventory_report.xml");  10.  11.   # Instantiate an XML::Writer object.  12.   my $writer = XML::Writer->new(OUTPUT => $output, DATA_MODE => 1, DATA_INDENT => 2);  13.  14.   # Start generating the XML document.  15.   $writer->xmlDecl("UTF-8");  16.   $writer->doctype("book_inventory", "", "ch5_book_inventory.dtd");  17.   $writer->comment("**** Book Inventory Database ****");  18.   $writer->startTag("book_inventory");  19.  20.   # Create a list of names that match the input CSV column names.  21.   my @column_names = qw(Title Author ISBN Publisher Price Quantity);  22.  23.   # Loop the input file.  24.   while (<$input>) {  25.     chomp; # chomp the new line char from each line  26.  27.     # Remove leading and trailing whitespace, split on a ','.  28.     my @data = map {s/^\s+//; s/\s+$//; $_;} split /,/;  29.     $writer->startTag("book", "Title" => $data[0]);  30.  31.     # Loop through the data contained in this row.  32.     foreach my $index (1..$#column_names) { 33.       $writer->startTag($column_names[$index]);  34.       $writer->characters($data[$index]);  35.       $writer->endTag($column_names[$index]);  36.     }  37.     $writer->endTag("book");  38.   }  39.  40.   # Don't forget the end tag.  41.   $writer->endTag("book_inventory"); 42.  43.   # Destroy the XML::Writer object and close the output file.  44.   $writer->end();  45.   $output->close(); 
Example Discussion

1 “9 You first employ the use pragma to load the XML::Writer and IO modules.You then open two files using the IO module. The first file contains the input CSV data, and the filename will be provided through the command-line argument. The second file will be used for output and will contain the generated XML document. In this example, the output file is named ch5_book_inventory_report.xml.

 1.   use strict;  2.   use XML::Writer;  3.   use IO;  4.  5.   # Open the file provided in the command line argument.  6.   my $input = new IO::File(shift);  7.  8.   # Open the output file.  9.   my $output = new IO::File(">ch5_book_inventory_report.xml"); 

11 “18 The new constructor method for the XML::Writer is called with DATA_MODE and DATA_INDENT attributes set to desirable values. As you recall from the previous example, the DATA_MODE=>1 argument tells the XML::Writer module to insert new lines around elements, while the DATA_INDENT=>4 argument tells the XML::Writer module the indent step size for elements in the output document.You can now start processing, transforming, and generating the XML data.

You start off by calling xmlDecl() to declare the XML, UTF-8 being the default encoding.You're using the XML::Writer doctype function to generate the DOCTYPE statement that will identify the external DTD. For others to be able to identify the content of the file and the date it was generated, you call the comment() function, which will print the string argument as a comment.

You call startTag with "books" as the argument to generate the root element.

 11.   # Instantiate an XML::Writer object.  12.   my $writer = XML::Writer->new(OUTPUT => $output, DATA_MODE => 1, DATA_INDENT => 2);  13.  14.   # Start generating the XML document.  15.   $writer->xmlDecl("UTF-8");  16.   $writer->doctype("book_inventory", "", "ch5_book_inventory.dtd");  17.   $writer->comment("**** Book Inventory Database ****");  18.   $writer->startTag("book_inventory"); 

20 “29 In this section of the application, you create an array named @column_names that contains literal column names.

 my @column_names = qw(Title Author ISBN Publisher Price Quantity); 

Note that these are the column names that appear in the CSV input file. The Perl qw function in this statement is equivalent to splitting the strings on whitespace. As you'll soon see, you'll use the column headings as your tag names when you generate the output XML file.

The next step reads through the file line by line and processes the data. You're using the Perl chomp() function to strip the new line ending from each line.

Because you didn't impose any spacing rules for your CSV file, you want to make sure that all the leading and trailing white spaces surrounding the data are removed, and you do that with the following line:

 my @data = map {s/^\s+//; s/\s+$//; $_;} split /,/; 

This is a busy expression, so let's take a moment to go through and explain it, so that you know what's happening here. What you're doing is basically combining three operations into one line of Perl code. Remember, this statement is inside the while ( <$input> ) loop, so each line of the input file is being processed , one at a time. Let's walk through this using a line of the input file as a sample. The first line of the input CSV file is shown in the following:

 MySQL , Paul DuBois , 34-3485-2399, New Riders, 49.99, 4 

The line is split using commas as the delimiters. So, for the first line, the split function has extracted the following strings:

  • " MySQL "

  • " Paul DuBois "

  • " 34-3485-2399 "

  • " New Riders "

  • " 49.99 "

  • " 4 "

The quotes are only included, so you can see that some of the records have spaces before and after the contents of the records. These five strings are passed to the map function that evaluates the substitution expressions for each element. The result is an array that contains the results of each substitution expression. The Perl statement s/^\s+// removes leading whitespace while the statement s/\s+$// removed trailing whitespace. After the evaluation, the array named data contains the following fields:

  • $data[0] = " MySQL "

  • $data[1] = " Paul DuBois "

  • $data[2] = " 34-3485-2399 "

  • $data[3] = " 49.99 "

  • $data[4] = " 4 "

As you can see from the contents of the @data array, the leading and trailing whitespace has been removed from each element in the array. We now have clean input data to work with.

 20.   # Create a list of names that match the input CSV column names.  21.   my @column_names = qw(Title Author ISBN Publisher Price Quantity);  22.  23.   # Loop the input file.  24.   while (<$input>) {  25.     chomp; # chomp the new line char from each line  26.  27.     # Remove leading and trailing whitespace, split on a ','.  28.     my @data = map {s/^\s+//; s/\s+$//; $_;} split /,/;  29.     $writer->startTag("book", "Title" => $data[0]); 

31 “45 Now that you've cleaned up the input data, you're ready to start generating the XML document. The first step for each book element is to generate the <book> tag. Because each <book> tag contains the " Title " attribute, you generate the <book> tag by passing the key-value pair argument to the startTag function. The first argument to startTag is always the element name, and the following arguments consist of key/value pairs that denote the attribute name/value pairs.You use the first element of @data as the attribute value because the first field in the CSV file is the book Title.You then loop through the remaining elements in the array and generate the XML data for each book element.

Because the array @column_names subscripts match up with @data , you use $index to access the same subscript of both arrays, and therefore use @column_data as the element name and @data as the actual data.

Note

Remember that you are responsible for following the XML grammar and properly nesting the elements. Just follow the last in, first out procedure. If element 1 is opened and then element 2 is opened, element 2 must be closed before element 1.


After every tag is closed, you call the end method to finish the XML output (which verifies starting and ending tag pairs, among other things) and then close the output file. At this point, the script has generated a file named ch5_book_inventory_report.xml that contains the new book inventory in an XML format.

 31.     # Loop through the data contained in this row.  32.     foreach my $index (1..$#column_names) {  33.       $writer->startTag($column_names[$index]);  34.       $writer->characters($data[$index]);  35.       $writer->endTag($column_names[$index]);  36.     }  37.     $writer->endTag("book");  38.   }  39.  40.   # Don't forget the end tag.  41.   $writer->endTag("book_inventory"); 42.  43.   # Destroy the XML::Writer object and close the output file.  44.   $writer->end();  45.   $output->close(); 

Note that when you run this application from the command line, you must pass the input CSV filename as a command-line argument. The output of this program is shown in Listing 5.7.

Listing 5.7 Generated XML book inventory. (Filename: ch5_book_inventory_report.xml)
 <?xml version="1.0" encoding="UTF-8"?>  <!DOCTYPE book_inventory SYSTEM "ch5_book_inventory.dtd">  <! **** Book Inventory Database **** >  <book_inventory>    <book Title="MySQL">      <Author>Paul DuBois</Author>      <ISBN>34-3485-2399</ISBN>      <Publisher>New Riders</Publisher>      <Price>49.99</Price>      <Quantity>4</Quantity>    </book>    <book Title="C++ XML">      <Author>Fabio Arciniegas</Author>      <ISBN>0-7357-1052-X</ISBN>      <Publisher>New Riders</Publisher>      <Price>39.99</Price>      <Quantity>3</Quantity>    </book>    <book Title="Writing Compilers and Interpreters">      <Author>Ronald Mak</Author>      <ISBN>0-471-11353-0</ISBN>      <Publisher>Wiley</Publisher>      <Price>59.99</Price>      <Quantity>7</Quantity>    </book>    <book Title="Object Oriented Perl">      <Author>Damian Conway</Author>      <ISBN>0-548-85785-0</ISBN>      <Publisher>Manning</Publisher>      <Price>34.99</Price>      <Quantity>9</Quantity>    </book>  </book_inventory> 

The output shown in Listing 5.7 now contains all the inventory data that has been transformed from CSV to XML. As you will see in Chapter 7, "Transforming Miscellaneous Data Formats to XML (and Vice-Versa)," there is an easier way to convert directly from CSV to XML by using the XML::SAXDriver::CSV Perl module. However, in this chapter, we demonstrated the use of the XML::Writer Perl module combined with the standard Perl split function.



XML and Perl
XML and Perl
ISBN: 0735712891
EAN: 2147483647
Year: 2002
Pages: 145

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net