Получить значение элемента xml в Oracle PL SQL - PullRequest
6 голосов
/ 13 апреля 2009

Кто-нибудь знает, как извлечь значения <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 ]

12 голосов
/ 13 апреля 2009

Вам нужно изменить строку

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;
/
0 голосов
/ 13 октября 2016

Это простая иллюстрация того, как извлечь нужные значения из документа:

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

т. весь текст в документе. Конечно, с помощью этой техники возможно множество вариаций на эту тему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...