[ruby-oci8-devel] About XML DB support in Ruby-OCI8
Liming Lian
liming.lian at oracle.com
Thu May 22 08:27:59 EDT 2008
Hi all,
Continue reporting my experiments on XMLDB support implementation.
>
> Maybe we can use the same approach as the Lazy XML loading. We don't
> retrieve the entire XML data when issue the cursor fetch operation,
> but instead maintain a client side object with an initialized XML
> context and retrieved xmlnode which is a pointer to XML data
> requested. Whenever users process the data of this xml doc such as
> retrieving child nodes, xpath querying and so on, we use corresponding
> XDK api to process data requested in database and retrieve the result
> to the client side. Or we can say, we add a ruby-oci8 class to wrap
> XDK api for processing xml data in database in Lazy XML loading mode.
> IMO, this may somehow increase the performance of XMLDB support in
> Ruby-OCI8.
I added an class OCI8::XDB::XMLnode which wraps following C structure:
typedef struct {
oci8_base_t base;
struct xmlctx *xctx; //XML Context
xmlnode *node; // Pointer to a single xml node
} oci8_xmlnode_t;
When fetching xmltype from database, we get an "xmldocnode" pointing to
the XML document. We create an instance of XMLNode to hold this
"xmldocnode" and the initialized "xmlctx". When we need to further
process the xml doc, for example to get the root element, we can
retrieve the "xmldocnode" from the object and use XDK api
"XmlDomGetDocElem" to retrieve root node. Then a new instance of XMLnode
presenting root element will be created to wrap the "xmlnode" returned
by "XmlDomGetDocElem". All the nodes in the xml doc can be accessed and
presented on the client side in the same way with different XDK api
calls. Since the XMLNode object holds the internal "xmlnode" pointer, we
can perform all the operations on that node by leveraging various XDK
apis. The benefit of this approach is that we don't need to go through
the whole tree of xml doc but only store the single "xmldocnode" at the
xmltype fetch stage. We can call it "lazy" loading, we load only the
nodes we demand.
The disadvantage of this implementation is also obvious. Since it
doesn't traverse the whole xml tree at xmltype fetch stage and a single
node in an xml document is hard to be identified, it is generally
difficult to maintain a structure such as hash table to store the nodes
we have visited. So every time we use XDK api such as
XmlDomGetFirstChild or XmlDomGetElemById to visit a node, we have to
create a new XMLNode instance to wrap the "xmlnode" returned, even this
node has been visited before.
Take a look at following example:
root
/ \
n1 n2
/ \ / \
n3 n4 n5 n6
root = doc.root
n3_1 = doc.get_elem_by_tag('n3')[0]
n3_2 = doc.get_elem_by_tag('n3')[0]
Here: "get_element_by_tag" returns elements with tag name "n3". "n3_1"
and "n3_2" are all instance of "XMLNode", but they have not the same
object_id.
Regards,
Liming
More information about the ruby-oci8-devel
mailing list