从 plsql 过程读取 xml 时出错

发布于 2024-11-04 02:14:27 字数 374 浏览 1 评论 0原文

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

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

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

I am trying to read a xml from plsql procedure using the xmlparser package, i am getting this error

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 is my procedure name, and no statements are there at line number 75, and next line contains p := xmlparser.newParser.

Can somebody please help me in resolving this problem. Or suggest a simple way to read xml in plsql.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

怂人 2024-11-11 02:14:27

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

我无法重现您收到的错误消息,但我只尝试了一些操作。也许您错误地调用了 Oracle XML API?也许您尝试解析的 XML 文档有些奇怪?恐怕我不知道,因为您没有向我们提供您的 DOMSAMPLE 过程的源代码,也没有向我们提供您尝试解析的 XML 文档。

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

以下是使用 DBMS_XMLPARSERDBMS_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(包括使用 dbms_xmlparser.parse)之前,您必须首先创建一个 Oracle“目录”。 Oracle 中的目录对应于文件系统上的目录。请注意,这是运行 Oracle 数据库的计算机上的文件系统。如果 XML 文件不在同一文件系统上(例如,Oracle 数据库位于服务器上,而您的 XML 文件位于开发 PC 上),您将无法使用 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 将行的其余部分发送到 shell 或 cmd。 Windows 上的 exe。在 Windows 上,您还可以使用 type 而不是 cat

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

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));

You have provided scant few details about what you are actually doing, so I'm afraid I can only guess.

I cannot reproduce the error message you have, but I have only tried a few things. Perhaps you're calling the Oracle XML APIs incorrectly? Perhaps there's something odd about the XML document you're attempting to parse? I'm afraid I have no idea, since you haven't given us the source of your DOMSAMPLE procedure nor the XML document you're attempting to parse.

I cannot believe line 75 of your procedure is a blank line. Is this line 75 of the procedure, or line 75 of the file that contains the procedure?

Here's an example using DBMS_XMLPARSER and DBMS_XMLDOM. It merely reads out the name of the root element of the XML string given:

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;
/

When I run this it gives me the output Tag name is thisIsATest.

As for simpler ways to read XML, there's one in a question I answered earlier. I don't know whether that will help you, because I know very little about what you're trying to achieve.

Finally, please don't create objects in the SYS schema.

EDIT: in your comment, you mention that you're using dbms_xmlparser.parse instead of dbms_xmlparser.parseBuffer. I had a play with dbms_xmlparser.parse and hit the same 'invalid resource handle or path name' error several times before finally finding something that worked. Below is what I managed to get working; there may well be a better solution to what you want than this.

Before you can do any file I/O with Oracle, and that appears to include using dbms_xmlparser.parse, you must first create an Oracle 'directory'. Directories in Oracle correspond to directories on the filesystem. Note that this is the filesystem on the machine on which the Oracle database runs. If the XML file isn't on the same filesystem (e.g. the Oracle database is on a server and your XML file is on your development PC), you won't be able to use dbms_xmlparser.parse, unless you first transfer this file to a directory on the database server's filesystem.

I'll start by creating a Oracle directory corresponding to a directory on my filesystem:

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

Directory created.

I'm using Linux here. If you're using Windows, feel free to reverse the direction of the slashes.

Before we go any further, let's take a quick look at the XML file we'll read in:

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

In SQL*Plus, host sends the rest of the line to the shell, or cmd.exe on Windows. On Windows you'd also use type instead of cat.

Finally, here's a PL/SQL block that reads this XML file:

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>

The only difference between this block and the one further up is that the line that called dbms_xmlparser.parseBuffer has been replaced with two lines. The first of these two lines calls dbms_xmlparser.setBaseDir to set a base directory for the parser, and the second calls dbms_xmlparser.parse using a filename relative to this directory.

EDIT 2: Your code, which wasn't working quite as you had hoped, and which you edited into my answer, is as follows:

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;

This apparently was returning all the values as null, as suggested by the last of the three comments.

To quote a previous answer of mine on a similar question:

In XML DOM, elements don't have any 'value' to speak of. Element nodes contain Text nodes as children, and it is these nodes that contain the values you want.

So, try replacing the line

      nodeval := xmldom.getNodeValue(n);

with

      nodeval := xmldom.getNodeValue(xmldom.getFirstChild(n));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文