Получить значение элемента xml в Oracle PL SQL
Кто-нибудь знает, как получить значения <ZIPCODE>
а также <CITY>
используя PL/SQL? Я следовал за учебником по сети, однако, он может получить имена элементов, но не их значения. Кто-нибудь из вас знает, в чем проблема? Я уже консультировался с Google (Интернет держится в секрете) по этому поводу, но не повезло:(
<Zipcodes>
<mappings Record="4">
<STATE_ABBREVIATION>CA</STATE_ABBREVIATION>
<ZIPCODE>94301</ZIPCODE>
<CITY>Palo Alto</CITY>
</mappings>
</Zipcodes>
вот пример кода:
-- prints elements in a document
PROCEDURE printElements(doc DBMS_XMLDOM.DOMDocument) IS
nl DBMS_XMLDOM.DOMNodeList;
n DBMS_XMLDOM.DOMNode;
len number;
BEGIN
-- get all elements
nl := DBMS_XMLDOM.getElementsByTagName(doc, '*');
len := DBMS_XMLDOM.getLength(nl);
-- loop through elements
FOR i IN 0 .. len - 1 LOOP
n := DBMS_XMLDOM.item(nl, i);
testr := DBMS_XMLDOM.getNodeName(n) || ' ' || DBMS_XMLDOM.getNodeValue(n);
DBMS_OUTPUT.PUT_LINE (testr);
END LOOP;
DBMS_OUTPUT.PUT_LINE ('');
END printElements;
2 ответа
Вам нужно изменить строку
testr := DBMS_XMLDOM.getNodeName(n) || ' ' || DBMS_XMLDOM.getNodeValue(n);
в
testr := DBMS_XMLDOM.getNodeName(n) || ' ' || DBMS_XMLDOM.getNodeValue(DBMS_XMLDOM.getFirstChild(n));
В XML DOM элементы не имеют никакого "значения", о котором можно говорить. Узлы элементов содержат текстовые узлы как дочерние элементы, и именно эти узлы содержат нужные значения.
РЕДАКТИРОВАТЬ (в ответ на комментарий Томалака): Мне не известны какие-либо функции в DBMS_XMLDOM для получения объединенного значения всех дочерних текстовых узлов элемента. Если это то, что вам нужно, то вам вполне может понадобиться что-то вроде следующей функции:
CREATE OR REPLACE FUNCTION f_get_text_content (
p_node DBMS_XMLDOM.DOMNode
) RETURN VARCHAR2
AS
l_children DBMS_XMLDOM.DOMNodeList;
l_child DBMS_XMLDOM.DOMNode;
l_text_content VARCHAR2(32767);
l_length INTEGER;
BEGIN
l_children := DBMS_XMLDOM.GetChildNodes(p_node);
l_length := DBMS_XMLDOM.GetLength(l_children);
FOR i IN 0 .. l_length - 1 LOOP
l_child := DBMS_XMLDOM.Item(l_children, i);
IF DBMS_XMLDOM.GetNodeType(l_child) IN (DBMS_XMLDOM.TEXT_NODE, DBMS_XMLDOM.CDATA_SECTION_NODE) THEN
l_text_content := l_text_content || DBMS_XMLDOM.GetNodeValue(l_child);
END IF;
END LOOP;
RETURN l_text_content;
END f_get_text_content;
/
Это простая иллюстрация того, как извлечь нужные значения из документа:
declare
vDOM dbms_xmldom.DOMDocument;
vNodes dbms_xmldom.DOMNodeList;
vXML xmltype := xmltype('<Zipcodes>
<mappings Record="4">
<STATE_ABBREVIATION>CA</STATE_ABBREVIATION>
<ZIPCODE>94301</ZIPCODE>
<CITY>Palo Alto</CITY>
</mappings>
</Zipcodes>');
begin
-- create the dom document from our example xmltype
vDOM := dbms_xmldom.newDOMDocument(vXML);
-- find all text nodes in the dom document and return them into a node list
vNodes := dbms_xslprocessor.selectNodes
(n => dbms_xmldom.makeNode(dbms_xmldom.getDocumentElement(vDOM))
,pattern => '//*[self::ZIPCODE or self::CITY]/text()'
,namespace => null
);
-- iterate through the node list
for i in 0 .. dbms_xmldom.getlength(vNodes) - 1 loop
-- output the text value of each text node in the list
dbms_output.put_line(dbms_xmldom.getNodeValue(dbms_xmldom.item(vNodes,i)));
end loop;
-- free up document resources
dbms_xmldom.freeDocument(vDOM);
end;
Вышеуказанные результаты в запрошенном выводе:
94301
Palo Alto
Замена шаблона xpath в приведенном выше примере на pattern => '//text()' приводит к выводу:
CA
94301
Palo Alto
то есть. весь текст в документе. Многие вариации на эту тему, конечно, возможны с использованием этой техники.