XML Bulk Loader, Version 1.01

Java Packages for Bulk Manipulating Data contained in
Relational Database

Sergey Yakovlev

Contents

1.0 Introduction
2.0 Getting Started
    2.1 System Requirements
    2.2 Downloading and Installing XML Bulk Loader
    2.3 Using XML Bulk Loader in Your Application
3.0 About the XML Bulk Load Process
4.0 Record Generation Process
    4.1 Generating Records
        4.1.1 Scope of a Node
        4.1.2 Record Generation Process
            4.1.2.1 Create Mode
            4.1.2.2 Update Mode
            4.1.2.3 Delete Mode
        4.1.3 Record Subset and the Key Ordering Rule
    4.2 Using Document Type Declaration and Name Mapping
        4.2.1 Default Mapping of XML Elements and Attributes to Tables and Columns
        4.2.2 Explicit Mapping of XML Elements and Attributes to Tables and Columns
        4.2.3 Specifying Relationships
            4.2.3.1 Walk the Relationships
            4.2.3.2 One-to-One or One-to-Many Relationships
            4.2.3.3 Many-to-One or Multiple Parent Relationships
        4.2.4 Creating Valid ID, IDREF, and IDREFS Type Attributes by Using Prefix
5.0 Rules for Creating XML Data Structures
6.0 Additional Programming Considerations
    6.1 Root Element Attributes and Database Connecting
    6.2 Java Custom Extensions
    6.3 Key Generation
7.0 Samples  
    7.1 Inserting Data
    7.2 Updating Data
    7.3 Deleting Data
8.0 Licensing and Support
    8.1 Licensing
    8.2 Support

Appendix A: Sample Documents and Tables
    A.1 Document Type Definition and Name Mapping
    A.2 Tables for Samples

1.0 Introduction

XML is rapidly becoming the de facto standard for data exchange over the Internet and across multiple disparate platforms. The ability to populate database tables with data contained in XML documents is a common application requirement. XML Bulk Loader is a set of Java packages for insert/update/delete data contained in XML documents into/from relational databases. An instance of it can be created and used by applications developed using Java language. A sample application can be run from the command line to populate database tables.

You can control the execution of the Bulk Load operation through a number of options provided by the XML Bulk Loader package. One feature not present in many other bulk load tools  that is available in XML Bulk Loader is the ability to execute a single Bulk Load operation to bulk insert/update/delete data into/from multiple database tables related by parent-child relationships implemented using primary and foreign keys. It also provides a higher level of performance when bulk inserting large volumes of data contained in XML documents.

The objective of this paper is to provide a code-driven introduction to the various aspects of programming the XML Bulk Loader Object Model. It is primarily targeted at database application developers who are familiar with the XML features. To understand and apply the information presented in this paper, you will need familiarity with the XML markup language, and XML Document Type Declaration. You will also need to be familiar with the Java programming language and development environment.

For a general discussion of XML and databases, see XML Structures for Existing Databases.

2.0 Getting Started

2.1 System Requirements

To run XML Bulk Loader, you need the following software:

 

2.2 Downloading and Installing XML Bulk Loader

To download the current version of XML Bulk Loader, see:

To install XML Bulk Loader:

  1. Unzip the downloaded file with a tool such as jar or WinZip.
  2. Add xmltool.jar to your CLASSPATH. For example:

    c:\Java\xmltool\lib\xmltool.jar;c:\Java\jdk1.3.1\bin;c:\Java\xerces-1_1_1\xerces.jar;.\
    

2.3 Using XML Bulk Loader in Your Application

You can use XML Bulk Loader as middleware -- that is, it sits between your application and a database. Because of this, you can write your own application to use it. For example, you might use the following code to transfer the data in the TestCreate.xml document to the database according to the mapping defined in create_map.dtd. This uses the XMLParser, XMLHandlerImpl, and DBManagerImpl classes from XML Bulk Loader.

 
   // Create a new XMLParser object, XMLHandler and DBManager implementation objects.
   XMLParser parser = new XMLParser(new XMLHandlerImpl(new DBManagerImpl(), "sql_map.properties"));
   
   //Parse the  input
   parser.setEcho(false); // Set off Echo
   parser.setValidating(true); // Will validate documents as they are parsed
   parser.parse(new InputSource("TestCreate.xml"));

XML Bulk Loader includes three sample programs (TestCreate, TestUpdate, and TestDelete) to show you how to use different parts of the system.

3.0 About the XML Bulk Load Process

