ошибка чтения xml из процедуры plsql - PullRequest
0 голосов
/ 29 апреля 2011

Я пытаюсь прочитать xml из процедуры plsql, используя пакет xmlparser, я получаю эту ошибку

ORA-31020: The operation is not allowed, Reason: Not supported
ORA-06512: at "XDB.DBMS_XMLPARSER", line 395
ORA-06512: at "SYS.DOMSAMPLE", line 75
ORA-06512: at line 2

DOMSAMPLE - это имя моей процедуры, и в строке № 75 нет операторов, а следующая строка содержит p := xmlparser.newParser.

Может кто-нибудь помочь мне в решении этой проблемы. Или предложите простой способ чтения XML в plsql.

1 Ответ

0 голосов
/ 29 апреля 2011

Вы предоставили мало информации о том, что вы на самом деле делаете, так что, боюсь, я могу только догадываться.

Я не могу воспроизвести сообщение об ошибке, которое у вас есть, но я пробовал только несколько вещей. Возможно, вы неправильно называете API Oracle XML? Возможно, есть что-то странное в XML-документе, который вы пытаетесь проанализировать? Боюсь, я понятия не имею, поскольку вы не указали нам ни источник вашей DOMSAMPLE процедуры, ни XML-документ, который вы пытаетесь проанализировать.

Я не могу поверить, что строка 75 вашей процедуры - пустая строка. Это строка 75 процедуры или строка 75 файла, содержащего процедуру?

Вот пример использования DBMS_XMLPARSER и DBMS_XMLDOM. Он просто считывает имя корневого элемента заданной строки XML:

SET SERVEROUTPUT ON;

DECLARE
   p    dbms_xmlparser.parser;
   d    dbms_xmldom.domdocument;
   e    dbms_xmldom.domelement;
BEGIN
   p := dbms_xmlparser.newParser;
   dbms_xmlparser.parseBuffer(p, '<thisIsATest />');
   d := dbms_xmlparser.getDocument(p);
   e := dbms_xmldom.getDocumentElement(d);
   dbms_output.put_line('Tag name is ' || dbms_xmldom.getTagName(e));
END;
/

Когда я запускаю это, это дает мне вывод Tag name is thisIsATest.

Что касается более простых способов чтения XML, есть один вопрос, на который я ответил ранее . Я не знаю, поможет ли это вам, потому что я очень мало знаю о том, чего вы пытаетесь достичь.

Наконец, не создавайте объекты в схеме SYS.

EDIT : в своем комментарии вы упоминаете, что используете dbms_xmlparser.parse вместо dbms_xmlparser.parseBuffer. Я поиграл с dbms_xmlparser.parse и несколько раз нажал одну и ту же ошибку «недопустимый дескриптор ресурса или имя пути», прежде чем наконец-то нашел что-то, что сработало. Ниже то, что мне удалось получить работу; вполне может быть лучшее решение того, что вы хотите, чем это.

Прежде чем вы сможете выполнить какой-либо файловый ввод-вывод с Oracle, и, похоже, это включает использование dbms_xmlparser.parse, вы должны сначала создать «каталог» Oracle. Каталоги в Oracle соответствуют каталогам в файловой системе. Обратите внимание, что это файловая система на компьютере, на котором работает база данных Oracle. Если файл XML не находится в той же файловой системе (например, база данных Oracle находится на сервере, а файл XML находится на компьютере разработчика), вы не сможете использовать dbms_xmlparser.parse, если только вы сначала не перенесете этот файл в каталог в файловой системе сервера базы данных.

Я начну с создания каталога Oracle, соответствующего каталогу в моей файловой системе:

SQL> create or replace directory ora_dir as '/home/luke/ora_dir';

Directory created.

Я использую Linux здесь. Если вы используете Windows, смело меняйте направление слеша.

Прежде чем идти дальше, давайте кратко рассмотрим XML-файл, в котором мы читаем:

SQL> host cat /home/luke/ora_dir/example.xml
<?xml version="1.0" ?>
<root>
  <child />
</root>

В SQL * Plus host отправляет остаток строки в оболочку или cmd.exe в Windows. В Windows вы бы также использовали type вместо cat.

Наконец, вот блок PL / SQL, который читает этот XML-файл:

SQL> set serveroutput on
SQL> DECLARE
  2     p    dbms_xmlparser.parser;
  3     d    dbms_xmldom.domdocument;
  4     e    dbms_xmldom.domelement;
  5  BEGIN
  6     p := dbms_xmlparser.newParser;
  7     dbms_xmlparser.setBaseDir(p, 'ORA_DIR');
  8     dbms_xmlparser.parse(p, 'example.xml');
  9     d := dbms_xmlparser.getDocument(p);
 10     e := dbms_xmldom.getDocumentElement(d);
 11     dbms_output.put_line('Tag name is ' || dbms_xmldom.getTagName(e));
 12  END;
 13  /
Tag name is root

PL/SQL procedure successfully completed.

SQL>

Единственное различие между этим блоком и тем, что дальше, состоит в том, что строка, которая называется dbms_xmlparser.parseBuffer, была заменена на две строки. Первая из этих двух строк вызывает dbms_xmlparser.setBaseDir, чтобы установить базовый каталог для анализатора, а вторая вызывает dbms_xmlparser.parse, используя имя файла относительно этого каталога.

РЕДАКТИРОВАТЬ 2: Ваш код, который работал не совсем так, как вы надеялись, и который вы отредактировали в моем ответе, выглядит следующим образом:

create or replace procedure printElements(doc xmldom.DOMDocument) is
nl xmldom.DOMNodeList;
len number;
n xmldom.DOMNode;
e xmldom.DOMElement;
nodeval varchar2(100);
begin
   -- get all elements
   nl := xmldom.getElementsByTagName(doc, '*');
   len := xmldom.getLength(nl);   
   -- loop through elements
   for i in 0..len-1 loop
      n := xmldom.item(nl, i);
      e := xmldom.makeElement(n => n);
      dbms_output.put(xmldom.getNodeName(n) || ' ');
      nodeval := xmldom.getNodeValue(n);
      -- here nodeval i am getting as null, what mistake am doing?
      dbms_output.put_line('  Value: '|| nodeval );

   end loop;

   dbms_output.put_line('');
end printElements;

Это, по-видимому, возвращало все значения как нулевые, как было предложено последним из трех комментариев.

Цитировать мой предыдущий ответ на аналогичный вопрос :

В XML DOM элементы не имеют никакого «значения», о котором можно говорить. Узлы элемента содержат текстовые узлы как дочерние элементы, и именно эти узлы содержат нужные значения.

Итак, попробуйте заменить строку

      nodeval := xmldom.getNodeValue(n);

с

      nodeval := xmldom.getNodeValue(xmldom.getFirstChild(n));
...