Be Careful When Using xmlDom.getElementsByTagName

If you are working with PL/SQL XML DOM API, searching for elements using xmldom.getElementsByTagName may dramatically affect the performance of your code, especially if you are dealing with big XML Documents. Instead of searching for the same element over and over again, you should cache the node returned by xmldom.getElementsByTagName API and use the cached reference in subsequent DOM operations.

In the code below, new elements are added to an XML Document. We get the parent node with xmldom.getElementsByTagName API. In the first example, we get the parent node each time when a new node is added. The code executes in 0.27 seconds. In the second example, we find the parent node only once and reuse it. The same operation now takes only 0.05 seconds.

package test_xml
exec test_xml.initxml;
/

select test_xml.getxmltype from dual
/

-- add new action elements (slow way)
declare
  v_doc_xml xmldom.domdocument;
  
  v_newActionElement_xml xmldom.domelement;
  v_newActionNode_xml    xmldom.domnode;
  
  v_newActionCount_nr number := 1000;
begin
  v_doc_xml := test_xml.getxml;
  
  for i in 1..v_newActionCount_nr loop
    v_newActionElement_xml := xmldom.createelement(v_doc_xml, 'action');
    xmldom.setAttribute(v_newActionElement_xml, 'atrib1', 'a');
    -- find actions node using xmldom.getElementsByTagName
    -- it is executed 1000 times
    v_newActionNode_xml := xmldom.appendchild(xmlDom.item(xmldom.getelementsbytagname(v_doc_xml, 'actions'),0),
                                              xmldom.makeNode(v_newActionElement_xml));
  end loop;
end;
/

-- add new action elements (fast way)
declare
  v_doc_xml xmldom.domdocument;
  v_actionsnode_xml xmldom.domnode;
  
  v_newActionElement_xml xmldom.domelement;
  v_newActionNode_xml    xmldom.domnode;
  
  v_newActionCount_nr number := 1000;  ---TODO bu degiskenin ismini degistir
begin
  v_doc_xml := test_xml.getxml;
  
  -- find actions node using xmldom.getElementsByTagName
  -- it is executed once only
  v_actionsnode_xml := xmlDom.item(xmldom.getelementsbytagname(v_doc_xml, 'actions'),0);
  for i in 1..v_newActionCount_nr loop
    v_newActionElement_xml := xmldom.createelement(v_doc_xml, 'action');
    xmldom.setAttribute(v_newActionElement_xml, 'atrib2', 'b');
    v_newActionNode_xml := xmldom.appendchild(v_actionsnode_xml, xmldom.makeNode(v_newActionElement_xml));
  end loop;
end;
/

select test_xml.getxmltype from dual
/

Uğur Koçak

Comments

Marco Gralike said…
xmldom is the old 9.2 package which is more or less a java parser based wrapper. Its better to use the more performant package dbms_xmldom although even this one is not a good idea if big xml documents have to dealt with.

Oracle advices (and supports/updates/maintains/focus is more on...) to use XQuery based functions/methods or xmlelement, xmlforest and such.
Marco Gralike said…
BTW those last methods mentioned are C based / Oracle kernel supported methods and out perform, if used properly of course in the context of XML handling, stuff like dbms_xmldom or xmldom.
Anonymous said…
Sorry for my bad english. Thank you so much for your good post. Your post helped me in my college assignment, If you can provide me more details please email me.

Popular posts from this blog

PostgreSQL for Oracle Developers and DBA's