как получить DOMTEXT с DBMS_XMLDOM на PL/SQL

я пытаюсь получить текстовое значение из моего xml с помощью DBMS_XMLDOM. Например в:

<Vehicle>
    <Cars name ="Tesla">Model-S</Cars>
</Vehicle>

Я хочу получить "Model-S" как Varchar2. Кажется, я не могу найти какую-либо функцию вроде getTextNode/getTextValue. Как правильно получить значение из DomText?

До сих пор я получил:

set serveroutput on size 1000000; 
DECLARE     
  xmlDomElement         xmldom.DOMElement; 
  xmlDomDokument        xmldom.DOMDocument; 
  v_xml    clob; 
BEGIN           
  v_xml := 
   '<Vehicle> 
      <Car> 
        <Tesla>Model-X</Tesla> 
      </Car> 
    </Vehicle>'; 

  xmlDomDokument := dbms_xmldom.newDomDocument(v_xml) ; 
  xmlDomElement :=  dbms_xmldom.getdocumentelement(xmlDomDokument); 
  xmlDomNode :=  dbms_xmldom.makeNode(xmlDomElement);   
  dbms_output.put_line( 'Print node Vehicle : ' || dbms_xmldom.getnodename(xmlDomNode)); 

  -- Question: is there something like "dbms_xmldom.getTextValue"?   

end; 

Заранее спасибо.

С уважением, Иван


person Ivancodescratch    schedule 16.02.2016    source источник


Ответы (2)


Для получения значения текстового узла вы можете использовать XMLDOM.GETNODEVALUE. Но чтобы использовать это, вам нужно получить первый дочерний элемент узла xmldom.getFirstChild(n). Используйте блок ниже, чтобы получить результат

DECLARE     
  xmlDomElement         xmldom.DOMElement; 
  xmlDomDokument        xmldom.DOMDocument; 
  xmlDomNode            xmldom.DOMNode; 
  lv_domnodelist1       dbms_xmldom.DomNodeList;
  lv_domnodelist2       dbms_xmldom.DomNodeList;
  v_xml    clob; 
BEGIN           
  v_xml := 
   '<Vehicle> 
      <Car> 
        <Tesla>Model-X</Tesla> 
      </Car> 
    </Vehicle>'; 

  xmlDomDokument := dbms_xmldom.newDomDocument(v_xml) ; 
  xmlDomElement :=  dbms_xmldom.getdocumentelement(xmlDomDokument); 
  xmlDomNode :=  dbms_xmldom.makeNode(xmlDomElement);   
  lv_domnodelist1 := DBMS_XMLDOM.GETCHILDNODES(xmlDomNode);

  For i in 0..dbms_xmldom.getLength( lv_domnodelist1 ) - 1 loop
    xmlDomNode := DBMS_XMLDOM.ITEM(lv_domnodelist1,i);
    lv_domnodelist2 := DBMS_XMLDOM.GETCHILDNODES(xmlDomNode);
    FOR J in 0..dbms_xmldom.getLength( lv_domnodelist2 ) - 1 loop
      xmlDomNode := DBMS_XMLDOM.ITEM(lv_domnodelist2,J);
      dbms_output.put_line( 'Print node Name : ' ||  dbms_xmldom.getnodename(xmlDomNode)); 
      xmlDomNode := DBMS_XMLDOM.getFirstChild(xmlDomNode);
      dbms_output.put_line( 'Print node Value : ' || dbms_xmldom.getnodevalue(xmlDomNode)); 
    end loop;
  end loop;
end;
person Dinesh V    schedule 16.02.2016

Ходить по DOM здесь кажется излишним; вы можете использовать XQuery:

select XMLQuery('/Vehicle/Car/Tesla/text()'
  passing XMLType('<Vehicle> 
      <Car> 
        <Tesla>Model-X</Tesla> 
      </Car> 
    </Vehicle>')
  returning content) as model
from dual;

MODEL             
------------------
Model-X

Если вам нужна дополнительная информация, вы можете получить больше полей; и с несколькими узлами вместо этого вы можете использовать XMLTable:

select *
from XMLTable('/Vehicle/Car'
  passing XMLType('<Vehicle> 
      <Car> 
        <Tesla>Model-X</Tesla> 
      </Car> 
    </Vehicle>')
  columns vehicle_type varchar2(10) path 'local-name(.)',
    vehicle_make varchar2(10) path 'local-name(./*)',
    vehicle_model varchar2(10) path '*'
);

VEHICLE_TY VEHICLE_MA VEHICLE_MO
---------- ---------- ----------
Car        Tesla      Model-X   
person Alex Poole    schedule 16.02.2016
comment
Использование xmldom очень полезно для анализа XML-документов, имена элементов или структура которых неизвестны. Написание кода xmldom может быть утомительным, но однажды созданный он будет действительно полезен для разбора всего документа. - person Dinesh V; 16.02.2016
comment
@DineshV - здесь все еще кажется излишним * 8-) Пример, конечно, может быть сильно упрощен. - person Alex Poole; 16.02.2016
comment
@AlexPoole Спасибо, что показали это. Это другой подход. Но и определенно правильный ответ. - person Ivancodescratch; 17.02.2016