XML table mapping

Since XML files are hierarical and MetaModel tables are tabular, you need to do some mapping. MetaModel provides a mapping model that is XPath based, with a few slight modifications.

Assume we have the following XML document:

<?xml version="1.0" encoding="UTF-8"?>
<root>
        <organization type="governmental">
                <name>Company A</name>
                <employees>
                        <employee>
                                <name>John Doe</name>
                                <gender>M</gender>
                        </employee>
                        <employee>
                                <name>Jane Doe</name>
                                <gender>F</gender>
                        </employee>
                </employees>
        </organization>

        <organization type="company">
                <name>Company B</name>
                <employees>
                        <employee>
                                <name>Peter</name>
                                <gender>M</gender>
                        </employee>
                        <employee>
                                <name>Bob</name>
                                <gender>M</gender>
                        </employee>
                </employees>
        </organization>
</root>

Now imagine that you want to have a table of employee names and gender information, and another table with company name and type information. We define our DataContext and those tables like this:

   1 XmlSaxTableDef employeeTableDef = new XmlSaxTableDef(
   2         "/root/organization/employees/employee",
   3         new String[] {
   4                 "/root/organization/employees/employee/name",
   5                 "/root/organization/employees/employee/gender"
   6         }
   7 );
   8 
   9 XmlSaxTableDef organizationTableDef = new XmlSaxTableDef(
  10         "/root/organization",
  11         new String[] {
  12                 "/root/organization/name",
  13                 "/root/organization@type"
  14         }
  15 );
  16 
  17 DataContext dc = new XmlSaxDataContext(
  18         new File("my_file.xml"), employeeTableDef, organizationTableDef);

As you see, we simply provide some XPath expressions to 1) define the record scope and 2) define paths of individual values (or rather - the column definitions). If you query those tables, you will get datasets like these:

Table: /employee

row_id

/name

/gender

0

John Doe

M

1

Jane Doe

F

2

Peter

M

3

Bob

M

Table: /organization

row_id

/name

@type

0

Company A

governmental

1

Company B

company

This is nice, but you might be thinking: How can I then join these tables? There doesn't seem to be any cross-reference value that we can join or perform lookups by.

To solve this issue, MetaModel provides a modification for XPath, the index(...) function. Say we want to add the organization's id to the employee table (as a foreign key). To archieve that, we will need this modified employee table definition (notice the third value XPath expression):

   1 XmlSaxTableDef employeeTableDef = new XmlSaxTableDef(
   2         "/root/organization/employees/employee",
   3         new String[] {
   4                 "/root/organization/employees/employee/name",
   5                 "/root/organization/employees/employee/gender",
   6                 "index(/root/organization)"
   7         }
   8 );

Now if you query the employees table, this will be your result:

row_id

/name

/gender

index(/root/organization)

0

John Doe

M

0

1

Jane Doe

F

0

2

Peter

M

1

3

Bob

M

1

Moving on, you will be able to define both joins and lookups using this foreign key. For example:

   1 Column fk = employeeTable.getColumnByName("index(/root/organization)");
   2 Column empName = employeeTable.getColumnByName("/name");
   3 Column orgId = organizationTable.getColumnByName("row_id");
   4 Column orgName = organizationTable.getColumnByName("/name");
   5 
   6 Query q = dc.query().from(employeeTable)
   7         .innerJoin(organizationTable).on(fk, orgId)
   8         .select(empName).as("employee")
   9         .select(orgName).as("company").toQuery();
  10 DataSet ds = dc.executeQuery(q);

The contents of this queried dataset will now be:

employee

company

John Doe

Company A

Jane Doe

Company A

Peter

Company B

Bob

Company B


CategoryExamples

examples/XmlTableMapping (last edited 2013-08-01 12:12:59 by KasperSorensen)