1 |
14
|
jones
|
When element types represent hierarchy that exists in the XML document
|
2 |
|
|
but not in the database, they can be eliminated by "passing-through"
|
3 |
|
|
the unwanted elements -- that is, by treating their properties as if
|
4 |
|
|
they were properties of their parent. For example, suppose a Customer
|
5 |
|
|
element type has the following structure:
|
6 |
|
|
|
7 |
|
|
<Customer>
|
8 |
|
|
<Name>ABC Incorporated</Name>
|
9 |
|
|
<Address>
|
10 |
|
|
<Street>123 Main St.</Street>
|
11 |
|
|
<City>Chicago</City>
|
12 |
|
|
<State>IL</State>
|
13 |
|
|
<PostCode>60609</PostCode>
|
14 |
|
|
<Country>USA</Country>
|
15 |
|
|
</Address>
|
16 |
|
|
</Customer>
|
17 |
|
|
|
18 |
|
|
Under the standard tree-of-objects view used by XML-DBMS, Address
|
19 |
|
|
requires its own table. But what if the street, city, state, etc.
|
20 |
|
|
existed as columns in the Customer table? It is relatively easy to
|
21 |
|
|
eliminate the Address element and treat its children as properties
|
22 |
|
|
of the Customer element. The problem with this is that there is no
|
23 |
|
|
general solution for reconstructing passed-through elements when
|
24 |
|
|
retrieving data from the database. In the case above, we know that
|
25 |
|
|
there is a single Address element and that Street, City, etc. are
|
26 |
|
|
its children. Now imagine the case in which an element A can have
|
27 |
|
|
multiple children B, each of which can have multiple children C:
|
28 |
|
|
|
29 |
|
|
<A>
|
30 |
|
|
<B>
|
31 |
|
|
<C>...</C>
|
32 |
|
|
<C>...</C>
|
33 |
|
|
</B>
|
34 |
|
|
<B>
|
35 |
|
|
<C>...</C>
|
36 |
|
|
<C>...</C>
|
37 |
|
|
</B>
|
38 |
|
|
</A>
|
39 |
|
|
|
40 |
|
|
If we pass through the element B, we store four C's in the database
|
41 |
|
|
as properties of A. However, when retrieving the C's from the database,
|
42 |
|
|
we have no way of knowing whether these all came from a single B, they
|
43 |
|
|
can from the two B's shown above, or they came from four different B's.
|
44 |
|
|
|
45 |
|
|
In the simple case -- a passed-through element occurs exactly once in
|
46 |
|
|
its parent -- the following mapping language constructions can be used
|
47 |
|
|
to pass-through an element type:
|
48 |
|
|
|
49 |
|
|
<!ELEMENT ClassMap (ElementType,
|
50 |
|
|
(ToRootTable | ToClassTable),
|
51 |
|
|
PropertyMap*, RelatedClass*, PassThrough*)>
|
52 |
|
|
|
53 |
|
|
<!ELEMENT PassThrough (ElementType,
|
54 |
|
|
PropertyMap*, RelatedClass*, PassThrough*,
|
55 |
|
|
OrderColumn?)>
|
56 |
|
|
|
57 |
|
|
Note that a PassThrough element looks almost the same as a ClassMap.
|
58 |
|
|
This is not surprising, as the passed-through element is simply an
|
59 |
|
|
element type-as-class that does not have its own table. For example,
|
60 |
|
|
the following declares that the Address element type is to be passed
|
61 |
|
|
through. Like element types-as-properties, passed-through element
|
62 |
|
|
types are mapped on a per-parent basis, so this map is nested inside
|
63 |
|
|
the class map for Customer.
|
64 |
|
|
|
65 |
|
|
<PassThrough>
|
66 |
|
|
<ElementType Name="Address"/>
|
67 |
|
|
<PropertyMap>
|
68 |
|
|
<ElementType Name="Street"/>
|
69 |
|
|
<ToColumn>
|
70 |
|
|
<Column Name="Street"/>
|
71 |
|
|
</ToColumn>
|
72 |
|
|
</PropertyMap>
|
73 |
|
|
...other property maps...
|
74 |
|
|
...related class maps...
|
75 |
|
|
...pass-through maps...
|
76 |
|
|
</PassThrough>
|
77 |
|
|
|
78 |
|
|
The first ElementType element gives the name of the passed through
|
79 |
|
|
element type. Because passed-through element types are viewed as
|
80 |
|
|
classes, the PassThrough element must map the properties, related
|
81 |
|
|
classes, and passed-through child classes of the passed-through
|
82 |
|
|
class, just like a class map does. Shown above is a property map
|
83 |
|
|
that maps the Street element type to the Street column of the
|
84 |
|
|
parent table (Customers).
|
85 |
|
|
|
86 |
|
|
There are a number of comments in the code to show where/how
|
87 |
|
|
pass-through can be implemented. When transferring data to the
|
88 |
|
|
database, the function to get a child element needs to check if
|
89 |
|
|
the next child is pass-through. If so, the children of that element
|
90 |
|
|
are processed immediately. That is, the grandchildren of the element
|
91 |
|
|
being processed are treated as if they were children. When
|
92 |
|
|
transferring data from the database, properties need to be checked
|
93 |
|
|
to see if they have a pass-through parent; if so, the parent needs
|
94 |
|
|
to be reconstructed before the children are added. Note that, in the
|
95 |
|
|
case of children of passed-through elements, order refers to the
|
96 |
|
|
order in the passed-through element, not the grandparent.
|