从 XMLTYPE 读取元素

Read element from XMLTYPE

希望有人能提供帮助。

在 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>

我尝试了几件事,但就是找不到合适的代码。

我在 CLOB 中捕获的 SOAP 结果 (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;

欢迎大家提出建议。

干杯 维姆

我发现代码有效。

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

我仍在努力寻找的是如何搜索元素 &RESULT# 以及属于该元素的值。 现在我确实计算了元素(19 个名称和 17 个值),只是为了检查代码。

维姆干杯

我根本不会尝试遍历 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) 节点,然后在 that items 节点下找到 values 节点。并获取其文本值。

(最好给出 items 节点的完整路径,并包含所有名称空间信息,但您可以将其添加进去;使用 //items 会忽略上面的结构) .

顺便说一下,您也可以对第一个示例执行相同的操作:

...
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.