It is important to understand that the objective of an XML Bulk Load operation is not to store the contents of an XML document in native XML format in a single field of a database table. The objective of an XML Bulk Load operation is to generate relational database records from the semi-structured data contained in an XML document, and to insert the generated records into one or more target database tables.

For example, let us assume we have a database table called Cust that was created using the following CREATE TABLE statement:

  
CREATE TABLE Cust ( 
       Customer_ID  INT   PRIMARY KEY,
       Company_Name VARCHAR2(20), 
       City         VARCHAR2(20)
)       

The following is an XML document called CustCreate.xml. CustCreate.xml is an example of a source XML document that can be used to generate relational database records that can be inserted into the Cust table:

 
<?xml version="1.0"?>
<!DOCTYPE Customers SYSTEM "create_map.dtd">
<Customers status="create">
    <Customer
         CustID="Cust1" 
         Company="BellSouth"
         City="New York"/>
    <Customer
         CustID="Cust2"
         Company="Barnes & Noble"
         City="New York"/>
    <Customer
         CustID="Cust3"
         Company="Comp USA"
         City= "Tampa"/>
    <Customer
         CustID="Cust4"
         Company="Borders"
         City="Charlotte"/>
</Customers>

Each <Customer> element in CustCreate.xml can be used to generate a record of data that can be inserted into the Cust  database table. The attributes of each <Customer> element (CustID, Company, and City) can be used to generate the values for the fields in each record.

Notice that the element and attribute names (with the exception of City) in CustCreate.xml do not match one-to-one with the corresponding database table and column names. This implies the need for an intermediary component that can be used to define the mappings between the element/attribute names in the source XML document and the table/column names in the target database. The role of the Name Mapping Properties document used in the Bulk Load operation is to address this requirement. This document is a Property List that defines the names of elements and attributes that appear in the source XML document.

Take a look at the following name mapping properties document called NameMap.properties that defines the correspondence between the elements/attributes in CustCreate.xml and the Cust database table:

# Database map properties file
Customer=CUST
CustID=CUSTOMER_ID
Company=COMPANY_NAME
City=CITY

By supplying the paths to name mapping properties document and the XML document, you ensure that the XML Bulk Loader will process the XML document in a sequential fashion generate the statements required to insert/update/delete the data in the XML document into/from the database table. In the case of our sample NameMap.properties and CustCreate.xml documents, the XML Bulk Loader object would generate four INSERT statements (using JDBC) to insert the four records of data contained in CustCreate.xml into the Cust database table.

Unlike other similar tools, the XML Bulk Loader object does not load the entire source XML document into memory. It also does not generate a complete recordset before sending the data to database. This is because XML input data can be large and loading the entire document into memory can be expensive. Instead, XML Bulk Loader interprets the XML data as a stream and interprets it reads it. As the utility reads the data, it identifies the database table(s), generates the appropriate record(s) from the XML data source, and then sends the record(s) to database for manipulation (insert, update or delete).

For example, the following source XML document consists of <Customer> elements and <Order> child elements:

<Customer ...>
    <Order.../>
    <Order .../>
     ...
</Customer>
...

As XML Bulk Load reads the <Customer> element, it generates a record for the Customer table. If current status is "create", it inserts this record into the table. When it reads the </Customer> end tag and the current status is "update" or "delete", XML Bulk Loader updates/deletes that record in/from the table in database. In the same manner, when it reads the <Order> element, XML Bulk Load generates a record for the Order table (and inserts this record if status is "create"). Then, if the current status is "update" or "delete", updates/deletes that record in/from the database table upon reading the </Order> end tag.

4.0 Record Generation Process

XML Bulk Loader processes the XML input data and prepares records for the appropriate tables in database. The logic in XML Bulk Loader determines when to generate a new record, what attribute values to copy into the fields of the record, and when the record is complete and ready to be sent to database for manipulation (insert, update or delete).

XML Bulk Loader handles name mapping properties, including column and table mappings (specified explicitly by using properties or implicitly through the default mapping).

4.1 Generating Records

Understanding record generation requires understanding the following concepts:

4.1.1 Scope of a Node

A node (an element or an attribute) enters "into scope" when XML Bulk Loader encounters it in the XML input data stream. For an element node, the start tag of the element brings the element in scope. For an attribute node, the attribute name brings the attribute in scope.

A node leaves scope when there is no more data for it: either at the end tag (in the case of an element node) or at the end of an attribute value (in the case of an attribute node).

