Проверить, существует ли значение (узел существует?) в переменной xmltype (не в таблице) в PL / SQL

#xml #oracle #soap #plsql

#xml #Oracle #soap #plsql

Вопрос:

У меня есть результирующая переменная из вызова SOAP в PL / SQL, и возвращаемая переменная out type — это xmltype (не писал пакет или процедуру, не меняйте его). Тип переменной, которую я получаю обратно, — xmltype, и я хочу проверить, был ли результат или нет. У меня возникли проблемы с пониманием документации по XML в PL / SQL.

Номер учетной записи всегда будет существовать, я проверяю, было ли возвращено местоположение или нет. Или возвращается более одного (что было бы ужасно, но я должен это проверить).

Результат выглядит так

 <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://www.w3.org/2005/08/addressing">
   <env:Header>
      <wsa:Action>http://xmlns.oracle.com/apps/cdm/foundation/parties/customerAccountService/applicationModule//CustomerAccountService/findCustomerAccountResponse</wsa:Action>
      <wsa:MessageID>urn:uuid:7dd64ecf-676f-4667-a761-dc7603e99929</wsa:MessageID>
   </env:Header>
   <env:Body>
      <ns0:findCustomerAccountResponse xmlns:ns0="http://xmlns.oracle.com/apps/cdm/foundation/parties/customerAccountService/applicationModule/types/">
         <ns0:result xsi:type="ns2:CustomerAccountResult" xmlns:ns2="http://xmlns.oracle.com/apps/cdm/foundation/parties/customerAccountService/" xmlns:ns1="http://xmlns.oracle.com/adf/svc/types/" xmlns:ns4="http://xmlns.oracle.com/apps/cdm/foundation/parties/partyService/" xmlns:tns="http://xmlns.oracle.com/adf/svc/errors/" xmlns:ns9="http://xmlns.oracle.com/apps/cdm/foundation/parties/flex/custAccount/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <ns1:Message>
               <tns:code>25089</tns:code>
               <tns:message>JBO-25089: Too many matching records found. Specify additional criteria to limit the number of records.</tns:message>
               <tns:severity>SEVERITY_WARNING</tns:severity>
            </ns1:Message>
            <ns2:Value>
               <ns2:AccountNumber>XXXXX</ns2:AccountNumber>
               <ns2:CustomerAccountSite xmlns:ns7="http://xmlns.oracle.com/apps/cdm/foundation/parties/flex/custAccountSite/"/>
               <ns2:CustomerAccountSite xmlns:ns7="http://xmlns.oracle.com/apps/cdm/foundation/parties/flex/custAccountSite/">
                  <ns2:CustomerAccountSiteUse xmlns:ns6="http://xmlns.oracle.com/apps/cdm/foundation/parties/flex/custAccountSiteUse/">
                     <ns2:Location>XXXXXXXX</ns2:Location>
                  </ns2:CustomerAccountSiteUse>
               </ns2:CustomerAccountSite>
               <ns2:CustomerAccountSite xmlns:ns7="http://xmlns.oracle.com/apps/cdm/foundation/parties/flex/custAccountSite/"/>
               <ns2:CustomerAccountSite xmlns:ns7="http://xmlns.oracle.com/apps/cdm/foundation/parties/flex/custAccountSite/"/>
            </ns2:Value>
         </ns0:result>
      </ns0:findCustomerAccountResponse>
   </env:Body>
</env:Envelope>
 

Я думаю, что-то вроде

 IF DBMS_LOB.INSTR(xml_response.getClobVal(), 'Location>XXXXXX<') > 0 THEN
     val_returned := TRUE;
END IF;
 

будет работать, но я думаю, что это, вероятно, плохой способ сделать это? Я пытался прочитать документы, но все они ссылаются на выбор из таблицы и тому подобное, А у меня нет таблицы. Могу ли я использовать XML-выражения для этих вещей без ссылки на таблицу? Должен ли я выбирать из dual или что-то в этом роде?

Ответ №1:

