你提供的关于你实际在做什么的细节很少,所以恐怕我只能猜测。
我无法重现您的错误消息,但我只尝试了几件事。也许您错误地调用了 Oracle XML API?也许您尝试解析的 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 的更简单方法,there's one in a question I answered earlier。我不知道这是否会对你有所帮助,因为我对你想要达到的目标知之甚少。
最后,请不要在 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> 创建或替换目录 ora_dir 为 '/home/luke/ora_dir';
已创建目录。
我在这里使用 Linux。如果您使用的是 Windows,请随意反转斜线的方向。
在我们继续之前,让我们快速浏览一下我们将读入的 XML 文件:
SQL> 主机猫 /home/luke/ora_dir/example.xml
在 SQL*Plus 中,host 将行的其余部分发送到 shell,或者在 Windows 上为 cmd.exe。在 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,正如三个 cmets 中的最后一个所建议的那样。
引用a previous answer of mine on a similar question:
在 XML DOM 中,元素没有任何“价值”可言。元素节点包含 Text 节点作为子节点,正是这些节点包含您想要的值。
所以,换行试试
nodeval := xmldom.getNodeValue(n);
与
nodeval := xmldom.getNodeValue(xmldom.getFirstChild(n));