4.1.2 Record Generation Process

IMPORTANT: In this model, because a record lives as long as the associated node is in scope, you must define all of the data that is associated with the record within the scope of the node.

4.1.2.1 Create Mode

When a node (element or attribute) enters into scope, there is a potential for generating a record from that node and inserting it into database. The record lives as long as the associated node is in scope. When the node goes out of scope, XML Bulk Loader does nothing.

For example, consider this DTD fragment:


<!ELEMENT customer (custOrder)*>
<!ATTLIST customer
    customerID ID #REQUIRED
    companyName CDATA #IMPLIED>

The DTD specifies a <customer> element with customerID and companyName attributes. The sql_map.properties maps the <customer> element to the Cust table:


customer=CUST
customerID=CUSTOMER_ID
companyName=COMPANY_NAME

Consider this fragment of an XML document:


<customer customerID=":1" companyName="xyz" />
<customer customerID=":2" companyName="abc" />
...

When XML Bulk Loader is provided with the DTD and name mappings that are described in the preceding paragraphs and XML data as input, it processes the nodes (elements and attributes) in the source data as follows:

XML Bulk Loader follows this process for each subsequent <customer> element.

4.1.2.2 Update Mode

When a node (element or attribute) enters into scope, there is a potential for generating a record from that node. The record lives as long as the associated node is in scope. When the node goes out of scope, XML Bulk Loader considers the generated record complete (with data) and sends it to database for updating.

For example, consider the DTD and name mapping fragments as in create mode.

Consider this fragment of an XML document:


<customer customerID=":1" companyName="xyz_new" />
<customer customerID=":2" companyName="abc_new" />
...

When XML Bulk Loader is provided with the DTD and name mappings that is described in the preceding paragraphs and XML data as input, it processes the nodes (elements and attributes) in the source data as follows:

XML Bulk Loader follows this process for each subsequent <customer> element.

4.1.2.3 Delete Mode

When a node (element or attribute) enters into scope, there is a potential for generating a record from that node. The record lives as long as the associated node is in scope. When the node goes out of scope, XML Bulk Loader considers the generated record complete (with data) and sends it to database for deleting.

For example, consider this DTD fragment:


<!ELEMENT customer (custOrder)*>
<!ATTLIST customer
    customerID ID #REQUIRED>

The DTD specifies a <customer> element with customerID attribute. The sql_map.properties maps the <customer> element to the Cust table:


customer=CUST
customerID=CUSTOMER_ID

Consider this fragment of an XML document:


<customer customerID=":1" />
<customer customerID=":2" />
...

When XML Bulk Loader is provided with the DTD and name mappings that is described in the preceding paragraphs and XML data as input, it processes the nodes (elements and attributes) in the source data as follows:

XML Bulk Loader follows this process for each subsequent <customer> element.

4.1.3 Record Subset and the Key Ordering Rule

The subset term refers to the set of records that is generated on the "foreign" side of the relationship. In the following example, the CustOrder records are on the foreign side.

For example, a database contains these two tables:

The CustomerID in the CustOrder table is a foreign key that refers to the CustomerID primary key in the Cust table.

Now, consider the XML structure as specified in the following DTD. This DTD uses containment to specify the relationship between the Cust and CustOrder tables (where related information is nested inside a parent element). Alternatively, if you want to keep the XML structures separate - like the tables of a database - you can use an ID to point to a corresponding structure that has an IDREF attribute.


<!ELEMENT customer (custOrder)*>
<!ATTLIST customer
    customerID ID #REQUIRED
    companyName CDATA #IMPLIED
    city CDATA #IMPLIED
    createdDate CDATA #REQUIRED>
    
<!ELEMENT custOrder EMPTY>
<!ATTLIST custOrder
    custOrderID ID #REQUIRED
    createdDate CDATA #REQUIRED
    customerIDREF IDREF #IMPLIED>

The sample XML data and the steps to create a working sample are given below.

Here are two observations about the mapping schema:

4.2 Using Document Type Declaration and Name Mapping

XML provides a mechanism, the document type declaration, to define constraints on the logical structure and to support the use of predefined storage units. An XML document is valid if it has an associated document type declaration and if the document complies with the constraints expressed in it.

These declarations can be used within the DTD to specify XML to relational mapping. Name Mapping includes mapping between elements and attributes in the XML structure to tables (views) and columns in the databases.

4.2.1 Default Mapping of XML Elements and Attributes to Tables and Columns

