0

我正在尝试使用 xmlparser 包从 plsql 过程中读取 xml,但出现此错误

ORA-31020: 不允许该操作,原因: 不支持
ORA-06512:在“XDB.DBMS_XMLPARSER”,第 395 行
ORA-06512:在“SYS.DOMSAMPLE”,第 75 行
ORA-06512: 在第 2 行

DOMSAMPLE是我的过程名称,第 75 行没有语句,下一行包含p := xmlparser.newParser.

有人可以帮我解决这个问题。或者建议一种在plsql中读取xml的简单方法。

4

1 回答 1

0

你提供的关于你实际在做什么的细节很少,所以恐怕我只能猜测。

我无法重现您的错误消息,但我只尝试了几件事。也许您错误地调用了 Oracle XML API?也许您尝试解析的 XML 文档有些奇怪?恐怕我不知道,因为您没有向我们提供DOMSAMPLE程序的来源,也没有向我们提供您尝试解析的 XML 文档。

我不敢相信您的程序的第 75 行是空白行。这是该过程的第 75 行,还是包含该过程的文件的第 75 行?

这是一个使用DBMS_XMLPARSERand的示例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模式中创建对象。

编辑:在您的评论中,您提到您使用dbms_xmlparser.parse的是dbms_xmlparser.parseBuffer. 在最终找到可行的方法之前,我dbms_xmlparser.parse曾多次尝试并遇到相同的“无效的资源句柄或路径名”错误。以下是我设法开始工作的内容;对于您想要的东西,可能有比这更好的解决方案。

在您可以使用 Oracle 执行任何文件 I/O 之前,并且这似乎包括 using dbms_xmlparser.parse,您必须首先创建一个 Oracle '目录'。Oracle 中的目录对应于文件系统上的目录。请注意,这是运行 Oracle 数据库的机器上的文件系统。如果 XML 文件不在同一个文件系统上(例如,Oracle 数据库在服务器上,而您的 XML 文件在您的开发 PC 上),您将无法使用dbms_xmlparser.parse,除非您先将此文件传输到数据库服务器的文件系统。

我将首先创建一个与我的文件系统上的目录相对应的 Oracle 目录:

SQL> 创建或替换目录 ora_dir 为 '/home/luke/ora_dir';

已创建目录。

我在这里使用Linux。如果您使用的是 Windows,请随意反转斜线的方向。

在我们继续之前,让我们快速浏览一下我们将读入的 XML 文件:

SQL> 主机猫 /home/luke/ora_dir/example.xml
<?xml 版本="1.0" ?>
<根>
  <孩子 />
</root>

在 SQL*Plus 中,host将行的其余部分发送到 shell,或cmd.exe在 Windows 上。在 Windows 上,您还可以使用type而不是cat.

最后,这是一个读取这个 XML 文件的 PL/SQL 块:

SQL> 设置服务器输出
SQL> 声明
  2 p dbms_xmlparser.parser;
  3d dbms_xmldom.domdocument;
  4 e dbms_xmldom.dom 元素;
  5 开始
  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('标签名是' || dbms_xmldom.getTagName(e));
 12 结束;
 13 /
标签名称是根

PL/SQL 过程成功完成。

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;

正如三条评论中的最后一条所建议的那样,这显然将所有值都返回为 null。

引用我之前对类似问题的回答

在 XML DOM 中,元素没有任何“价值”可言。元素节点包含作为子节点的文本节点,正是这些节点包含您想要的值。

所以,尝试更换线路

      nodeval := xmldom.getNodeValue(n);

      nodeval := xmldom.getNodeValue(xmldom.getFirstChild(n));
于 2011-04-29T13:33:06.207 回答