Да, XPath в Oracle не очень хорош, особенно если задействованы пространства имен. Я не силен в этом, но, возможно, это поможет вам начать в правильном направлении:

 DECLARE
  accountnumber VARCHAR2(100);
  location      VARCHAR2(100);
  x XMLType := XMLType('
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://www.w3.org/2005/08/addressing">
   <env:Header>
      <wsa:Action>http://xmlns.oracle.com/apps/cdm/foundation/parties/customerAccountService/applicationModule//CustomerAccountService/findCustomerAccountResponse</wsa:Action>
      <wsa:MessageID>urn:uuid:7dd64ecf-676f-4667-a761-dc7603e99929</wsa:MessageID>
   </env:Header>
   <env:Body>
      <ns0:findCustomerAccountResponse xmlns:ns0="http://xmlns.oracle.com/apps/cdm/foundation/parties/customerAccountService/applicationModule/types/">
         <ns0:result xsi:type="ns2:CustomerAccountResult" xmlns:ns2="http://xmlns.oracle.com/apps/cdm/foundation/parties/customerAccountService/" xmlns:ns1="http://xmlns.oracle.com/adf/svc/types/" xmlns:ns4="http://xmlns.oracle.com/apps/cdm/foundation/parties/partyService/" xmlns:tns="http://xmlns.oracle.com/adf/svc/errors/" xmlns:ns9="http://xmlns.oracle.com/apps/cdm/foundation/parties/flex/custAccount/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <ns1:Message>
               <tns:code>25089</tns:code>
               <tns:message>JBO-25089: Too many matching records found. Specify additional criteria to limit the number of records.</tns:message>
               <tns:severity>SEVERITY_WARNING</tns:severity>
            </ns1:Message>
            <ns2:Value>
               <ns2:AccountNumber>XXXXX</ns2:AccountNumber>
               <ns2:CustomerAccountSite xmlns:ns7="http://xmlns.oracle.com/apps/cdm/foundation/parties/flex/custAccountSite/"/>
               <ns2:CustomerAccountSite xmlns:ns7="http://xmlns.oracle.com/apps/cdm/foundation/parties/flex/custAccountSite/">
                  <ns2:CustomerAccountSiteUse xmlns:ns6="http://xmlns.oracle.com/apps/cdm/foundation/parties/flex/custAccountSiteUse/">
                     <ns2:Location>XXXXXXXX</ns2:Location>
                     <ns2:Location>YYYYYYYY</ns2:Location>
                  </ns2:CustomerAccountSiteUse>
               </ns2:CustomerAccountSite>
               <ns2:CustomerAccountSite xmlns:ns7="http://xmlns.oracle.com/apps/cdm/foundation/parties/flex/custAccountSite/"/>
               <ns2:CustomerAccountSite xmlns:ns7="http://xmlns.oracle.com/apps/cdm/foundation/parties/flex/custAccountSite/"/>
            </ns2:Value>
         </ns0:result>
      </ns0:findCustomerAccountResponse>
   </env:Body>
</env:Envelope>  
  ');
BEGIN
  SELECT EXTRACT(x, '//ns2:AccountNumber/text()', 'xmlns:ns2="http://xmlns.oracle.com/apps/cdm/foundation/parties/customerAccountService/"').getStringVal()
    INTO accountnumber FROM DUAL;
  dbms_output.put_line('accountnumber:'||accountnumber);
  
  SELECT EXTRACT(x, '//ns2:Location/text()', 'xmlns:ns2="http://xmlns.oracle.com/apps/cdm/foundation/parties/customerAccountService/"').getStringVal()
    INTO location FROM DUAL;
  dbms_output.put_line('locations:'||location);
  
  SELECT EXTRACT(x, '//ns2:Location[2]/text()', 'xmlns:ns2="http://xmlns.oracle.com/apps/cdm/foundation/parties/customerAccountService/"').getStringVal()
    INTO location FROM DUAL;
  dbms_output.put_line('location2:'||location);
  
  SELECT EXTRACT(x, '//ns2:Location[3]/text()', 'xmlns:ns2="http://xmlns.oracle.com/apps/cdm/foundation/parties/customerAccountService/"').getStringVal()
    INTO location FROM DUAL;
  dbms_output.put_line('location3:'||location);
END;
/
 

Это выведет

 accountnumber:XXXXX
locations:XXXXXXXXYYYYYYYY
location2:YYYYYYYY
location3:
 

Комментарии:

1. Это действительно продвигает то, что я пытался сделать, спасибо.

2. Рад слышать, для этого и предназначен этот сайт 🙂