By default, an element in an XML document maps to the table (view) with the same name in the specified database, and an attribute maps to the column with the same name in the table.

4.2.2 Explicit Mapping of XML Elements and Attributes to Tables and Columns

In providing an XML view of the relational database ,using DTD, the elements and attributes in the XML document must be mapped to database tables and columns. The rows in the database table/view will map to elements in the XML document. The column values in the database map to attributes. If the name of an element/attribute is not the same name as the table/view or column name to which it maps, the following name mapping properties are used to specify the mapping between an element or attribute in an XML document and the table (view) or column in a database:

<xml element name>=<database table name>

     Maps an XML element to a database table.

<xml attribute name>=<database column name>

     Maps an attribute to a database column.

4.2.3 Specifying Relationships

The elements in an XML document can be related. The elements can be nested hierarchically, and ID, IDREF, or IDREFS relationships can be specified between the elements.

For example, in an XML document, a <customer> element contains <order> subelements. The <customer> element maps to the Customers table and the <order> element maps to the Orders table in the database. These underlying tables, Customers and Orders, are related because customers place orders. The CustomerID in the Orders table is a foreign key referring to the CustomerID primary key in the Customers table. You can create hierarchical structures, which allow you to use containment to show relationships between data (where related information is nested inside a parent element). Alternatively, if you want to keep the XML structures separate - like the tables of a database - you can use an ID to point to a corresponding structure that has an IDREF attribute.

In the DTD, the element type declaration is used to nest the schema elements hierarchically, on the basis of primary key and foreign key relationships among the underlying tables to which the elements map. In specifying the element type declaration, you must identify:

This information is used in generating the proper hierarchy. (For each <customer> element, the related <order> elements appear as subelements.)

4.2.3.1 Walk the Relationships

You need to walk the relationships between the table (or tables) to add element content or ID-IDREF(S) pairs as appropriate. This process is similar to the process you would use when walking a tree data structure - you navigate each of the relationships, then each of the relationships from the children of the previous relationships, and so on, until all the relationships contained in the subset of tables you have chosen to include in your XML document have been traversed. Relationships that lead outside of the subset of tables you're representing do not need to be traversed.

Again, when you have a choice of directions in which a relationship may be followed, you do so in the direction that makes the most business sense - for example, you'll probably need to go from Invoice to LineItem pretty frequently, but much less often from LineItem to Invoice. On the other hand, a relationship such as the one between Customer and Invoice may need to be walked in either direction as frequently, making it necessary to define the relationship in both directions. You need to determine the direction in which the relationships will be walked, in order to determine whether pointing or containment should be used to represent the relationships.

4.2.3.2 One-to-One or One-to-Many Relationships

First consider the case where a relationship is one-to-one or one-to-many in the direction you selected for the relationship traversal, and the relationship is the only one in the selected subset of tables where this table is the destination of a relationship traversal. Then you should represent the relationship by adding the child element as element content of the parent content.

Assign the multiplicity of the element according to the following table:

If the relationship is  Set the multiplicity to
One-to-one ?
One-to-many *

Examples of element type declarations:


<!ELEMENT customer (order)*>
<!ATTLIST customer
    CustomerID ID #REQUIRED
    CompanyName CDATA #IMPLIED
    City CDATA #IMPLIED
    CreatedDate CDATA #REQUIRED>
    
<!ELEMENT order EMPTY>
<!ATTLIST order
    OrderID ID #REQUIRED
    CreatedDate CDATA #REQUIRED>
4.2.3.3 Many-to-One or Multiple Parent Relationships

If the relationship is many-to-one, or the child has more than one parent, then you need to use pointing to describe the relationship. This is done by adding an IDREF or IDREFS attribute to the element on the parent side of the relationship. The IDREF should point to the ID of the child element. If the relationship is one-to-many, and the child has more than one parent, you should use an IDREFS attribute instead.

Note that if you have defined a relationship to be navigable in either direction, for the purposes of this analysis it really counts as two different relationships.

Note that these rules emphasize the use of containment over pointing whenever it is possible. Because of the inherent performance penalties when using the DOM and SAX with pointing relationships, containment is almost always the preferred solution. If you have a situation that requires pointing, however, and its presence in your structures is causing too much slowdown in your processing, you may want to consider changing the relationship to a containment relationship, and repeating the information pointed to wherever it would have appeared before.

Applying this rule to example and adding IDREF/IDREFS attributes, you arrive at the following:


