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

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));
于 2011-04-29T13:33:06.207 に答える