使用oracle过程解析xml字符串

时间:2014-05-10 06:42:59

标签: xml oracle xml-parsing xmltype

我收到一个我需要在oracle过程中接受的XML字符串并解析

我有一个oracle过程可以解析XML文件,但不能解析字符串 我不知道如何修改现有的proc来解析字符串。请说明脚本是否准确以及如何修改

我有一个XML

 <TWObject className="TWObject">
  <array size="240">
    <item>
      <variable type="QuestionDetail">
        <questionId type="String"><![CDATA[30]]></questionId>
        <questionType type="questionType"><![CDATA[COUNTRY]]></questionType>
        <country type="String"><![CDATA[GB]]></country>
        <questionText type="String"><![CDATA[Please indicate if the following "Type of Market Research" applies to your Project : <br><br>Detail Follow-up Study OR Message Recall Study fielded from a Lilly Call/Target List]]></questionText>
        <optionType type="String"><![CDATA[RadioButton]]></optionType>
        <answerOptions type="String[]">
          <item><![CDATA[Yes]]></item>
          <item><![CDATA[No]]></item>
        </answerOptions>
        <ruleId type="String"><![CDATA[CRP_GB001]]></ruleId>
        <parentQuestionId type="String"></parentQuestionId>
        <parentQuestionResp type="String"></parentQuestionResp>
      </variable>
    </item>
 </array>
</TWOject>

我有一个可以将XML文件解析为

的oracle过程
Create or replace procedure parse_xml_data is
 l_bfile   BFILE;
 l_clob    CLOB;
 l_parser  dbms_xmlparser.Parser;
 l_doc     dbms_xmldom.DOMDocument;
 l_nl      dbms_xmldom.DOMNodeList;
 l_n       dbms_xmldom.DOMNode;
 l_file      dbms_xmldom.DOMNodeList;
 l_filen       dbms_xmldom.DOMNode;
 lv_value VARCHAR2(1000);
 l_ch      dbms_xmldom.DOMNode;

 l_partname varchar2(100);
 l_filename varchar2(1000);
 l_temp    VARCHAR2(1000);
 TYPE tab_type IS TABLE OF tab_data_parts%ROWTYPE;
 t_tab  tab_type := tab_type();
BEGIN
 l_bfile := BFileName('DIR1', 'Parts.xml');
 dbms_lob.createtemporary(l_clob, cache=>FALSE);
 dbms_lob.open(l_bfile, dbms_lob.lob_readonly);
 dbms_lob.loadFromFile(dest_lob => l_clob,    src_lob  => l_bfile,    amount   =>  dbms_lob.getLength(l_bfile));
 dbms_lob.close(l_bfile); 
 dbms_session.set_nls('NLS_DATE_FORMAT','''DD-MON-YYYY''');

 l_parser := dbms_xmlparser.newParser;

 dbms_xmlparser.parseClob(l_parser, l_clob);
 l_doc := dbms_xmlparser.getDocument(l_parser);
 dbms_lob.freetemporary(l_clob);
 dbms_xmlparser.freeParser(l_parser);

 l_nl := dbms_xslprocessor.selectNodes(dbms_xmldom.makeNode(l_doc),'/TWObject/array/item');

 FOR cur_emp IN 0 .. dbms_xmldom.getLength(l_nl) - 1 LOOP
 l_n := dbms_xmldom.item(l_nl, cur_emp);
 t_tab.extend;
 dbms_xslprocessor.valueOf(l_n,'variable/text()',t_tab(t_tab.last).variable);
 dbms_xslprocessor.valueOf(l_n,'questionId/text()',t_tab(t_tab.last).questionId);
 dbms_xslprocessor.valueOf(l_n,'questionType/text()',t_tab(t_tab.last).questionType);
 dbms_xslprocessor.valueOf(l_n,'country/text()',t_tab(t_tab.last).country);
 dbms_xslprocessor.valueOf(l_n,'questionText/text()',t_tab(t_tab.last).questionText);
 dbms_xslprocessor.valueOf(l_n,'optionType/text()',t_tab(t_tab.last).optionType);
 //selecting the answerOptions
 l_file := dbms_xslprocessor.selectNodes(l_n,'answerOptions/item');
 FOR cur_ch IN 0 .. dbms_xmldom.getLength(l_file) - 1 LOOP
 l_ch := dbms_xmldom.item(l_file, cur_ch);
 lv_value := dbms_xmldom.getnodevalue(dbms_xmldom.getfirstchild(l_ch));
 if t_tab(t_tab.last).item is null then t_tab(t_tab.last).item := l_partname; end if;
 t_tab(t_tab.last).item := lv_value;
 t_tab.extend;
 END LOOP;
 END LOOP;
 t_tab.delete(t_tab.last);
 FOR cur_emp IN t_tab.first .. t_tab.last LOOP
 if t_tab(cur_emp).variable is not null and  t_tab(cur_emp).item is not null then
 INSERT INTO tab_data_parts
 VALUES
 (t_tab(cur_emp).variable,t_tab(cur_emp).questionId,t_tab(cur_emp).questionType,t_tab(cur_emp).country,t_tab(cur_emp).questionText,t_tab(cur_emp).optionType, t_tab(cur_emp).item);
 end if;

 END LOOP;
 COMMIT;    
 dbms_xmldom.freeDocument(l_doc);
 EXCEPTION
 WHEN OTHERS THEN
 dbms_lob.freetemporary(l_clob);
 dbms_xmlparser.freeParser(l_parser);
 dbms_xmldom.freeDocument(l_doc);
 END;

1 个答案:

答案 0 :(得分:0)

如果字符串小于32k,您可以直接将其分配给l_clob变量,其余部分也会相同:

...
BEGIN
 l_clob := '<TWObject className="TWObject">
  <array size="240">
   ...
 </array>
</TWOject>';

 dbms_session.set_nls('NLS_DATE_FORMAT','''DD-MON-YYYY''');
 l_parser := dbms_xmlparser.newParser;
 dbms_xmlparser.parseClob(l_parser, l_clob);
...

或者更灵活地,在您的过程中添加一个CLOB参数,并将您的字符串分配给调用者中的CLOB:

Create or replace procedure parse_xml_data (p_clob in clob) is
 l_parser  dbms_xmlparser.Parser;
 l_doc     dbms_xmldom.DOMDocument;
 ...
BEGIN
 dbms_session.set_nls('NLS_DATE_FORMAT','''DD-MON-YYYY''');
 l_parser := dbms_xmlparser.newParser;
 dbms_xmlparser.parseClob(l_parser, p_clob);
 l_doc := dbms_xmlparser.getDocument(l_parser);
 dbms_xmlparser.freeParser(l_parser);

 ...

 dbms_xmldom.freeDocument(l_doc);
EXCEPTION
 WHEN OTHERS THEN
 dbms_xmlparser.freeParser(l_parser);
 dbms_xmldom.freeDocument(l_doc);
END;
/

并称之为:

DECLARE
 l_clob clob;
BEGIN
 l_clob := '<TWObject className="TWObject">
  <array size="240">
   ...
 </array>
</TWOject>';

 parse_xml_data(l_clob);
END;
/

如果字符串超过32k,那么您需要通过以块的形式附加到CLOB来构建CLOB;但在这种情况下,无论如何都可以从文件中加载。

你也可以让你当前的程序成为这个程序的包装 - 让它从文件加载CLOB,然后将它传递给新函数,这样你就不会复制解析逻辑。