<!ELEMENT customer EMPTY>
<!ATTLIST customer
    CustomerID ID #REQUIRED
    CompanyName CDATA #IMPLIED
    City CDATA #IMPLIED
    CreatedDate CDATA #REQUIRED>
    
<!ELEMENT order EMPTY>
<!ATTLIST order
    OrderID ID #REQUIRED
    CreatedDate CDATA #REQUIRED
    CustomerIDREF IDREF #IMPLIED>

4.2.4 Creating Valid ID, IDREF, and IDREFS Type Attributes by Using Prefix

An attribute can be specified to be an ID type attribute. Attributes specified as IDREF or IDREFS can then be used to refer to the ID type attributes, enabling links between documents.

ID, IDREF, and IDREFS correspond to PK/FK (primary key/foreign key) relationships in the database, with few differences. In an XML document, the values of ID type attributes must be distinct. If CustomerID and OrderID attributes are specified as ID type in an XML document, these values must be distinct. However, in a database, CustomerID and OrderID columns can have the same values. (For example, CustomerID = 1 and OrderID = 1 are valid in the database).

For the ID, IDREF, and IDREFS attributes to be valid:

If an XML document contains multiple IDs, use the prefix followed by colon to ensure that the values are unique.

For example, consider this DTD fragment:


<!ELEMENT customer EMPTY>
<!ATTLIST customer
    customerID ID #REQUIRED>
    
<!ELEMENT order EMPTY>
<!ATTLIST order
    orderID ID #REQUIRED
    customerIDREF IDREF #IMPLIED>

Then, consider this fragment of an XML document:


<customer customerID="customer:1" />
<customer customerID="customer:2" />
<customer customerID="customer:3" />
<order orderID="order:1" customerIDREF="customer:2"/>
...

In the DTD above, the orderID attribute of <order> and customerID attribute of <customer> are declared as ID type. To ensure that the IDs are valid, the prefix is specified. The customerIDREF attribute of <order> is declared as an IDREF type, thus establishing a primary-key/foreign-key relationship.

IMPORTANT: The prefix and colons do not appear in generated SQL statements.

5.0 Rules for Creating XML Data Structures

You must bear in mind as you create these structures that there are usually many XML structures that may be used to represent the same relational database data. The techniques described in this chapter should allow you to optimize your documents for rapid processing and minimum document size. Using the techniques discussed in this chapter, you should be able to easily move information between your relational database and XML documents.

Here are the eleven rules that have been defined for the development of XML structures for data in a relational database:

6.0 Additional Programming Considerations

6.1 Root Element Attributes and Database Connecting

When a root element enters into scope, there is a potential for opening a database connection from that element. The connection lives as long as the associated root element is in scope. When the root element goes out of scope, XML Bulk Loader considers the opened connection complete (with data) and closes it.

For example, consider this XML document fragment:


<ROOT driver="oracle.jdbc.driver.OracleDriver"
         url="jdbc:oracle:thin:@server:1521:ILMS27"
         user="scott"
         password="tiger"
         status="create">
         
     ... 
        
</ROOT>

The following optional attributes are used to specify the connection to database:

driver

The fully qualified driver class name. For example: oracle.jdbc.driver.OracleDriver.

url

The JDBC URL for the database connection. This URL typically begins with jdbc: and a short code name for the driver, followed by another colon. The rest of the URL depends on the type of driver you are using. For example, you might need to specify a host and port; alternatively, the name of a database file might suffice, or an ODBC DSN. If in doubt, refer to the documentation for the driver you are using.

user
password

The user name and password, if required by your database configuration.

The status required attribute is used to specify the type of bulk manipulating. It has three predefined values:

NOTE: If you omit one or more optional attributes, you'll be provided with the New Database Connection dialog box to enter the omitted information.

6.2 Java Custom Extensions

With Java Custom Extensions (JCE), you can generate the field values dynamically at run-time. JCE may be used in the value of element attributes. This is done by placing the JCE class name between "${" and "}" in the attribute value. For example, if there is a "com.synex.xml.ext.CurrentDate" class with the method getValue() that returns the current system date, then this could be used in an attribute like this: ${com.synex.xml.ext.CurrentDate}.

NOTE: The JCE class should implement CustomAction interface.

The following example class gets the current date:


public class CurrentDate implements CustomAction {

    public java.lang.String getValue() {
        return new java.sql.Timestamp(new java.util.Date().getTime()).toString();
    }
    
}

Then, consider this fragment of an XML document:


