|
|
|
||||
|
Code Tips
Dynamic SQL |
Data Driven Processing: XML Metadata The traditional relational database approach for implementing data driven processing would typically store metadata in a set of relational tables. Limitations with maintainability, version control, and deployment make this an unattractive approach compared to the latest XML-centric approaches. How can this be done in PL/SQL? by Philip Lambert With Oracle’s rich support for XML in the database it is now very hard to not exploit its use in your database application designs. XML is now becoming the most popular format for holding configuration metadata for bespoke systems and even the native format for many desktop applications. This article describes how to develop a generic PL/SQL package to read the hierarchical structure of XML metadata and map it to a hierarchical structure of a PL/SQL nested table record type driven by its own XML mapping rules. It is directed at PL/SQL developers looking to use XML as a metadata format for their data driven applications. To download the metadata mapping package
click here. Data Driven Applications Traditional Approach Before looking at how XML can be read by a
PL/SQL application, let us take a look at how we may have
traditionally designed a data driven application. As an experienced
data modeller, over the years I have developed or come across many
enterprise level data models that have had a subset of entities to
control the behaviour of the application - the data driven “rules”
of the system.
XML Approach XML has become a very attractive means of
representing certain types of data, in particular small “envelopes”
of data such as message payloads, configuration metadata, transient
data in web applications, etc.
Design Considerations XML and PL/SQL At first glance it is easy to be over-whelmed
with the available XML functionality in PL/SQL. It helps if you can
understand the origins of the various capabilities and see what
supersedes what as there is quite a bit of “legacy” support. The
main split is between XML Developers Kit (XDK) introduced in Oracle
8i and XMLDB introduced in Oracle 9i R2. PL/SQL Control Flow Whichever method you op for to read the content
of the XMLTYPE, where it is being used to drive the flow of the
program as in the case of metadata, then in needs to be converted
into a more accessible format. The best way to simulate the
hierarchical structure of XML is using nested tables within PL/SQL
record types. In Oracle 9i there is no limitation to how many levels
of nesting you can descend, so your typical XML document should be
easily accommodated. Strong Typing The main issue with PL/SQL record types in a
compiled program is that they are strong typed, i.e. their
definition is predefined at compile time, which means that any
generic package developed to perform the mapping would have to be
compiled with the PL/SQL record type it is trying to populate. A
very useful way to overcome this is to use dynamic PL/SQL and
generate the PL/SQL on the fly to access the PL/SQL record type. Dynamic PL/SQL Having the EXECUTE IMMEDIATE command makes using dynamic PL/SQL very straight forward. Though this command does have its limitations where code cannot exceed the 32k bytes in size of code. The alternative is to use the more traditional, but also more resilient method of using the DBMS_SQL supplied package, which has no limit to the size of SQL you use. It is not as easy to use as EXECUTE IMMEDIATE, but it does the job. Solution Outlined Design So we have now discussed and overcome each potential limitation and now have a workable solution. So to summarise the overall design we have:
Working Solution My next step could be to explain how to code up a solution, but instead I have developed my own open source solution for you to use and examine. Feel free to download it and use it in your own solutions. Any feedback or proposed enhancements are very welcome. To download the metadata mapping package
click here. Demonstration Example Source XML Metadata Rather than show an authentic example and have to explain what the metadata is representing, I have put together a hypothetical example. It shows a simple hierarchical structure that descends five levels with content data in a mixture of elements and attributes. The elements have been given obvious names eg Level1, Level2, ... etc. <?xml version="1.0"?>
<level1 Id="1" Name="Name 1">
<description>Level 1 Demo</description>
<level2 Id="11" Name="Name 1.1">
<description>Level 2 Demo - 1.1</description>
<level3 Id="111" Name="Name 1.1.1">
<description>Level 3 Demo - 1.1.1</description>
<level4 Id="1111" Name="Name 1.1.1.1">
<description>Level 4 Demo - 1.1.1.1</description>
<level5 Id="11111" Name="Name 1.1.1.1.1">
<description>Level 5 Demo - 1.1.1.1.1</description>
</level5>
<level5 Id="11112" Name="Name 1.1.1.1.2">
<description>Level 5 Demo - 1.1.1.1.2</description>
</level5>
</level4>
</level3>
<level3 Id="112" Name="Name 1.1.2">
<description>Level 3 Demo - 1.1.2</description>
<level4 Id="1121" Name="Name 1.1.2.1">
<description>Level 4 Demo - 1.1.2.1</description>
<level5 Id="11211" Name="Name 1.1.2.1.1">
<description>Level 5 Demo - 1.1.2.1.1</description>
</level5>
<level5 Id="11212" Name="Name 1.1.2.1.2">
<description>Level 5 Demo - 1.1.2.1.2</description>
</level5>
</level4>
</level3>
</level2>
<level2 Id="12" Name="Name 1.2">
<description>Level 2 Demo - 1.2</description>
</level2>
</level1>
Target Record Type This XML data needs to be loaded into a PL/SQL record type that simulates the hierarchical structure of the XML metadata:
TYPE t_level5 IS RECORD
(
id VARCHAR2(10),
name VARCHAR2(100),
descr VARCHAR2(100)
);
TYPE t_level5_col IS TABLE OF t_level5;
TYPE t_level4 IS RECORD
(
id VARCHAR2(10),
name VARCHAR2(100),
descr VARCHAR2(100),
level5 t_level5_col
);
TYPE t_level4_col IS TABLE OF t_level4;
TYPE t_level3 IS RECORD
(
id VARCHAR2(10),
name VARCHAR2(100),
descr VARCHAR2(100),
level4 t_level4_col
);
TYPE t_level3_col IS TABLE OF t_level3;
TYPE t_level2 IS RECORD
(
id VARCHAR2(10),
name VARCHAR2(100),
descr VARCHAR2(100),
level3 t_level3_col
);
TYPE t_level2_col IS TABLE OF t_level2;
TYPE t_level1 IS RECORD
(
id VARCHAR2(10),
name VARCHAR2(100),
descr VARCHAR2(100),
level2 t_level2_col
);
TYPE t_level1_col IS TABLE OF t_level1;
TYPE t_param IS RECORD
(
level1 t_level1_col
);
The record types do not necessarily have to be PL/SQL record types, but can also be object types defined in the database. XML to Record Type Mappings To define a mapping between the source XML metadata and the target PL/SQL record type, we use some XML metadata:
<?xml version="1.0"?>
<Mappings Global="demo_metadata.g_param" DateFormat="YYYYMMDD">
<Record
Id="Level1"
ParentId=""
Source="Level1"
ParentSource=""
Target="level1"
Type="test_metadata2.t_level1_col">
<Mapping Type="String" Source="@Id" Target="id"/>
<Mapping Type="String" Source="@Name" Target="name"/>
<Mapping Type="String" Source="Description" Target="descr"/>
<Mapping Type="Boolean" Source="@IsValid"
Target="is_valid_ind"/>
<Mapping Type="Number" Source="@Version"
Target="version"/>
<Mapping Type="LargeString" Source="Comments"
Target="comments"/>
<Mapping Type="Date" Source="CreatedOn" Target="create_dt"/>
<Mapping Type="Date" Source="UpdatedOn" Target="update_dt"
DateFormat="YYYYMMDDHH24MISS"/>
</Record>
<Record
Id="Level2"
ParentId="Level1"
Source="Level2"
ParentSource="Level1"
Target="level2"
Type="test_metadata2.t_level2_col">
<Mapping Type="String" Source="@Id" Target="id"/>
<Mapping Type="String" Source="@Name" Target="name"/>
<Mapping Type="String" Source="Description" Target="descr"/>
</Record>
<Record
Id="Level3"
ParentId="Level2"
Source="Level3"
ParentSource="Level2"
Target="level3"
Type="test_metadata2.t_level3_col">
<Mapping Type="String" Source="@Id" Target="id"/>
<Mapping Type="String" Source="@Name" Target="name"/>
<Mapping Type="String" Source="Description" Target="descr"/>
</Record>
<Record
Id="Level4"
ParentId="Level3"
Source="Level4"
ParentSource="Level3"
Target="level4"
Type="test_metadata2.t_level4_col">
<Mapping Type="String" Source="@Id" Target="id"/>
<Mapping Type="String" Source="@Name" Target="name"/>
<Mapping Type="String" Source="Description" Target="descr"/>
</Record>
<Record
Id="Level5"
ParentId="Level4"
Source="Level5"
ParentSource="Level4"
Target="level5"
Type="test_metadata2.t_level5_col">
<Mapping Type="String" Source="@Id" Target="id"/>
<Mapping Type="String" Source="@Name" Target="name"/>
<Mapping Type="String" Source="Description" Target="descr"/>
</Record>
</Mappings>
The metadata has two levels of mapping: one at record level and one at column level. There are rules for defining the mappings:
Conclusion The solution described here gives a quick and easy method for mapping an XML document to a PL/SQL record type. The dbi_metadata package I have developed can be incorporated very easily into to your own package solutions giving you the power and flexibility to quickly utilise XML as a metadata medium. The dbi_metadata package has been released as an open source project. So feel free to use it and provide back whatever feedback you may have. To download the metadata mapping package
click here. |
|
|||
|
|
Send mail to webmaster@db-innovations.co.uk with questions or
comments about this web site. |
||||