从XMLTYPE读取元素

时间:2017-05-24 11:53:51

标签: xml soap oracle12c

希望有人可以提供帮助。

在PLSQL中,我进行soap调用,并从SOAP接收XML结果。 我需要检索元素值。

这在这个XML上运行良好:

<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
   <S:Body>
      <ns2:executeObjectResponse xmlns:ns2="http://www.uc4.com/uc4/">
         <runID>1120864</runID>
      </ns2:executeObjectResponse>
   </S:Body>
</S:Envelope>

使用此代码:

declare
       v_doc               DBMS_XMLDOM.DOMDocument;
       v_Value             VARCHAR2 (2000);
       v_node              DBMS_XMLDOM.DOMNode;
       v_nodelist          DBMS_XMLDOM.DOMNodelist;
begin
      ...  XML result from soap call catched in CLOB => l_result

v_doc := DBMS_XMLDOM.newdomdocument (l_result);
v_nodelist := DBMS_XMLDOM.getelementsbytagname (v_doc, 'runID');
v_node := DBMS_XMLDOM.getfirstchild (DBMS_XMLDOM.item (v_nodelist, 0));
v_value := DBMS_XMLDOM.getnodevalue (v_node);
DBMS_OUTPUT.put_line ('value a: ' || v_Value);

value a: 1120864

但我确实遇到以下XML问题。 我需要检索此标记的值:

<name>&amp;RESULT#</name>

我尝试了几件事,但却找不到适当的代码。

SOAP的结果我在CLOB(l_result)中捕获。

<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
   <S:Body>
      <ns2:getTaskDetailsResponse xmlns:ns2="http://www.uc4.com/uc4/">
         <groups>
            <name>General</name>
            <label>SCRI.ADP.SOAP.TEST (1120864)</label>
            <items>
               <name>Object name</name>
               <value>SCRI.ADP.SOAP.TEST</value>
            </items>
            <items>
               <name>Queue</name>
               <value>CLIENT_QUEUE</value>
            </items>
            <items>
               <name>Version</name>
               <value>6</value>
            </items>
            <items>
               <name>RunID</name>
               <value>1120864</value>
            </items>
            <items>
               <name>Activator</name>
               <value>1115216</value>
            </items>
            <items>
               <name>User</name>
               <value>ADP_SOAP/ADP</value>
            </items>
            <items>
               <name>Activation</name>
               <value>2017-05-24T13:38:44</value>
            </items>
            <items>
               <name>Start</name>
               <value>2017-05-24T13:38:45</value>
            </items>
            <items>
               <name>End</name>
               <value>2017-05-24T13:38:45</value>
            </items>
            <items>
               <name>Runtime</name>
               <value>0:00:00</value>
            </items>
            <items>
               <name>Status</name>
               <value>ENDED_OK - ended normally</value>
            </items>
            <items>
               <name>Return code</name>
               <value>0</value>
            </items>
            <items>
               <name>Event ID</name>
               <value>1120864</value>
            </items>
            <items>
               <name>Enable Rollback</name>
               <value>No</value>
            </items>
         </groups>
         <groups>
            <name>Object variables</name>
            <label>SCRI.ADP.SOAP.TEST (1120864)</label>
            <items>
               <name>&amp;EXT_HOSTNAME#</name>
               <value>sz4183</value>
            </items>
            <items>
               <name>&amp;EXT_SOAP_ID#</name>
               <value>sz4183</value>
            </items>
            <items>
               <name>&amp;EXT_SOAP_WF#</name>
               <value>JOBP.ADP.SOAP_TEST1</value>
            </items>
            <items>
               <name>&amp;RESULT#</name>
               <value>/dev;/u01;/etc/mnttab;/etc/dfs/sharetab;/dev/fd;/export;/rpool;/mnt/ora_dba</value>
            </items>
         </groups>
      </ns2:getTaskDetailsResponse>
   </S:Body>