<custOrder custOrderID="custOrder:1"
           createdDate="${com.synex.xml.ext.CurrentDate}"/>
...

In the example above, the createDate attribute of <custOrder> is settled as the current system date during the bulk loading. Also, you can use JCE for generating of ID unique values or other application specific values.

6.3 Key Generation

If you want to create a primary key that should be used in the INSERT statement, then you must not specify an ID value (prefixed by a colon). For example:


<custOrder custOrderID="custOrder1"/>
<custOrder custOrderID="custOrder2"/>
...

IMPORTANT: XML Bulk Loader features automatic generation of keys for NUMERIC fields only.

6.4 Tips and Tricks

Here is a short list of ways that might help your code run faster:

7.0 Samples

XML Bulk Loader comes with three samples, TestCreate, TestUpdate, and TestDelete. These can be found in the samples subdirectory.

Applications that use XML Bulk Loader usually use a specific JDBC driver. The sample programs are no different. They use the JDBC driver from Oracle. Thus, if you want to run the samples or use them as a starting point for your application, you must either install this software on your system or modify the sample code.

If you decide to change the code, here is a list of things you might need to change. These are clearly labeled in the samples and generally separated from the rest of the code.

XML Bulk Loader also comes with three sets of sample data that you can use with the sample applications. This is described in Appendix A, "Sample Documents and Data".

7.1 Inserting Data

TestCreate is a simple command-line application that inserts data contained in XML file into the database according to a particular map document. It shows how to use the XMLParser, XMLHandlerImpl, and DBManagerImpl classes.

When inserting data from an XML document to the database, use the command:

   java com.synex.xml.sax.XMLParser -sqlm=<name-map-file> <xml-file>

For example, to insert data from the sample file TestCreate.xml to the database according the name map document sql_map.properties, use the command:

   java com.synex.xml.sax.XMLParser -sqlm=sql_map.properties TestCreate.xml

Before you use the TestCreate sample, you must create the tables that you want to transfer data to. If you are using the sample data, see the table schemas in Appendix A, "Sample Documents and Data".

7.2 Updating Data

Like TestCreate, TestUpdate is a simple command-line application that updates existing data in the database according to a particular map.

To update existing data, use the command:

   java com.synex.xml.sax.XMLParser -sqlm=sql_map.properties TestUpdate.xml

Before you use the TestUpdate sample, you must create the tables that you want to update data in. Then, you must insert some data rows in these tables using TestCreate Sample or manually. If you are using the sample data, see the table schemas in Appendix A, "Sample Documents and Data".

7.3 Deleting Data

TestDelete is a simple command-line application that deletes existing records from the database tables.

To run TestDelete, use the command:

   java com.synex.xml.sax.XMLParser -sqlm=sql_map.properties TestDelete.xml

Before you use the TestDelete sample, you must create the tables that you want to delete data from. Then, you must insert some data rows in these tables using TestCreate Sample or manually. If you are using the sample data, see the table schemas in Appendix A, "Sample Documents and Data".

8.0 Licensing and Support

8.1 Licensing

Copyright (C) 2002 Sergey Yakovlev

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  
This is one of a set of classes that make up XML Bulk Loader,
a framework for bulk manipulating data contained in relational database.

The latest version of XML Bulk Loader is available at URL:
http://www.geocities.com/synexsoft/downloads/xblkld1.zip.

8.2 Support

If you have questions about how to use XML Bulk Loader, the first thing you should do is read the documentation and look at the sample programs.

If you still have a question, you can send email at syakovlev@hotmail.com.

Appendix A: Sample Documents and Tables

XML Bulk Loader comes with a set of sample XML documents: TestCreate.xml, TestUpdate.xml and TestDelete.xml.The sample documents and the tables needed to store these documents according to the shipped DTDs and name mapping document are described in this section.

A.1 Document Type Definition and Name Mapping

The samples come with a single name mapping document (sql_map.properties), as well as three DTDs:

A.2 Tables for Samples

The following tables are needed to store the sample documents, as they are mapped with sql_map.properties and DTDs.

Cust Cust_Order
Customer_ID INT Order_ID INT
Company_Name VARCHAR(20) Created_Date DATE
City VARCHAR(20) Customer_ID INT
Created_Date DATE

Product Order_Detail
Product_ID INT Order_ID INT
Product_Name VARCHAR(20) Product_ID INT
Created_Date DATE Order_Type VARCHAR(20)

For more details see the CREATE TABLE statements for Oracle database in sample_data.sql.