2016-01-21 2 views
0

У меня возникли проблемы с пониманием других вопросов, которые я вижу, поскольку они немного разные.XML Oracle: Извлечение определенного атрибута из нескольких повторяющихся дочерних узлов

Я получаю XML как ответ от webservice vi UTL_HTTP. XML повторяет дочерние узлы, и я хочу извлечь только 1 конкретное значение.

XML-ответ:

<Customer> 
    <Loyalty> 
     <Client> 
      <Identifications> 
       <Identification> 
        <Form>Form1</Form> 
        <value>1234</value> 
       </Identification> 
       <Identification> 
        <Form>Form2</Form> 
        <value>4442</value> 
       </Identification> 
       <Identification> 
        <Form>Form3</Form> 
        <value>9995</value> 
       </Identification> 
      </Identifications> 
     </Client> 
    </Loyalty> 
</Customer> 

Мне нужно извлечь узел <value> только тогда, когда узел <Form> = "Форма Form3".

Итак, в моем коде, я получаю ответ от другой функции

v_ds_xml_response XMLTYPE; 
-- Here would lie the rest of the code (omitted) preparing the XML and next calling the function with it: 

V_DS_XML_RESPONSE := FUNCTION_CALL_WEBSERVICE(
     P_URL => V_DS_URL, --endpoint 
     P_DS_XML => V_DS_XML, --the request XML 
     P_ERROR => P_ERROR); 

При том, что я создал LOOP для хранения ценностей. Я пробовал использовать WHERE и даже создать тип (V_IDENTIFICATION ниже - тип), но он ничего не возвращал (null).

for r IN (
SELECT   
ExtractValue(Value(p),'/Customer/Loyalty/Client/Identifications/Identification/*[local-name()="Form"]/text()') as form, 
    ExtractValue(Value(p),'/Customer/Loyalty/Client/Identifications/Identification/*[local-name()="value"]/text()') as value 
    FROM TABLE(XMLSequence(Extract(V_DS_XML_RESPONSE,'//*[local-name()="Customer"]'))) p 

LOOP 
V_IDENTIFICATION.FORM := r.form; 
V_IDENTIFICATION.VALUE := r.value; 
END LOOP; 

SELECT 
     V_IDENTIFICATION.VALUE 
INTO 
     P_LOYALTY_VALUE 
FROM dual 
WHERE V_IDENTIFICATION.TIPO = 'Form3'; 

Примечание, P_LOYALTY_VALUE является параметр OUT от моего процедуры

ответ

0

Aaand мне удалось найти решение, которое довольно просто , только что добавили [текст() = "Форма Form3"] /.../»предицировать в Xpath, как в

SELECT   
ExtractValue(Value(p),'/Customer/Loyalty/Client/Identifications/Identification/*[local-name()="Form"][text()="Form3"]/text()') as form, 
ExtractValue(Value(p),'/Customer/Loyalty/Client/Identifications/Identification/Form[text()="Form3"]/.../*[local-name()="value"]/text()') as value 

экстракт также значения, которые просто отправляются непосредственно в параметр OUT OUT:

P_FORM := r.form; 
P_LOYALTY_VALUE := r.value; 
2

с этим SQL вы должны получить желаемое значение:

with data as 
(select '<Customer> 
    <Loyalty> 
    <Client> 
     <Identifications> 
      <Identification> 
       <Form>Form1</Form> 
       <value>1234</value> 
      </Identification> 
      <Identification> 
       <Form>Form2</Form> 
       <value>4442</value> 
      </Identification> 
      <Identification> 
       <Form>Form3</Form> 
       <value>9995</value> 
      </Identification> 
     </Identifications> 
    </Client> 
</Loyalty> 
</Customer>' as xmlval 
    from dual b) 
(SELECT t.val 
    FROM data d, 
     xmltable('/Customer/Loyalty/Client/Identifications/Identification' 
        PASSING xmltype(d.xmlval) COLUMNS 
        form VARCHAR2(254) PATH './Form', 
        val VARCHAR2(254) PATH './value') t 
    where t.form = 'Form3'); 
1

Когда вы не знаете точный путь.

select * from 
xmltable('for $i in $doc//*/Form 
where $i = "Form2" 
return $i/../value' 
passing 
xmltype('<Customer> 
    <Loyalty> 
     <Client> 
      <Identifications> 
       <Identification> 
        <Form>Form1</Form> 
        <value>1234</value> 
       </Identification> 
       <Identification> 
        <Form>Form2</Form> 
        <value>4442</value> 
       </Identification> 
       <Identification> 
        <Form>Form3</Form> 
        <value>9995</value> 
       </Identification> 
      </Identifications> 
     </Client> 
    </Loyalty> 
</Customer>') as "doc") 
0

Чтобы извлечь значение, которое вы ищете вы можете использовать следующее выражение XPATH:

/Customer/Loyalty/Client/Identifications/Identification/Form[text()='Form3']/../value 

Test it here

Затем вы можете использовать XMLTABLE функцию, чтобы получить результат

SELECT my_value 
FROM xmltable(
     '/Customer/Loyalty/Client/Identifications/Identification/Form[text()=''Form3'']/../value' 
     PASSING xmltype(
'<Customer> 
    <Loyalty> 
     <Client> 
     <Identifications> 
      <Identification> 
       <Form>Form1</Form> 
       <value>1234</value> 
      </Identification> 
      <Identification> 
       <Form>Form2</Form> 
       <value>4442</value> 
      </Identification> 
      <Identification> 
       <Form>Form3</Form> 
       <value>9995</value> 
      </Identification> 
     </Identifications> 
     </Client> 
    </Loyalty> 
</Customer>') 
     COLUMNS 
      my_value VARCHAR2(4000) path '/value' 
    ) 
Смежные вопросы