</S:Envelope>

我玩弄了这个,但没有成功:

    declare
       v_doc               DBMS_XMLDOM.DOMDocument;
       v_Value             VARCHAR2 (2000);
       v_node              DBMS_XMLDOM.DOMNode;
       v_nodelist          DBMS_XMLDOM.DOMNodelist;
    begin
      ...  XML result from soap call catched in CLOB => l_result
      v_doc := DBMS_XMLDOM.newdomdocument (l_result);
      v_nodelist := DBMS_XMLDOM.getelementsbytagname (v_doc, '&amp;RESULT#');
      v_node := DBMS_XMLDOM.getfirstchild (DBMS_XMLDOM.item (v_nodelist, 0));
      v_value := DBMS_XMLDOM.getnodevalue (v_node);
       DBMS_OUTPUT.put_line ('value: ' || v_Value);
   end;

欢迎所有的消遣。

欢呼声 维姆

2 个答案:

答案 0 :(得分:0)

我发现代码有效。

dbms_xmldom.freeDocument(v_doc);
      v_doc := DBMS_XMLDOM.newdomdocument (l_result);
      v_nodelist := DBMS_XMLDOM.getelementsbytagname (v_doc, 'name');
      v_node := DBMS_XMLDOM.getfirstchild (DBMS_XMLDOM.item (v_nodelist, 19));
      v_value := DBMS_XMLDOM.getnodevalue (v_node);
       DBMS_OUTPUT.put_line ('name: ' || v_Value);
       v_nodelist := DBMS_XMLDOM.getelementsbytagname (v_doc, 'value');
      v_node := DBMS_XMLDOM.getfirstchild (DBMS_XMLDOM.item (v_nodelist, 17));
      v_value := DBMS_XMLDOM.getnodevalue (v_node);
       DBMS_OUTPUT.put_line ('value : ' || v_Value);

结果是:

name: &RESULT#
value : /dev;/u01;/etc/mnttab;/etc/dfs/sharetab;/dev/fd;/export;/rpool;/mnt/ora_dba

我还想找到的是如何搜索元素&amp; RESULT#以及属于该元素的值。 现在我确实计算了元素(名称为19,值为17),只是为了检查代码。

欢呼Wim

答案 1 :(得分:0)

我根本不会尝试遍历DOM,但我想你可以迭代items个节点,测试每个节点中的name文本,当你找到那个节点时停止对此感兴趣 - 然后使用items节点的value文本。

虽然使用内置的XML处理更容易:

declare
    l_result clob := '... your SOAP response ...';
    v_Value VARCHAR2 (2000);
begin
    select xmlquery('//items/name[text()=''&amp;RESULT#'']/../value/text()'
      passing xmltype(l_result)
      returning content).getstringval()
    into v_Value
    from dual;
    DBMS_OUTPUT.put_line ('value: ' || v_Value);
end;
/

value: /dev;/u01;/etc/mnttab;/etc/dfs/sharetab;/dev/fd;/export;/rpool;/mnt/ora_dba

PL/SQL procedure successfully completed.

你可以read more about XMLQuery in the documentation。在这种情况下我使用的XPath:

//items/name[text()=''&amp;RESULT#'']/../value/text()

查找items/name节点,其文本值是您想要的字符串(在转义的单引号中);然后使用items找到它的父(..)节点,然后在 values节点下找到items节点。并获得其文本值。

(可能最好提供items节点的完整路径,并包含所有命名空间信息,但您可以添加它;使用//items忽略上面的结构。)< / p>

你也可以用你的第一个例子做同样的事情,顺便说一下:

...
begin
    select xmlquery('//runID/text()'
      passing xmltype(l_result)
      returning content).getstringval()
    into v_Value
    from dual;
    DBMS_OUTPUT.put_line ('value a: ' || v_Value);
end;
/

value a: 1120864

PL/SQL procedure successfully completed.